on 906eb68 help sign in
.github/workflows/tests.ymldeleted−44
since splitsnapshots
unifiedsplit
@@ -1,44 +0,0 @@
1−name: Tests
2−
3−on:
4− pull_request:
5− push:
6− branches:
7− - master
8−
9−jobs:
10− build:
11− name: CI
12− runs-on: ${{ matrix.os }}
13− strategy:
14− fail-fast: false
15− matrix:
16− os: [ubuntu-latest, macos-latest, windows-latest]
17− resolver: [nightly, lts-22, lts-20, lts-17]
18− exclude:
19− - os: windows-latest
20− resolver: lts-15
21− - os: windows-latest
22− resolver: nightly
23−
24− steps:
25− - name: Clone project
26− uses: actions/checkout@v3
27−
28− - name: Cache dependencies
29− if: ${{ runner.os != 'Windows' }}
30− # Andreas Abel, 2023-06-10, switching off caching on Windows since ~/.stack is not the correct path here.
31− uses: actions/cache@v3
32− with:
33− path: ~/.stack
34− #NB: This path is not valid on Windows
35− key: ${{ runner.os }}-${{ matrix.resolver }}-${{ hashFiles('stack.yaml') }}
36− restore-keys: |
37− ${{ runner.os }}-${{ matrix.resolver }}-
38−
39− - name: Build and run tests
40− shell: bash
41− run: |
42− set -ex
43− stack upgrade || curl -sSL https://get.haskellstack.org/ | sh -s - -f
44− stack test --bench --no-run-benchmarks --haddock --no-haddock-deps --no-terminal --resolver=${{ matrix.resolver }}
.gitignore−9
@@ -1,11 +1,2 @@
1dist
1dist
2*.swp
2*.swp
3−cabal-dev/
4−.cabal-sandbox/
5−cabal.sandbox.config
6−.stack-work/
7−*~
8−tarballs/
9−.dir-locals.el
10−*#
11−stack.yaml.lock
.gitmodulesdeleted−3
@@ -1,3 +0,0 @@
1−[submodule "vendor/libyaml"]
2− path = libyaml/vendor/libyaml
3− url = https://github.com/snoyberg/libyaml
libyaml/LICENSE → LICENSErenamed

The content is the same.

READMEnew file+1
@@ -0,0 +1 @@
1+Support for serialising Haskell to and from Yaml.
README.mddeleted−23
@@ -1,23 +0,0 @@
1−# YAML Haskell Library
2−
3−[![Build Status](https://dev.azure.com/snoyberg/yaml/_apis/build/status/snoyberg.yaml?branchName=master)](https://dev.azure.com/snoyberg/yaml/_build/latest?definitionId=7&branchName=master)
4−
5−This project contains two haskell packages: `yaml` for higher-level parsing and writing of yaml documents, and `libyaml`
6−for lower-level event-based streaming.
7−
8−## `yaml` Package
9−
10−`yaml` provides a high-level interface based around the JSON datatypes provided by the `aeson` package. This allows
11−using JSON and YAML interchangeably in your code with the `aeson` typeclasses. See the
12−[yaml README](https://github.com/snoyberg/yaml/tree/master/yaml/README.md) for more details.
13−
14−## `libyaml` Package
15−
16−`libyaml` is a wrapper over the libyaml C library (and includes the source so no external library is needed). It is an
17−event-based streaming API. See the [libyaml README](https://github.com/snoyberg/yaml/tree/master/libyaml/README.md) for
18−more details.
19−
20−## License
21−
22−This project is licensed with the BSD 3-Clause license. Copies of the license can be found in both the `yaml` and
23−`libyaml` subdirectories
yaml/Setup.lhs → Setup.lhsrenamed

Only the mode changed.

Text/Libyaml.hsnew file+586
@@ -0,0 +1,586 @@
1+{-# LANGUAGE EmptyDataDecls #-}
2+{-# LANGUAGE ForeignFunctionInterface #-}
3+{-# LANGUAGE DeriveDataTypeable #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE PackageImports #-}
8+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9+{-# LANGUAGE RankNTypes #-}
10+{-# LANGUAGE CPP #-}
11+
12+module Text.Libyaml
13+ ( -- * The event stream
14+ Event (..)
15+ , Style (..)
16+ , Tag (..)
17+ , AnchorName
18+ , Anchor
19+ -- * Encoding and decoding
20+ , encode
21+ , decode
22+ , encodeFile
23+ , decodeFile
24+ -- * Exception
25+ , YamlException (..)
26+ ) where
27+
28+import qualified Data.ByteString.Internal as B
29+import qualified Data.ByteString.Char8 as B8
30+import qualified Data.ByteString
31+import qualified Data.ByteString.Unsafe as BU
32+import Data.ByteString (ByteString, packCStringLen)
33+import Control.Monad
34+import Foreign.C
35+import Foreign.Ptr
36+import Foreign.ForeignPtr
37+import Foreign.Marshal.Alloc
38+import Data.Data
39+
40+import Control.Monad.IO.Class
41+import Control.Monad.Trans.Class (lift)
42+
43+import Control.Exception (throwIO, Exception)
44+import Data.Enumerator
45+import Control.Applicative
46+import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO, finally)
47+
48+data Event =
49+ EventStreamStart
50+ | EventStreamEnd
51+ | EventDocumentStart
52+ | EventDocumentEnd
53+ | EventAlias !AnchorName
54+ | EventScalar !ByteString !Tag !Style !Anchor
55+ | EventSequenceStart !Anchor
56+ | EventSequenceEnd
57+ | EventMappingStart !Anchor
58+ | EventMappingEnd
59+ deriving (Show, Eq)
60+
61+data Style = Any
62+ | Plain
63+ | SingleQuoted
64+ | DoubleQuoted
65+ | Literal
66+ | Folded
67+ deriving (Show, Read, Eq, Enum, Bounded, Ord, Data, Typeable)
68+
69+data Tag = StrTag
70+ | FloatTag
71+ | NullTag
72+ | BoolTag
73+ | SetTag
74+ | IntTag
75+ | SeqTag
76+ | MapTag
77+ | UriTag String
78+ | NoTag
79+ deriving (Show, Eq, Read, Data, Typeable)
80+
81+type AnchorName = String
82+type Anchor = Maybe AnchorName
83+
84+tagToString :: Tag -> String
85+tagToString StrTag = "tag:yaml.org,2002:str"
86+tagToString FloatTag = "tag:yaml.org,2002:float"
87+tagToString NullTag = "tag:yaml.org,2002:null"
88+tagToString BoolTag = "tag:yaml.org,2002:bool"
89+tagToString SetTag = "tag:yaml.org,2002:set"
90+tagToString IntTag = "tag:yaml.org,2002:int"
91+tagToString SeqTag = "tag:yaml.org,2002:seq"
92+tagToString MapTag = "tag:yaml.org,2002:map"
93+tagToString (UriTag s) = s
94+tagToString NoTag = ""
95+
96+bsToTag :: ByteString -> Tag
97+bsToTag = stringToTag . B8.unpack
98+
99+stringToTag :: String -> Tag
100+stringToTag "tag:yaml.org,2002:str" = StrTag
101+stringToTag "tag:yaml.org,2002:float" = FloatTag
102+stringToTag "tag:yaml.org,2002:null" = NullTag
103+stringToTag "tag:yaml.org,2002:bool" = BoolTag
104+stringToTag "tag:yaml.org,2002:set" = SetTag
105+stringToTag "tag:yaml.org,2002:int" = IntTag
106+stringToTag "tag:yaml.org,2002:seq" = SeqTag
107+stringToTag "tag:yaml.org,2002:map" = MapTag
108+stringToTag "" = NoTag
109+stringToTag s = UriTag s
110+
111+data ParserStruct
112+type Parser = Ptr ParserStruct
113+parserSize :: Int
114+parserSize = 480
115+
116+data EventRawStruct
117+type EventRaw = Ptr EventRawStruct
118+eventSize :: Int
119+eventSize = 104
120+
121+foreign import ccall unsafe "yaml_parser_initialize"
122+ c_yaml_parser_initialize :: Parser -> IO CInt
123+
124+foreign import ccall unsafe "yaml_parser_delete"
125+ c_yaml_parser_delete :: Parser -> IO ()
126+
127+foreign import ccall unsafe "yaml_parser_set_input_string"
128+ c_yaml_parser_set_input_string :: Parser
129+ -> Ptr CUChar
130+ -> CULong
131+ -> IO ()
132+
133+foreign import ccall unsafe "yaml_parser_set_input_file"
134+ c_yaml_parser_set_input_file :: Parser
135+ -> File
136+ -> IO ()
137+
138+data FileStruct
139+type File = Ptr FileStruct
140+
141+foreign import ccall unsafe "fopen"
142+ c_fopen :: Ptr CChar
143+ -> Ptr CChar
144+ -> IO File
145+
146+foreign import ccall unsafe "fclose"
147+ c_fclose :: File
148+ -> IO ()
149+
150+withForeignPtr' :: MonadIO m => ForeignPtr a -> (Ptr a -> m b) -> m b
151+withForeignPtr' fp f = do
152+ r <- f $ unsafeForeignPtrToPtr fp
153+ liftIO $ touchForeignPtr fp
154+ return r
155+
156+foreign import ccall unsafe "yaml_parser_parse"
157+ c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
158+
159+foreign import ccall unsafe "yaml_event_delete"
160+ c_yaml_event_delete :: EventRaw -> IO ()
161+
162+foreign import ccall "get_parser_error_problem"
163+ c_get_parser_error_problem :: Parser -> IO (Ptr CUChar)
164+
165+foreign import ccall "get_parser_error_context"
166+ c_get_parser_error_context :: Parser -> IO (Ptr CUChar)
167+
168+foreign import ccall unsafe "get_parser_error_offset"
169+ c_get_parser_error_offset :: Parser -> IO CULong
170+
171+makeString :: MonadIO m => (a -> m (Ptr CUChar)) -> a -> m String
172+makeString f a = do
173+ cchar <- castPtr `liftM` f a
174+ if cchar == nullPtr
175+ then return ""
176+ else liftIO $ peekCString cchar
177+
178+data EventType = YamlNoEvent
179+ | YamlStreamStartEvent
180+ | YamlStreamEndEvent
181+ | YamlDocumentStartEvent
182+ | YamlDocumentEndEvent
183+ | YamlAliasEvent
184+ | YamlScalarEvent
185+ | YamlSequenceStartEvent
186+ | YamlSequenceEndEvent
187+ | YamlMappingStartEvent
188+ | YamlMappingEndEvent
189+ deriving (Enum,Show)
190+
191+foreign import ccall unsafe "get_event_type"
192+ c_get_event_type :: EventRaw -> IO CInt
193+
194+foreign import ccall unsafe "get_scalar_value"
195+ c_get_scalar_value :: EventRaw -> IO (Ptr CUChar)
196+
197+foreign import ccall unsafe "get_scalar_length"
198+ c_get_scalar_length :: EventRaw -> IO CULong
199+
200+foreign import ccall unsafe "get_scalar_tag"
201+ c_get_scalar_tag :: EventRaw -> IO (Ptr CUChar)
202+
203+foreign import ccall unsafe "get_scalar_tag_len"
204+ c_get_scalar_tag_len :: EventRaw -> IO CULong
205+
206+foreign import ccall unsafe "get_scalar_style"
207+ c_get_scalar_style :: EventRaw -> IO CInt
208+
209+foreign import ccall unsafe "get_scalar_anchor"
210+ c_get_scalar_anchor :: EventRaw -> IO CString
211+
212+foreign import ccall unsafe "get_sequence_start_anchor"
213+ c_get_sequence_start_anchor :: EventRaw -> IO CString
214+
215+foreign import ccall unsafe "get_mapping_start_anchor"
216+ c_get_mapping_start_anchor :: EventRaw -> IO CString
217+
218+foreign import ccall unsafe "get_alias_anchor"
219+ c_get_alias_anchor :: EventRaw -> IO CString
220+
221+getEvent :: EventRaw -> IO (Maybe Event)
222+getEvent er = do
223+ et <- c_get_event_type er
224+ case toEnum $ fromEnum et of
225+ YamlNoEvent -> return Nothing
226+ YamlStreamStartEvent -> return $ Just EventStreamStart
227+ YamlStreamEndEvent -> return $ Just EventStreamEnd
228+ YamlDocumentStartEvent -> return $ Just EventDocumentStart
229+ YamlDocumentEndEvent -> return $ Just EventDocumentEnd
230+ YamlAliasEvent -> do
231+ yanchor <- c_get_alias_anchor er
232+ anchor <- if yanchor == nullPtr
233+ then error "got YamlAliasEvent with empty anchor"
234+ else peekCString yanchor
235+ return $ Just $ EventAlias anchor
236+ YamlScalarEvent -> do
237+ yvalue <- c_get_scalar_value er
238+ ylen <- c_get_scalar_length er
239+ ytag <- c_get_scalar_tag er
240+ ytag_len <- c_get_scalar_tag_len er
241+ ystyle <- c_get_scalar_style er
242+ let ytag_len' = fromEnum ytag_len
243+ let yvalue' = castPtr yvalue
244+ let ytag' = castPtr ytag
245+ let ylen' = fromEnum ylen
246+ bs <- packCStringLen (yvalue', ylen')
247+ tagbs <-
248+ if ytag_len' == 0
249+ then return Data.ByteString.empty
250+ else packCStringLen (ytag', ytag_len')
251+ let style = toEnum $ fromEnum ystyle
252+ yanchor <- c_get_scalar_anchor er
253+ anchor <- if yanchor == nullPtr
254+ then return Nothing
255+ else fmap Just $ peekCString yanchor
256+ return $ Just $ EventScalar bs (bsToTag tagbs) style anchor
257+ YamlSequenceStartEvent -> do
258+ yanchor <- c_get_sequence_start_anchor er
259+ anchor <- if yanchor == nullPtr
260+ then return Nothing
261+ else fmap Just $ peekCString yanchor
262+ return $ Just $ EventSequenceStart anchor
263+ YamlSequenceEndEvent -> return $ Just EventSequenceEnd
264+ YamlMappingStartEvent -> do
265+ yanchor <- c_get_mapping_start_anchor er
266+ anchor <- if yanchor == nullPtr
267+ then return Nothing
268+ else fmap Just $ peekCString yanchor
269+ return $ Just $ EventMappingStart anchor
270+ YamlMappingEndEvent -> return $ Just EventMappingEnd
271+
272+-- Emitter
273+
274+data EmitterStruct
275+type Emitter = Ptr EmitterStruct
276+emitterSize :: Int
277+emitterSize = 432
278+
279+foreign import ccall unsafe "yaml_emitter_initialize"
280+ c_yaml_emitter_initialize :: Emitter -> IO CInt
281+
282+foreign import ccall unsafe "yaml_emitter_delete"
283+ c_yaml_emitter_delete :: Emitter -> IO ()
284+
285+data BufferStruct
286+type Buffer = Ptr BufferStruct
287+bufferSize :: Int
288+bufferSize = 16
289+
290+foreign import ccall unsafe "buffer_init"
291+ c_buffer_init :: Buffer -> IO ()
292+
293+foreign import ccall unsafe "get_buffer_buff"
294+ c_get_buffer_buff :: Buffer -> IO (Ptr CUChar)
295+
296+foreign import ccall unsafe "get_buffer_used"
297+ c_get_buffer_used :: Buffer -> IO CULong
298+
299+foreign import ccall unsafe "my_emitter_set_output"
300+ c_my_emitter_set_output :: Emitter -> Buffer -> IO ()
301+
302+foreign import ccall unsafe "yaml_emitter_set_output_file"
303+ c_yaml_emitter_set_output_file :: Emitter -> File -> IO ()
304+
305+foreign import ccall unsafe "yaml_emitter_emit"
306+ c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
307+
308+foreign import ccall unsafe "yaml_stream_start_event_initialize"
309+ c_yaml_stream_start_event_initialize :: EventRaw -> CInt -> IO CInt
310+
311+foreign import ccall unsafe "yaml_stream_end_event_initialize"
312+ c_yaml_stream_end_event_initialize :: EventRaw -> IO CInt
313+
314+foreign import ccall unsafe "yaml_scalar_event_initialize"
315+ c_yaml_scalar_event_initialize
316+ :: EventRaw
317+ -> Ptr CUChar -- anchor
318+ -> Ptr CUChar -- tag
319+ -> Ptr CUChar -- value
320+ -> CInt -- length
321+ -> CInt -- plain_implicit
322+ -> CInt -- quoted_implicit
323+ -> CInt -- style
324+ -> IO CInt
325+
326+foreign import ccall unsafe "simple_document_start"
327+ c_simple_document_start :: EventRaw -> IO CInt
328+
329+foreign import ccall unsafe "yaml_document_end_event_initialize"
330+ c_yaml_document_end_event_initialize :: EventRaw -> CInt -> IO CInt
331+
332+foreign import ccall unsafe "yaml_sequence_start_event_initialize"
333+ c_yaml_sequence_start_event_initialize
334+ :: EventRaw
335+ -> Ptr CUChar
336+ -> Ptr CUChar
337+ -> CInt
338+ -> CInt
339+ -> IO CInt
340+
341+foreign import ccall unsafe "yaml_sequence_end_event_initialize"
342+ c_yaml_sequence_end_event_initialize :: EventRaw -> IO CInt
343+
344+foreign import ccall unsafe "yaml_mapping_start_event_initialize"
345+ c_yaml_mapping_start_event_initialize
346+ :: EventRaw
347+ -> Ptr CUChar
348+ -> Ptr CUChar
349+ -> CInt
350+ -> CInt
351+ -> IO CInt
352+
353+foreign import ccall unsafe "yaml_mapping_end_event_initialize"
354+ c_yaml_mapping_end_event_initialize :: EventRaw -> IO CInt
355+
356+foreign import ccall unsafe "yaml_alias_event_initialize"
357+ c_yaml_alias_event_initialize
358+ :: EventRaw
359+ -> Ptr CUChar
360+ -> IO CInt
361+
362+toEventRaw :: Event -> (EventRaw -> IO a) -> IO a
363+toEventRaw e f = allocaBytes eventSize $ \er -> do
364+ ret <- case e of
365+ EventStreamStart ->
366+ c_yaml_stream_start_event_initialize
367+ er
368+ 0 -- YAML_ANY_ENCODING
369+ EventStreamEnd ->
370+ c_yaml_stream_end_event_initialize er
371+ EventDocumentStart ->
372+ c_simple_document_start er
373+ EventDocumentEnd ->
374+ c_yaml_document_end_event_initialize er 1
375+ EventScalar bs thetag style anchor -> do
376+ BU.unsafeUseAsCStringLen bs $ \(value, len) -> do
377+ let value' = castPtr value :: Ptr CUChar
378+ len' = fromIntegral len :: CInt
379+ let thetag' = tagToString thetag
380+ withCString thetag' $ \tag' -> do
381+ let style' = toEnum $ fromEnum style
382+ tagP = castPtr tag'
383+ qi = if null thetag' then 1 else 0
384+ case anchor of
385+ Nothing ->
386+ c_yaml_scalar_event_initialize
387+ er
388+ nullPtr -- anchor
389+ tagP -- tag
390+ value' -- value
391+ len' -- length
392+ 0 -- plain_implicit
393+ qi -- quoted_implicit
394+ style' -- style
395+ Just anchor' ->
396+ withCString anchor' $ \anchorP' -> do
397+ let anchorP = castPtr anchorP'
398+ c_yaml_scalar_event_initialize
399+ er
400+ anchorP -- anchor
401+ tagP -- tag
402+ value' -- value
403+ len' -- length
404+ 0 -- plain_implicit
405+ qi -- quoted_implicit
406+ style' -- style
407+ EventSequenceStart Nothing ->
408+ c_yaml_sequence_start_event_initialize
409+ er
410+ nullPtr
411+ nullPtr
412+ 1
413+ 0 -- YAML_ANY_SEQUENCE_STYLE
414+ EventSequenceStart (Just anchor) ->
415+ withCString anchor $ \anchor' -> do
416+ let anchorP = castPtr anchor'
417+ c_yaml_sequence_start_event_initialize
418+ er
419+ anchorP
420+ nullPtr
421+ 1
422+ 0 -- YAML_ANY_SEQUENCE_STYLE
423+ EventSequenceEnd ->
424+ c_yaml_sequence_end_event_initialize er
425+ EventMappingStart Nothing ->
426+ c_yaml_mapping_start_event_initialize
427+ er
428+ nullPtr
429+ nullPtr
430+ 1
431+ 0 -- YAML_ANY_SEQUENCE_STYLE
432+ EventMappingStart (Just anchor) ->
433+ withCString anchor $ \anchor' -> do
434+ let anchorP = castPtr anchor'
435+ c_yaml_mapping_start_event_initialize
436+ er
437+ anchorP
438+ nullPtr
439+ 1
440+ 0 -- YAML_ANY_SEQUENCE_STYLE
441+ EventMappingEnd ->
442+ c_yaml_mapping_end_event_initialize er
443+ EventAlias anchor ->
444+ withCString anchor $ \anchorP' -> do
445+ let anchorP = castPtr anchorP'
446+ c_yaml_alias_event_initialize
447+ er
448+ anchorP
449+ unless (ret == 1) $ throwIO $ ToEventRawException ret
450+ f er
451+
452+newtype ToEventRawException = ToEventRawException CInt
453+ deriving (Show, Typeable)
454+instance Exception ToEventRawException
455+
456+decode :: MonadCatchIO m => B.ByteString -> Enumerator Event m a
457+decode bs i = do
458+ fp <- liftIO $ mallocForeignPtrBytes parserSize
459+ res <- liftIO $ withForeignPtr fp c_yaml_parser_initialize
460+ a <-
461+ if (res == 0)
462+ then throwError $ YamlException "Yaml out of memory"
463+ else do -- NOTE: can't replace the following with unsafeUseAsCString
464+ -- since it must run in a MonadIO
465+ let (fptr, offset, len) = B.toForeignPtr bs
466+ withForeignPtr' fptr $ \ptr -> do
467+ let ptr' = castPtr ptr `plusPtr` offset
468+ len' = fromIntegral len
469+ liftIO $ withForeignPtr fp $ \p ->
470+ c_yaml_parser_set_input_string p ptr' len'
471+ runParser fp i
472+ liftIO $ withForeignPtr fp c_yaml_parser_delete -- FIXME finally
473+ return a
474+
475+decodeFile :: MonadIO m => FilePath -> Enumerator Event m a
476+decodeFile file i = do
477+ fp <- liftIO $ mallocForeignPtrBytes parserSize
478+ res <- liftIO $ withForeignPtr fp c_yaml_parser_initialize
479+ a <-
480+ if res == 0
481+ then throwError $ YamlException "Yaml out of memory"
482+ else do
483+ file' <- liftIO
484+ $ withCString file $ \file' -> withCString "r" $ \r' ->
485+ c_fopen file' r'
486+ if (file' == nullPtr)
487+ then throwError $ YamlException
488+ $ "Yaml file not found: " ++ file
489+ else do
490+ liftIO $ withForeignPtr fp $ \p ->
491+ c_yaml_parser_set_input_file p file'
492+ a <- runParser fp i
493+ -- FIXME finally
494+ liftIO $ c_fclose file'
495+ liftIO $ withForeignPtr fp c_yaml_parser_delete
496+ return a
497+ liftIO $ withForeignPtr fp c_yaml_parser_delete -- FIXME finally
498+ return a
499+
500+runParser :: MonadIO m
501+ => ForeignPtr ParserStruct
502+ -> Enumerator Event m a
503+runParser fp (Continue k) = do
504+ e <- liftIO $ withForeignPtr fp parserParseOne'
505+ case e of
506+ Left err -> throwError $ YamlException err
507+ Right Nothing -> continue k
508+ Right (Just ev) -> do
509+ step' <- lift $ runIteratee $ k $ Chunks [ev]
510+ runParser fp step'
511+runParser _ step = returnI step
512+
513+parserParseOne' :: Parser
514+ -> IO (Either String (Maybe Event))
515+parserParseOne' parser = allocaBytes eventSize $ \er -> do
516+ res <- liftIO $ c_yaml_parser_parse parser er
517+ flip finally (c_yaml_event_delete er) $
518+ if res == 0
519+ then do
520+ problem <- makeString c_get_parser_error_problem parser
521+ context <- makeString c_get_parser_error_context parser
522+ offset <- c_get_parser_error_offset parser
523+ return $ Left $ concat
524+ [ "YAML parse error: "
525+ , problem
526+ , "\nContext: "
527+ , context
528+ , "\nOffset: "
529+ , show offset
530+ , "\n"
531+ ]
532+ else liftIO $ Right <$> getEvent er
533+
534+encode :: MonadIO m => Iteratee Event m B.ByteString
535+encode = do
536+ fp <- liftIO $ mallocForeignPtrBytes emitterSize
537+ res <- liftIO $ withForeignPtr fp c_yaml_emitter_initialize
538+ when (res == 0) $ throwError
539+ $ YamlException "c_yaml_emitter_initialize failed"
540+ buf <- liftIO $ mallocForeignPtrBytes bufferSize
541+ liftIO $ withForeignPtr buf c_buffer_init
542+ liftIO $ withForeignPtr fp $
543+ \emitter -> withForeignPtr buf $
544+ \b -> c_my_emitter_set_output emitter b
545+ runEmitter (go buf) fp
546+ where
547+ go buf = withForeignPtr buf $ \b -> do
548+ ptr' <- c_get_buffer_buff b
549+ len <- c_get_buffer_used b
550+ fptr <- newForeignPtr_ $ castPtr ptr'
551+ return $ B.fromForeignPtr fptr 0 $ fromIntegral len
552+
553+encodeFile :: MonadIO m
554+ => FilePath
555+ -> Iteratee Event m ()
556+encodeFile filePath = do
557+ fp <- liftIO $ mallocForeignPtrBytes emitterSize
558+ res <- liftIO $ withForeignPtr fp c_yaml_emitter_initialize
559+ when (res == 0) $ throwError
560+ $ YamlException "c_yaml_emitter_initialize failed"
561+ file <- liftIO $ withCString filePath $
562+ \filePath' -> withCString "w" $
563+ \w' -> c_fopen filePath' w'
564+ when (file == nullPtr) $ throwError
565+ $ YamlException $ "could not open file for write: " ++ filePath
566+ liftIO $ withForeignPtr fp $ flip c_yaml_emitter_set_output_file file
567+ runEmitter (c_fclose file) fp
568+
569+runEmitter :: MonadIO m
570+ => IO a
571+ -> ForeignPtr EmitterStruct
572+ -> Iteratee Event m a
573+runEmitter close fp = continue go
574+ where
575+ go EOF = do
576+ liftIO $ withForeignPtr fp c_yaml_emitter_delete
577+ a <- liftIO close
578+ yield a EOF
579+ go (Chunks c) = do
580+ liftIO $ withForeignPtr fp $ \emitter ->
581+ mapM_ (\e -> toEventRaw e $ c_yaml_emitter_emit emitter) c
582+ continue go
583+
584+data YamlException = YamlException String
585+ deriving (Show, Typeable)
586+instance Exception YamlException
c/api.cnew file+1390
@@ -0,0 +1,1390 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * Get the library version.
6+ */
7+
8+YAML_DECLARE(const char *)
9+yaml_get_version_string(void)
10+{
11+ return YAML_VERSION_STRING;
12+}
13+
14+/*
15+ * Get the library version numbers.
16+ */
17+
18+YAML_DECLARE(void)
19+yaml_get_version(int *major, int *minor, int *patch)
20+{
21+ *major = YAML_VERSION_MAJOR;
22+ *minor = YAML_VERSION_MINOR;
23+ *patch = YAML_VERSION_PATCH;
24+}
25+
26+/*
27+ * Allocate a dynamic memory block.
28+ */
29+
30+YAML_DECLARE(void *)
31+yaml_malloc(size_t size)
32+{
33+ return malloc(size ? size : 1);
34+}
35+
36+/*
37+ * Reallocate a dynamic memory block.
38+ */
39+
40+YAML_DECLARE(void *)
41+yaml_realloc(void *ptr, size_t size)
42+{
43+ return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
44+}
45+
46+/*
47+ * Free a dynamic memory block.
48+ */
49+
50+YAML_DECLARE(void)
51+yaml_free(void *ptr)
52+{
53+ if (ptr) free(ptr);
54+}
55+
56+/*
57+ * Duplicate a string.
58+ */
59+
60+YAML_DECLARE(yaml_char_t *)
61+yaml_strdup(const yaml_char_t *str)
62+{
63+ if (!str)
64+ return NULL;
65+
66+ return (yaml_char_t *)strdup((char *)str);
67+}
68+
69+/*
70+ * Extend a string.
71+ */
72+
73+YAML_DECLARE(int)
74+yaml_string_extend(yaml_char_t **start,
75+ yaml_char_t **pointer, yaml_char_t **end)
76+{
77+ yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2);
78+
79+ if (!new_start) return 0;
80+
81+ memset(new_start + (*end - *start), 0, *end - *start);
82+
83+ *pointer = new_start + (*pointer - *start);
84+ *end = new_start + (*end - *start)*2;
85+ *start = new_start;
86+
87+ return 1;
88+}
89+
90+/*
91+ * Append a string B to a string A.
92+ */
93+
94+YAML_DECLARE(int)
95+yaml_string_join(
96+ yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
97+ yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
98+{
99+ if (*b_start == *b_pointer)
100+ return 1;
101+
102+ while (*a_end - *a_pointer <= *b_pointer - *b_start) {
103+ if (!yaml_string_extend(a_start, a_pointer, a_end))
104+ return 0;
105+ }
106+
107+ memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
108+ *a_pointer += *b_pointer - *b_start;
109+
110+ return 1;
111+}
112+
113+/*
114+ * Extend a stack.
115+ */
116+
117+YAML_DECLARE(int)
118+yaml_stack_extend(void **start, void **top, void **end)
119+{
120+ void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
121+
122+ if (!new_start) return 0;
123+
124+ *top = (char *)new_start + ((char *)*top - (char *)*start);
125+ *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
126+ *start = new_start;
127+
128+ return 1;
129+}
130+
131+/*
132+ * Extend or move a queue.
133+ */
134+
135+YAML_DECLARE(int)
136+yaml_queue_extend(void **start, void **head, void **tail, void **end)
137+{
138+ /* Check if we need to resize the queue. */
139+
140+ if (*start == *head && *tail == *end) {
141+ void *new_start = yaml_realloc(*start,
142+ ((char *)*end - (char *)*start)*2);
143+
144+ if (!new_start) return 0;
145+
146+ *head = (char *)new_start + ((char *)*head - (char *)*start);
147+ *tail = (char *)new_start + ((char *)*tail - (char *)*start);
148+ *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
149+ *start = new_start;
150+ }
151+
152+ /* Check if we need to move the queue at the beginning of the buffer. */
153+
154+ if (*tail == *end) {
155+ if (*head != *tail) {
156+ memmove(*start, *head, (char *)*tail - (char *)*head);
157+ }
158+ *tail = (char *)*tail - (char *)*head + (char *)*start;
159+ *head = *start;
160+ }
161+
162+ return 1;
163+}
164+
165+
166+/*
167+ * Create a new parser object.
168+ */
169+
170+YAML_DECLARE(int)
171+yaml_parser_initialize(yaml_parser_t *parser)
172+{
173+ assert(parser); /* Non-NULL parser object expected. */
174+
175+ memset(parser, 0, sizeof(yaml_parser_t));
176+ if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
177+ goto error;
178+ if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
179+ goto error;
180+ if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
181+ goto error;
182+ if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
183+ goto error;
184+ if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
185+ goto error;
186+ if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
187+ goto error;
188+ if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
189+ goto error;
190+ if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
191+ goto error;
192+
193+ return 1;
194+
195+error:
196+
197+ BUFFER_DEL(parser, parser->raw_buffer);
198+ BUFFER_DEL(parser, parser->buffer);
199+ QUEUE_DEL(parser, parser->tokens);
200+ STACK_DEL(parser, parser->indents);
201+ STACK_DEL(parser, parser->simple_keys);
202+ STACK_DEL(parser, parser->states);
203+ STACK_DEL(parser, parser->marks);
204+ STACK_DEL(parser, parser->tag_directives);
205+
206+ return 0;
207+}
208+
209+/*
210+ * Destroy a parser object.
211+ */
212+
213+YAML_DECLARE(void)
214+yaml_parser_delete(yaml_parser_t *parser)
215+{
216+ assert(parser); /* Non-NULL parser object expected. */
217+
218+ BUFFER_DEL(parser, parser->raw_buffer);
219+ BUFFER_DEL(parser, parser->buffer);
220+ while (!QUEUE_EMPTY(parser, parser->tokens)) {
221+ yaml_token_delete(&DEQUEUE(parser, parser->tokens));
222+ }
223+ QUEUE_DEL(parser, parser->tokens);
224+ STACK_DEL(parser, parser->indents);
225+ STACK_DEL(parser, parser->simple_keys);
226+ STACK_DEL(parser, parser->states);
227+ STACK_DEL(parser, parser->marks);
228+ while (!STACK_EMPTY(parser, parser->tag_directives)) {
229+ yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
230+ yaml_free(tag_directive.handle);
231+ yaml_free(tag_directive.prefix);
232+ }
233+ STACK_DEL(parser, parser->tag_directives);
234+
235+ memset(parser, 0, sizeof(yaml_parser_t));
236+}
237+
238+/*
239+ * String read handler.
240+ */
241+
242+static int
243+yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
244+ size_t *size_read)
245+{
246+ yaml_parser_t *parser = data;
247+
248+ if (parser->input.string.current == parser->input.string.end) {
249+ *size_read = 0;
250+ return 1;
251+ }
252+
253+ if (size > (size_t)(parser->input.string.end
254+ - parser->input.string.current)) {
255+ size = parser->input.string.end - parser->input.string.current;
256+ }
257+
258+ memcpy(buffer, parser->input.string.current, size);
259+ parser->input.string.current += size;
260+ *size_read = size;
261+ return 1;
262+}
263+
264+/*
265+ * File read handler.
266+ */
267+
268+static int
269+yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
270+ size_t *size_read)
271+{
272+ yaml_parser_t *parser = data;
273+
274+ *size_read = fread(buffer, 1, size, parser->input.file);
275+ return !ferror(parser->input.file);
276+}
277+
278+/*
279+ * Set a string input.
280+ */
281+
282+YAML_DECLARE(void)
283+yaml_parser_set_input_string(yaml_parser_t *parser,
284+ const unsigned char *input, size_t size)
285+{
286+ assert(parser); /* Non-NULL parser object expected. */
287+ assert(!parser->read_handler); /* You can set the source only once. */
288+ assert(input); /* Non-NULL input string expected. */
289+
290+ parser->read_handler = yaml_string_read_handler;
291+ parser->read_handler_data = parser;
292+
293+ parser->input.string.start = input;
294+ parser->input.string.current = input;
295+ parser->input.string.end = input+size;
296+}
297+
298+/*
299+ * Set a file input.
300+ */
301+
302+YAML_DECLARE(void)
303+yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
304+{
305+ assert(parser); /* Non-NULL parser object expected. */
306+ assert(!parser->read_handler); /* You can set the source only once. */
307+ assert(file); /* Non-NULL file object expected. */
308+
309+ parser->read_handler = yaml_file_read_handler;
310+ parser->read_handler_data = parser;
311+
312+ parser->input.file = file;
313+}
314+
315+/*
316+ * Set a generic input.
317+ */
318+
319+YAML_DECLARE(void)
320+yaml_parser_set_input(yaml_parser_t *parser,
321+ yaml_read_handler_t *handler, void *data)
322+{
323+ assert(parser); /* Non-NULL parser object expected. */
324+ assert(!parser->read_handler); /* You can set the source only once. */
325+ assert(handler); /* Non-NULL read handler expected. */
326+
327+ parser->read_handler = handler;
328+ parser->read_handler_data = data;
329+}
330+
331+/*
332+ * Set the source encoding.
333+ */
334+
335+YAML_DECLARE(void)
336+yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
337+{
338+ assert(parser); /* Non-NULL parser object expected. */
339+ assert(!parser->encoding); /* Encoding is already set or detected. */
340+
341+ parser->encoding = encoding;
342+}
343+
344+/*
345+ * Create a new emitter object.
346+ */
347+
348+YAML_DECLARE(int)
349+yaml_emitter_initialize(yaml_emitter_t *emitter)
350+{
351+ assert(emitter); /* Non-NULL emitter object expected. */
352+
353+ memset(emitter, 0, sizeof(yaml_emitter_t));
354+ if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
355+ goto error;
356+ if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
357+ goto error;
358+ if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE))
359+ goto error;
360+ if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE))
361+ goto error;
362+ if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE))
363+ goto error;
364+ if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE))
365+ goto error;
366+
367+ return 1;
368+
369+error:
370+
371+ BUFFER_DEL(emitter, emitter->buffer);
372+ BUFFER_DEL(emitter, emitter->raw_buffer);
373+ STACK_DEL(emitter, emitter->states);
374+ QUEUE_DEL(emitter, emitter->events);
375+ STACK_DEL(emitter, emitter->indents);
376+ STACK_DEL(emitter, emitter->tag_directives);
377+
378+ return 0;
379+}
380+
381+/*
382+ * Destroy an emitter object.
383+ */
384+
385+YAML_DECLARE(void)
386+yaml_emitter_delete(yaml_emitter_t *emitter)
387+{
388+ assert(emitter); /* Non-NULL emitter object expected. */
389+
390+ BUFFER_DEL(emitter, emitter->buffer);
391+ BUFFER_DEL(emitter, emitter->raw_buffer);
392+ STACK_DEL(emitter, emitter->states);
393+ while (!QUEUE_EMPTY(emitter, emitter->events)) {
394+ yaml_event_delete(&DEQUEUE(emitter, emitter->events));
395+ }
396+ QUEUE_DEL(emitter, emitter->events);
397+ STACK_DEL(emitter, emitter->indents);
398+ while (!STACK_EMPTY(empty, emitter->tag_directives)) {
399+ yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
400+ yaml_free(tag_directive.handle);
401+ yaml_free(tag_directive.prefix);
402+ }
403+ STACK_DEL(emitter, emitter->tag_directives);
404+ yaml_free(emitter->anchors);
405+
406+ memset(emitter, 0, sizeof(yaml_emitter_t));
407+}
408+
409+/*
410+ * String write handler.
411+ */
412+
413+static int
414+yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
415+{
416+ yaml_emitter_t *emitter = data;
417+
418+ if (emitter->output.string.size + *emitter->output.string.size_written
419+ < size) {
420+ memcpy(emitter->output.string.buffer
421+ + *emitter->output.string.size_written,
422+ buffer,
423+ emitter->output.string.size
424+ - *emitter->output.string.size_written);
425+ *emitter->output.string.size_written = emitter->output.string.size;
426+ return 0;
427+ }
428+
429+ memcpy(emitter->output.string.buffer
430+ + *emitter->output.string.size_written, buffer, size);
431+ *emitter->output.string.size_written += size;
432+ return 1;
433+}
434+
435+/*
436+ * File write handler.
437+ */
438+
439+static int
440+yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
441+{
442+ yaml_emitter_t *emitter = data;
443+
444+ return (fwrite(buffer, 1, size, emitter->output.file) == size);
445+}
446+/*
447+ * Set a string output.
448+ */
449+
450+YAML_DECLARE(void)
451+yaml_emitter_set_output_string(yaml_emitter_t *emitter,
452+ unsigned char *output, size_t size, size_t *size_written)
453+{
454+ assert(emitter); /* Non-NULL emitter object expected. */
455+ assert(!emitter->write_handler); /* You can set the output only once. */
456+ assert(output); /* Non-NULL output string expected. */
457+
458+ emitter->write_handler = yaml_string_write_handler;
459+ emitter->write_handler_data = emitter;
460+
461+ emitter->output.string.buffer = output;
462+ emitter->output.string.size = size;
463+ emitter->output.string.size_written = size_written;
464+ *size_written = 0;
465+}
466+
467+/*
468+ * Set a file output.
469+ */
470+
471+YAML_DECLARE(void)
472+yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
473+{
474+ assert(emitter); /* Non-NULL emitter object expected. */
475+ assert(!emitter->write_handler); /* You can set the output only once. */
476+ assert(file); /* Non-NULL file object expected. */
477+
478+ emitter->write_handler = yaml_file_write_handler;
479+ emitter->write_handler_data = emitter;
480+
481+ emitter->output.file = file;
482+}
483+
484+/*
485+ * Set a generic output handler.
486+ */
487+
488+YAML_DECLARE(void)
489+yaml_emitter_set_output(yaml_emitter_t *emitter,
490+ yaml_write_handler_t *handler, void *data)
491+{
492+ assert(emitter); /* Non-NULL emitter object expected. */
493+ assert(!emitter->write_handler); /* You can set the output only once. */
494+ assert(handler); /* Non-NULL handler object expected. */
495+
496+ emitter->write_handler = handler;
497+ emitter->write_handler_data = data;
498+}
499+
500+/*
501+ * Set the output encoding.
502+ */
503+
504+YAML_DECLARE(void)
505+yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
506+{
507+ assert(emitter); /* Non-NULL emitter object expected. */
508+ assert(!emitter->encoding); /* You can set encoding only once. */
509+
510+ emitter->encoding = encoding;
511+}
512+
513+/*
514+ * Set the canonical output style.
515+ */
516+
517+YAML_DECLARE(void)
518+yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
519+{
520+ assert(emitter); /* Non-NULL emitter object expected. */
521+
522+ emitter->canonical = (canonical != 0);
523+}
524+
525+/*
526+ * Set the indentation increment.
527+ */
528+
529+YAML_DECLARE(void)
530+yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
531+{
532+ assert(emitter); /* Non-NULL emitter object expected. */
533+
534+ emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
535+}
536+
537+/*
538+ * Set the preferred line width.
539+ */
540+
541+YAML_DECLARE(void)
542+yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
543+{
544+ assert(emitter); /* Non-NULL emitter object expected. */
545+
546+ emitter->best_width = (width >= 0) ? width : -1;
547+}
548+
549+/*
550+ * Set if unescaped non-ASCII characters are allowed.
551+ */
552+
553+YAML_DECLARE(void)
554+yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
555+{
556+ assert(emitter); /* Non-NULL emitter object expected. */
557+
558+ emitter->unicode = (unicode != 0);
559+}
560+
561+/*
562+ * Set the preferred line break character.
563+ */
564+
565+YAML_DECLARE(void)
566+yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
567+{
568+ assert(emitter); /* Non-NULL emitter object expected. */
569+
570+ emitter->line_break = line_break;
571+}
572+
573+/*
574+ * Destroy a token object.
575+ */
576+
577+YAML_DECLARE(void)
578+yaml_token_delete(yaml_token_t *token)
579+{
580+ assert(token); /* Non-NULL token object expected. */
581+
582+ switch (token->type)
583+ {
584+ case YAML_TAG_DIRECTIVE_TOKEN:
585+ yaml_free(token->data.tag_directive.handle);
586+ yaml_free(token->data.tag_directive.prefix);
587+ break;
588+
589+ case YAML_ALIAS_TOKEN:
590+ yaml_free(token->data.alias.value);
591+ break;
592+
593+ case YAML_ANCHOR_TOKEN:
594+ yaml_free(token->data.anchor.value);
595+ break;
596+
597+ case YAML_TAG_TOKEN:
598+ yaml_free(token->data.tag.handle);
599+ yaml_free(token->data.tag.suffix);
600+ break;
601+
602+ case YAML_SCALAR_TOKEN:
603+ yaml_free(token->data.scalar.value);
604+ break;
605+
606+ default:
607+ break;
608+ }
609+
610+ memset(token, 0, sizeof(yaml_token_t));
611+}
612+
613+/*
614+ * Check if a string is a valid UTF-8 sequence.
615+ *
616+ * Check 'reader.c' for more details on UTF-8 encoding.
617+ */
618+
619+static int
620+yaml_check_utf8(yaml_char_t *start, size_t length)
621+{
622+ yaml_char_t *end = start+length;
623+ yaml_char_t *pointer = start;
624+
625+ while (pointer < end) {
626+ unsigned char octet;
627+ unsigned int width;
628+ unsigned int value;
629+ size_t k;
630+
631+ octet = pointer[0];
632+ width = (octet & 0x80) == 0x00 ? 1 :
633+ (octet & 0xE0) == 0xC0 ? 2 :
634+ (octet & 0xF0) == 0xE0 ? 3 :
635+ (octet & 0xF8) == 0xF0 ? 4 : 0;
636+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
637+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
638+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
639+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
640+ if (!width) return 0;
641+ if (pointer+width > end) return 0;
642+ for (k = 1; k < width; k ++) {
643+ octet = pointer[k];
644+ if ((octet & 0xC0) != 0x80) return 0;
645+ value = (value << 6) + (octet & 0x3F);
646+ }
647+ if (!((width == 1) ||
648+ (width == 2 && value >= 0x80) ||
649+ (width == 3 && value >= 0x800) ||
650+ (width == 4 && value >= 0x10000))) return 0;
651+
652+ pointer += width;
653+ }
654+
655+ return 1;
656+}
657+
658+/*
659+ * Create STREAM-START.
660+ */
661+
662+YAML_DECLARE(int)
663+yaml_stream_start_event_initialize(yaml_event_t *event,
664+ yaml_encoding_t encoding)
665+{
666+ yaml_mark_t mark = { 0, 0, 0 };
667+
668+ assert(event); /* Non-NULL event object is expected. */
669+
670+ STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
671+
672+ return 1;
673+}
674+
675+/*
676+ * Create STREAM-END.
677+ */
678+
679+YAML_DECLARE(int)
680+yaml_stream_end_event_initialize(yaml_event_t *event)
681+{
682+ yaml_mark_t mark = { 0, 0, 0 };
683+
684+ assert(event); /* Non-NULL event object is expected. */
685+
686+ STREAM_END_EVENT_INIT(*event, mark, mark);
687+
688+ return 1;
689+}
690+
691+/*
692+ * Create DOCUMENT-START.
693+ */
694+
695+YAML_DECLARE(int)
696+yaml_document_start_event_initialize(yaml_event_t *event,
697+ yaml_version_directive_t *version_directive,
698+ yaml_tag_directive_t *tag_directives_start,
699+ yaml_tag_directive_t *tag_directives_end,
700+ int implicit)
701+{
702+ struct {
703+ yaml_error_type_t error;
704+ } context;
705+ yaml_mark_t mark = { 0, 0, 0 };
706+ yaml_version_directive_t *version_directive_copy = NULL;
707+ struct {
708+ yaml_tag_directive_t *start;
709+ yaml_tag_directive_t *end;
710+ yaml_tag_directive_t *top;
711+ } tag_directives_copy = { NULL, NULL, NULL };
712+ yaml_tag_directive_t value = { NULL, NULL };
713+
714+ assert(event); /* Non-NULL event object is expected. */
715+ assert((tag_directives_start && tag_directives_end) ||
716+ (tag_directives_start == tag_directives_end));
717+ /* Valid tag directives are expected. */
718+
719+ if (version_directive) {
720+ version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
721+ if (!version_directive_copy) goto error;
722+ version_directive_copy->major = version_directive->major;
723+ version_directive_copy->minor = version_directive->minor;
724+ }
725+
726+ if (tag_directives_start != tag_directives_end) {
727+ yaml_tag_directive_t *tag_directive;
728+ if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
729+ goto error;
730+ for (tag_directive = tag_directives_start;
731+ tag_directive != tag_directives_end; tag_directive ++) {
732+ assert(tag_directive->handle);
733+ assert(tag_directive->prefix);
734+ if (!yaml_check_utf8(tag_directive->handle,
735+ strlen((char *)tag_directive->handle)))
736+ goto error;
737+ if (!yaml_check_utf8(tag_directive->prefix,
738+ strlen((char *)tag_directive->prefix)))
739+ goto error;
740+ value.handle = yaml_strdup(tag_directive->handle);
741+ value.prefix = yaml_strdup(tag_directive->prefix);
742+ if (!value.handle || !value.prefix) goto error;
743+ if (!PUSH(&context, tag_directives_copy, value))
744+ goto error;
745+ value.handle = NULL;
746+ value.prefix = NULL;
747+ }
748+ }
749+
750+ DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
751+ tag_directives_copy.start, tag_directives_copy.top,
752+ implicit, mark, mark);
753+
754+ return 1;
755+
756+error:
757+ yaml_free(version_directive_copy);
758+ while (!STACK_EMPTY(context, tag_directives_copy)) {
759+ yaml_tag_directive_t value = POP(context, tag_directives_copy);
760+ yaml_free(value.handle);
761+ yaml_free(value.prefix);
762+ }
763+ STACK_DEL(context, tag_directives_copy);
764+ yaml_free(value.handle);
765+ yaml_free(value.prefix);
766+
767+ return 0;
768+}
769+
770+/*
771+ * Create DOCUMENT-END.
772+ */
773+
774+YAML_DECLARE(int)
775+yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
776+{
777+ yaml_mark_t mark = { 0, 0, 0 };
778+
779+ assert(event); /* Non-NULL emitter object is expected. */
780+
781+ DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
782+
783+ return 1;
784+}
785+
786+/*
787+ * Create ALIAS.
788+ */
789+
790+YAML_DECLARE(int)
791+yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
792+{
793+ yaml_mark_t mark = { 0, 0, 0 };
794+ yaml_char_t *anchor_copy = NULL;
795+
796+ assert(event); /* Non-NULL event object is expected. */
797+ assert(anchor); /* Non-NULL anchor is expected. */
798+
799+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
800+
801+ anchor_copy = yaml_strdup(anchor);
802+ if (!anchor_copy)
803+ return 0;
804+
805+ ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
806+
807+ return 1;
808+}
809+
810+/*
811+ * Create SCALAR.
812+ */
813+
814+YAML_DECLARE(int)
815+yaml_scalar_event_initialize(yaml_event_t *event,
816+ yaml_char_t *anchor, yaml_char_t *tag,
817+ yaml_char_t *value, int length,
818+ int plain_implicit, int quoted_implicit,
819+ yaml_scalar_style_t style)
820+{
821+ yaml_mark_t mark = { 0, 0, 0 };
822+ yaml_char_t *anchor_copy = NULL;
823+ yaml_char_t *tag_copy = NULL;
824+ yaml_char_t *value_copy = NULL;
825+
826+ assert(event); /* Non-NULL event object is expected. */
827+ /* following line added for Haskell yaml library */
828+ if (!value && !length) value = "";
829+ assert(value); /* Non-NULL anchor is expected. */
830+
831+ if (anchor) {
832+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
833+ anchor_copy = yaml_strdup(anchor);
834+ if (!anchor_copy) goto error;
835+ }
836+
837+ if (tag) {
838+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
839+ tag_copy = yaml_strdup(tag);
840+ if (!tag_copy) goto error;
841+ }
842+
843+ if (length < 0) {
844+ length = strlen((char *)value);
845+ }
846+
847+ if (!yaml_check_utf8(value, length)) goto error;
848+ value_copy = yaml_malloc(length+1);
849+ if (!value_copy) goto error;
850+ memcpy(value_copy, value, length);
851+ value_copy[length] = '\0';
852+
853+ SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
854+ plain_implicit, quoted_implicit, style, mark, mark);
855+
856+ return 1;
857+
858+error:
859+ yaml_free(anchor_copy);
860+ yaml_free(tag_copy);
861+ yaml_free(value_copy);
862+
863+ return 0;
864+}
865+
866+/*
867+ * Create SEQUENCE-START.
868+ */
869+
870+YAML_DECLARE(int)
871+yaml_sequence_start_event_initialize(yaml_event_t *event,
872+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
873+ yaml_sequence_style_t style)
874+{
875+ yaml_mark_t mark = { 0, 0, 0 };
876+ yaml_char_t *anchor_copy = NULL;
877+ yaml_char_t *tag_copy = NULL;
878+
879+ assert(event); /* Non-NULL event object is expected. */
880+
881+ if (anchor) {
882+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
883+ anchor_copy = yaml_strdup(anchor);
884+ if (!anchor_copy) goto error;
885+ }
886+
887+ if (tag) {
888+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
889+ tag_copy = yaml_strdup(tag);
890+ if (!tag_copy) goto error;
891+ }
892+
893+ SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
894+ implicit, style, mark, mark);
895+
896+ return 1;
897+
898+error:
899+ yaml_free(anchor_copy);
900+ yaml_free(tag_copy);
901+
902+ return 0;
903+}
904+
905+/*
906+ * Create SEQUENCE-END.
907+ */
908+
909+YAML_DECLARE(int)
910+yaml_sequence_end_event_initialize(yaml_event_t *event)
911+{
912+ yaml_mark_t mark = { 0, 0, 0 };
913+
914+ assert(event); /* Non-NULL event object is expected. */
915+
916+ SEQUENCE_END_EVENT_INIT(*event, mark, mark);
917+
918+ return 1;
919+}
920+
921+/*
922+ * Create MAPPING-START.
923+ */
924+
925+YAML_DECLARE(int)
926+yaml_mapping_start_event_initialize(yaml_event_t *event,
927+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
928+ yaml_mapping_style_t style)
929+{
930+ yaml_mark_t mark = { 0, 0, 0 };
931+ yaml_char_t *anchor_copy = NULL;
932+ yaml_char_t *tag_copy = NULL;
933+
934+ assert(event); /* Non-NULL event object is expected. */
935+
936+ if (anchor) {
937+ if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
938+ anchor_copy = yaml_strdup(anchor);
939+ if (!anchor_copy) goto error;
940+ }
941+
942+ if (tag) {
943+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
944+ tag_copy = yaml_strdup(tag);
945+ if (!tag_copy) goto error;
946+ }
947+
948+ MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
949+ implicit, style, mark, mark);
950+
951+ return 1;
952+
953+error:
954+ yaml_free(anchor_copy);
955+ yaml_free(tag_copy);
956+
957+ return 0;
958+}
959+
960+/*
961+ * Create MAPPING-END.
962+ */
963+
964+YAML_DECLARE(int)
965+yaml_mapping_end_event_initialize(yaml_event_t *event)
966+{
967+ yaml_mark_t mark = { 0, 0, 0 };
968+
969+ assert(event); /* Non-NULL event object is expected. */
970+
971+ MAPPING_END_EVENT_INIT(*event, mark, mark);
972+
973+ return 1;
974+}
975+
976+/*
977+ * Destroy an event object.
978+ */
979+
980+YAML_DECLARE(void)
981+yaml_event_delete(yaml_event_t *event)
982+{
983+ yaml_tag_directive_t *tag_directive;
984+
985+ assert(event); /* Non-NULL event object expected. */
986+
987+ switch (event->type)
988+ {
989+ case YAML_DOCUMENT_START_EVENT:
990+ yaml_free(event->data.document_start.version_directive);
991+ for (tag_directive = event->data.document_start.tag_directives.start;
992+ tag_directive != event->data.document_start.tag_directives.end;
993+ tag_directive++) {
994+ yaml_free(tag_directive->handle);
995+ yaml_free(tag_directive->prefix);
996+ }
997+ yaml_free(event->data.document_start.tag_directives.start);
998+ break;
999+
1000+ case YAML_ALIAS_EVENT:
1001+ yaml_free(event->data.alias.anchor);
1002+ break;
1003+
1004+ case YAML_SCALAR_EVENT:
1005+ yaml_free(event->data.scalar.anchor);
1006+ yaml_free(event->data.scalar.tag);
1007+ yaml_free(event->data.scalar.value);
1008+ break;
1009+
1010+ case YAML_SEQUENCE_START_EVENT:
1011+ yaml_free(event->data.sequence_start.anchor);
1012+ yaml_free(event->data.sequence_start.tag);
1013+ break;
1014+
1015+ case YAML_MAPPING_START_EVENT:
1016+ yaml_free(event->data.mapping_start.anchor);
1017+ yaml_free(event->data.mapping_start.tag);
1018+ break;
1019+
1020+ default:
1021+ break;
1022+ }
1023+
1024+ memset(event, 0, sizeof(yaml_event_t));
1025+}
1026+
1027+/*
1028+ * Create a document object.
1029+ */
1030+
1031+YAML_DECLARE(int)
1032+yaml_document_initialize(yaml_document_t *document,
1033+ yaml_version_directive_t *version_directive,
1034+ yaml_tag_directive_t *tag_directives_start,
1035+ yaml_tag_directive_t *tag_directives_end,
1036+ int start_implicit, int end_implicit)
1037+{
1038+ struct {
1039+ yaml_error_type_t error;
1040+ } context;
1041+ struct {
1042+ yaml_node_t *start;
1043+ yaml_node_t *end;
1044+ yaml_node_t *top;
1045+ } nodes = { NULL, NULL, NULL };
1046+ yaml_version_directive_t *version_directive_copy = NULL;
1047+ struct {
1048+ yaml_tag_directive_t *start;
1049+ yaml_tag_directive_t *end;
1050+ yaml_tag_directive_t *top;
1051+ } tag_directives_copy = { NULL, NULL, NULL };
1052+ yaml_tag_directive_t value = { NULL, NULL };
1053+ yaml_mark_t mark = { 0, 0, 0 };
1054+
1055+ assert(document); /* Non-NULL document object is expected. */
1056+ assert((tag_directives_start && tag_directives_end) ||
1057+ (tag_directives_start == tag_directives_end));
1058+ /* Valid tag directives are expected. */
1059+
1060+ if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
1061+
1062+ if (version_directive) {
1063+ version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1064+ if (!version_directive_copy) goto error;
1065+ version_directive_copy->major = version_directive->major;
1066+ version_directive_copy->minor = version_directive->minor;
1067+ }
1068+
1069+ if (tag_directives_start != tag_directives_end) {
1070+ yaml_tag_directive_t *tag_directive;
1071+ if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
1072+ goto error;
1073+ for (tag_directive = tag_directives_start;
1074+ tag_directive != tag_directives_end; tag_directive ++) {
1075+ assert(tag_directive->handle);
1076+ assert(tag_directive->prefix);
1077+ if (!yaml_check_utf8(tag_directive->handle,
1078+ strlen((char *)tag_directive->handle)))
1079+ goto error;
1080+ if (!yaml_check_utf8(tag_directive->prefix,
1081+ strlen((char *)tag_directive->prefix)))
1082+ goto error;
1083+ value.handle = yaml_strdup(tag_directive->handle);
1084+ value.prefix = yaml_strdup(tag_directive->prefix);
1085+ if (!value.handle || !value.prefix) goto error;
1086+ if (!PUSH(&context, tag_directives_copy, value))
1087+ goto error;
1088+ value.handle = NULL;
1089+ value.prefix = NULL;
1090+ }
1091+ }
1092+
1093+ DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1094+ tag_directives_copy.start, tag_directives_copy.top,
1095+ start_implicit, end_implicit, mark, mark);
1096+
1097+ return 1;
1098+
1099+error:
1100+ STACK_DEL(&context, nodes);
1101+ yaml_free(version_directive_copy);
1102+ while (!STACK_EMPTY(&context, tag_directives_copy)) {
1103+ yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1104+ yaml_free(value.handle);
1105+ yaml_free(value.prefix);
1106+ }
1107+ STACK_DEL(&context, tag_directives_copy);
1108+ yaml_free(value.handle);
1109+ yaml_free(value.prefix);
1110+
1111+ return 0;
1112+}
1113+
1114+/*
1115+ * Destroy a document object.
1116+ */
1117+
1118+YAML_DECLARE(void)
1119+yaml_document_delete(yaml_document_t *document)
1120+{
1121+ struct {
1122+ yaml_error_type_t error;
1123+ } context;
1124+ yaml_tag_directive_t *tag_directive;
1125+
1126+ context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */
1127+
1128+ assert(document); /* Non-NULL document object is expected. */
1129+
1130+ while (!STACK_EMPTY(&context, document->nodes)) {
1131+ yaml_node_t node = POP(&context, document->nodes);
1132+ yaml_free(node.tag);
1133+ switch (node.type) {
1134+ case YAML_SCALAR_NODE:
1135+ yaml_free(node.data.scalar.value);
1136+ break;
1137+ case YAML_SEQUENCE_NODE:
1138+ STACK_DEL(&context, node.data.sequence.items);
1139+ break;
1140+ case YAML_MAPPING_NODE:
1141+ STACK_DEL(&context, node.data.mapping.pairs);
1142+ break;
1143+ default:
1144+ assert(0); /* Should not happen. */
1145+ }
1146+ }
1147+ STACK_DEL(&context, document->nodes);
1148+
1149+ yaml_free(document->version_directive);
1150+ for (tag_directive = document->tag_directives.start;
1151+ tag_directive != document->tag_directives.end;
1152+ tag_directive++) {
1153+ yaml_free(tag_directive->handle);
1154+ yaml_free(tag_directive->prefix);
1155+ }
1156+ yaml_free(document->tag_directives.start);
1157+
1158+ memset(document, 0, sizeof(yaml_document_t));
1159+}
1160+
1161+/**
1162+ * Get a document node.
1163+ */
1164+
1165+YAML_DECLARE(yaml_node_t *)
1166+yaml_document_get_node(yaml_document_t *document, int index)
1167+{
1168+ assert(document); /* Non-NULL document object is expected. */
1169+
1170+ if (index > 0 && document->nodes.start + index <= document->nodes.top) {
1171+ return document->nodes.start + index - 1;
1172+ }
1173+ return NULL;
1174+}
1175+
1176+/**
1177+ * Get the root object.
1178+ */
1179+
1180+YAML_DECLARE(yaml_node_t *)
1181+yaml_document_get_root_node(yaml_document_t *document)
1182+{
1183+ assert(document); /* Non-NULL document object is expected. */
1184+
1185+ if (document->nodes.top != document->nodes.start) {
1186+ return document->nodes.start;
1187+ }
1188+ return NULL;
1189+}
1190+
1191+/*
1192+ * Add a scalar node to a document.
1193+ */
1194+
1195+YAML_DECLARE(int)
1196+yaml_document_add_scalar(yaml_document_t *document,
1197+ yaml_char_t *tag, yaml_char_t *value, int length,
1198+ yaml_scalar_style_t style)
1199+{
1200+ struct {
1201+ yaml_error_type_t error;
1202+ } context;
1203+ yaml_mark_t mark = { 0, 0, 0 };
1204+ yaml_char_t *tag_copy = NULL;
1205+ yaml_char_t *value_copy = NULL;
1206+ yaml_node_t node;
1207+
1208+ assert(document); /* Non-NULL document object is expected. */
1209+ assert(value); /* Non-NULL value is expected. */
1210+
1211+ if (!tag) {
1212+ tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
1213+ }
1214+
1215+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1216+ tag_copy = yaml_strdup(tag);
1217+ if (!tag_copy) goto error;
1218+
1219+ if (length < 0) {
1220+ length = strlen((char *)value);
1221+ }
1222+
1223+ if (!yaml_check_utf8(value, length)) goto error;
1224+ value_copy = yaml_malloc(length+1);
1225+ if (!value_copy) goto error;
1226+ memcpy(value_copy, value, length);
1227+ value_copy[length] = '\0';
1228+
1229+ SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
1230+ if (!PUSH(&context, document->nodes, node)) goto error;
1231+
1232+ return document->nodes.top - document->nodes.start;
1233+
1234+error:
1235+ yaml_free(tag_copy);
1236+ yaml_free(value_copy);
1237+
1238+ return 0;
1239+}
1240+
1241+/*
1242+ * Add a sequence node to a document.
1243+ */
1244+
1245+YAML_DECLARE(int)
1246+yaml_document_add_sequence(yaml_document_t *document,
1247+ yaml_char_t *tag, yaml_sequence_style_t style)
1248+{
1249+ struct {
1250+ yaml_error_type_t error;
1251+ } context;
1252+ yaml_mark_t mark = { 0, 0, 0 };
1253+ yaml_char_t *tag_copy = NULL;
1254+ struct {
1255+ yaml_node_item_t *start;
1256+ yaml_node_item_t *end;
1257+ yaml_node_item_t *top;
1258+ } items = { NULL, NULL, NULL };
1259+ yaml_node_t node;
1260+
1261+ assert(document); /* Non-NULL document object is expected. */
1262+
1263+ if (!tag) {
1264+ tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
1265+ }
1266+
1267+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1268+ tag_copy = yaml_strdup(tag);
1269+ if (!tag_copy) goto error;
1270+
1271+ if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
1272+
1273+ SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
1274+ style, mark, mark);
1275+ if (!PUSH(&context, document->nodes, node)) goto error;
1276+
1277+ return document->nodes.top - document->nodes.start;
1278+
1279+error:
1280+ STACK_DEL(&context, items);
1281+ yaml_free(tag_copy);
1282+
1283+ return 0;
1284+}
1285+
1286+/*
1287+ * Add a mapping node to a document.
1288+ */
1289+
1290+YAML_DECLARE(int)
1291+yaml_document_add_mapping(yaml_document_t *document,
1292+ yaml_char_t *tag, yaml_mapping_style_t style)
1293+{
1294+ struct {
1295+ yaml_error_type_t error;
1296+ } context;
1297+ yaml_mark_t mark = { 0, 0, 0 };
1298+ yaml_char_t *tag_copy = NULL;
1299+ struct {
1300+ yaml_node_pair_t *start;
1301+ yaml_node_pair_t *end;
1302+ yaml_node_pair_t *top;
1303+ } pairs = { NULL, NULL, NULL };
1304+ yaml_node_t node;
1305+
1306+ assert(document); /* Non-NULL document object is expected. */
1307+
1308+ if (!tag) {
1309+ tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
1310+ }
1311+
1312+ if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1313+ tag_copy = yaml_strdup(tag);
1314+ if (!tag_copy) goto error;
1315+
1316+ if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
1317+
1318+ MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
1319+ style, mark, mark);
1320+ if (!PUSH(&context, document->nodes, node)) goto error;
1321+
1322+ return document->nodes.top - document->nodes.start;
1323+
1324+error:
1325+ STACK_DEL(&context, pairs);
1326+ yaml_free(tag_copy);
1327+
1328+ return 0;
1329+}
1330+
1331+/*
1332+ * Append an item to a sequence node.
1333+ */
1334+
1335+YAML_DECLARE(int)
1336+yaml_document_append_sequence_item(yaml_document_t *document,
1337+ int sequence, int item)
1338+{
1339+ struct {
1340+ yaml_error_type_t error;
1341+ } context;
1342+
1343+ assert(document); /* Non-NULL document is required. */
1344+ assert(sequence > 0
1345+ && document->nodes.start + sequence <= document->nodes.top);
1346+ /* Valid sequence id is required. */
1347+ assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
1348+ /* A sequence node is required. */
1349+ assert(item > 0 && document->nodes.start + item <= document->nodes.top);
1350+ /* Valid item id is required. */
1351+
1352+ if (!PUSH(&context,
1353+ document->nodes.start[sequence-1].data.sequence.items, item))
1354+ return 0;
1355+
1356+ return 1;
1357+}
1358+
1359+/*
1360+ * Append a pair of a key and a value to a mapping node.
1361+ */
1362+
1363+YAML_DECLARE(int)
1364+yaml_document_append_mapping_pair(yaml_document_t *document,
1365+ int mapping, int key, int value)
1366+{
1367+ struct {
1368+ yaml_error_type_t error;
1369+ } context;
1370+ yaml_node_pair_t pair = { key, value };
1371+
1372+ assert(document); /* Non-NULL document is required. */
1373+ assert(mapping > 0
1374+ && document->nodes.start + mapping <= document->nodes.top);
1375+ /* Valid mapping id is required. */
1376+ assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
1377+ /* A mapping node is required. */
1378+ assert(key > 0 && document->nodes.start + key <= document->nodes.top);
1379+ /* Valid key id is required. */
1380+ assert(value > 0 && document->nodes.start + value <= document->nodes.top);
1381+ /* Valid value id is required. */
1382+
1383+ if (!PUSH(&context,
1384+ document->nodes.start[mapping-1].data.mapping.pairs, pair))
1385+ return 0;
1386+
1387+ return 1;
1388+}
1389+
1390+
c/dumper.cnew file+394
@@ -0,0 +1,394 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * API functions.
6+ */
7+
8+YAML_DECLARE(int)
9+yaml_emitter_open(yaml_emitter_t *emitter);
10+
11+YAML_DECLARE(int)
12+yaml_emitter_close(yaml_emitter_t *emitter);
13+
14+YAML_DECLARE(int)
15+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
16+
17+/*
18+ * Clean up functions.
19+ */
20+
21+static void
22+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter);
23+
24+/*
25+ * Anchor functions.
26+ */
27+
28+static void
29+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index);
30+
31+static yaml_char_t *
32+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id);
33+
34+
35+/*
36+ * Serialize functions.
37+ */
38+
39+static int
40+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index);
41+
42+static int
43+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor);
44+
45+static int
46+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
47+ yaml_char_t *anchor);
48+
49+static int
50+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
51+ yaml_char_t *anchor);
52+
53+static int
54+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
55+ yaml_char_t *anchor);
56+
57+/*
58+ * Issue a STREAM-START event.
59+ */
60+
61+YAML_DECLARE(int)
62+yaml_emitter_open(yaml_emitter_t *emitter)
63+{
64+ yaml_event_t event;
65+ yaml_mark_t mark = { 0, 0, 0 };
66+
67+ assert(emitter); /* Non-NULL emitter object is required. */
68+ assert(!emitter->opened); /* Emitter should not be opened yet. */
69+
70+ STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark);
71+
72+ if (!yaml_emitter_emit(emitter, &event)) {
73+ return 0;
74+ }
75+
76+ emitter->opened = 1;
77+
78+ return 1;
79+}
80+
81+/*
82+ * Issue a STREAM-END event.
83+ */
84+
85+YAML_DECLARE(int)
86+yaml_emitter_close(yaml_emitter_t *emitter)
87+{
88+ yaml_event_t event;
89+ yaml_mark_t mark = { 0, 0, 0 };
90+
91+ assert(emitter); /* Non-NULL emitter object is required. */
92+ assert(emitter->opened); /* Emitter should be opened. */
93+
94+ if (emitter->closed) return 1;
95+
96+ STREAM_END_EVENT_INIT(event, mark, mark);
97+
98+ if (!yaml_emitter_emit(emitter, &event)) {
99+ return 0;
100+ }
101+
102+ emitter->closed = 1;
103+
104+ return 1;
105+}
106+
107+/*
108+ * Dump a YAML document.
109+ */
110+
111+YAML_DECLARE(int)
112+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
113+{
114+ yaml_event_t event;
115+ yaml_mark_t mark = { 0, 0, 0 };
116+
117+ assert(emitter); /* Non-NULL emitter object is required. */
118+ assert(document); /* Non-NULL emitter object is expected. */
119+
120+ emitter->document = document;
121+
122+ if (!emitter->opened) {
123+ if (!yaml_emitter_open(emitter)) goto error;
124+ }
125+
126+ if (STACK_EMPTY(emitter, document->nodes)) {
127+ if (!yaml_emitter_close(emitter)) goto error;
128+ yaml_emitter_delete_document_and_anchors(emitter);
129+ return 1;
130+ }
131+
132+ assert(emitter->opened); /* Emitter should be opened. */
133+
134+ emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
135+ * (document->nodes.top - document->nodes.start));
136+ if (!emitter->anchors) goto error;
137+ memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
138+ * (document->nodes.top - document->nodes.start));
139+
140+ DOCUMENT_START_EVENT_INIT(event, document->version_directive,
141+ document->tag_directives.start, document->tag_directives.end,
142+ document->start_implicit, mark, mark);
143+ if (!yaml_emitter_emit(emitter, &event)) goto error;
144+
145+ yaml_emitter_anchor_node(emitter, 1);
146+ if (!yaml_emitter_dump_node(emitter, 1)) goto error;
147+
148+ DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark);
149+ if (!yaml_emitter_emit(emitter, &event)) goto error;
150+
151+ yaml_emitter_delete_document_and_anchors(emitter);
152+
153+ return 1;
154+
155+error:
156+
157+ yaml_emitter_delete_document_and_anchors(emitter);
158+
159+ return 0;
160+}
161+
162+/*
163+ * Clean up the emitter object after a document is dumped.
164+ */
165+
166+static void
167+yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter)
168+{
169+ int index;
170+
171+ if (!emitter->anchors) {
172+ yaml_document_delete(emitter->document);
173+ emitter->document = NULL;
174+ return;
175+ }
176+
177+ for (index = 0; emitter->document->nodes.start + index
178+ < emitter->document->nodes.top; index ++) {
179+ yaml_node_t node = emitter->document->nodes.start[index];
180+ if (!emitter->anchors[index].serialized) {
181+ yaml_free(node.tag);
182+ if (node.type == YAML_SCALAR_NODE) {
183+ yaml_free(node.data.scalar.value);
184+ }
185+ }
186+ if (node.type == YAML_SEQUENCE_NODE) {
187+ STACK_DEL(emitter, node.data.sequence.items);
188+ }
189+ if (node.type == YAML_MAPPING_NODE) {
190+ STACK_DEL(emitter, node.data.mapping.pairs);
191+ }
192+ }
193+
194+ STACK_DEL(emitter, emitter->document->nodes);
195+ yaml_free(emitter->anchors);
196+
197+ emitter->anchors = NULL;
198+ emitter->last_anchor_id = 0;
199+ emitter->document = NULL;
200+}
201+
202+/*
203+ * Check the references of a node and assign the anchor id if needed.
204+ */
205+
206+static void
207+yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index)
208+{
209+ yaml_node_t *node = emitter->document->nodes.start + index - 1;
210+ yaml_node_item_t *item;
211+ yaml_node_pair_t *pair;
212+
213+ emitter->anchors[index-1].references ++;
214+
215+ if (emitter->anchors[index-1].references == 1) {
216+ switch (node->type) {
217+ case YAML_SEQUENCE_NODE:
218+ for (item = node->data.sequence.items.start;
219+ item < node->data.sequence.items.top; item ++) {
220+ yaml_emitter_anchor_node(emitter, *item);
221+ }
222+ break;
223+ case YAML_MAPPING_NODE:
224+ for (pair = node->data.mapping.pairs.start;
225+ pair < node->data.mapping.pairs.top; pair ++) {
226+ yaml_emitter_anchor_node(emitter, pair->key);
227+ yaml_emitter_anchor_node(emitter, pair->value);
228+ }
229+ break;
230+ default:
231+ break;
232+ }
233+ }
234+
235+ else if (emitter->anchors[index-1].references == 2) {
236+ emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id);
237+ }
238+}
239+
240+/*
241+ * Generate a textual representation for an anchor.
242+ */
243+
244+#define ANCHOR_TEMPLATE "id%03d"
245+#define ANCHOR_TEMPLATE_LENGTH 16
246+
247+static yaml_char_t *
248+yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)
249+{
250+ yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);
251+
252+ if (!anchor) return NULL;
253+
254+ sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id);
255+
256+ return anchor;
257+}
258+
259+/*
260+ * Serialize a node.
261+ */
262+
263+static int
264+yaml_emitter_dump_node(yaml_emitter_t *emitter, int index)
265+{
266+ yaml_node_t *node = emitter->document->nodes.start + index - 1;
267+ int anchor_id = emitter->anchors[index-1].anchor;
268+ yaml_char_t *anchor = NULL;
269+
270+ if (anchor_id) {
271+ anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
272+ if (!anchor) return 0;
273+ }
274+
275+ if (emitter->anchors[index-1].serialized) {
276+ return yaml_emitter_dump_alias(emitter, anchor);
277+ }
278+
279+ emitter->anchors[index-1].serialized = 1;
280+
281+ switch (node->type) {
282+ case YAML_SCALAR_NODE:
283+ return yaml_emitter_dump_scalar(emitter, node, anchor);
284+ case YAML_SEQUENCE_NODE:
285+ return yaml_emitter_dump_sequence(emitter, node, anchor);
286+ case YAML_MAPPING_NODE:
287+ return yaml_emitter_dump_mapping(emitter, node, anchor);
288+ default:
289+ assert(0); /* Could not happen. */
290+ break;
291+ }
292+
293+ return 0; /* Could not happen. */
294+}
295+
296+/*
297+ * Serialize an alias.
298+ */
299+
300+static int
301+yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor)
302+{
303+ yaml_event_t event;
304+ yaml_mark_t mark = { 0, 0, 0 };
305+
306+ ALIAS_EVENT_INIT(event, anchor, mark, mark);
307+
308+ return yaml_emitter_emit(emitter, &event);
309+}
310+
311+/*
312+ * Serialize a scalar.
313+ */
314+
315+static int
316+yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node,
317+ yaml_char_t *anchor)
318+{
319+ yaml_event_t event;
320+ yaml_mark_t mark = { 0, 0, 0 };
321+
322+ int plain_implicit = (strcmp((char *)node->tag,
323+ YAML_DEFAULT_SCALAR_TAG) == 0);
324+ int quoted_implicit = (strcmp((char *)node->tag,
325+ YAML_DEFAULT_SCALAR_TAG) == 0);
326+
327+ SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value,
328+ node->data.scalar.length, plain_implicit, quoted_implicit,
329+ node->data.scalar.style, mark, mark);
330+
331+ return yaml_emitter_emit(emitter, &event);
332+}
333+
334+/*
335+ * Serialize a sequence.
336+ */
337+
338+static int
339+yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node,
340+ yaml_char_t *anchor)
341+{
342+ yaml_event_t event;
343+ yaml_mark_t mark = { 0, 0, 0 };
344+
345+ int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0);
346+
347+ yaml_node_item_t *item;
348+
349+ SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit,
350+ node->data.sequence.style, mark, mark);
351+ if (!yaml_emitter_emit(emitter, &event)) return 0;
352+
353+ for (item = node->data.sequence.items.start;
354+ item < node->data.sequence.items.top; item ++) {
355+ if (!yaml_emitter_dump_node(emitter, *item)) return 0;
356+ }
357+
358+ SEQUENCE_END_EVENT_INIT(event, mark, mark);
359+ if (!yaml_emitter_emit(emitter, &event)) return 0;
360+
361+ return 1;
362+}
363+
364+/*
365+ * Serialize a mapping.
366+ */
367+
368+static int
369+yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node,
370+ yaml_char_t *anchor)
371+{
372+ yaml_event_t event;
373+ yaml_mark_t mark = { 0, 0, 0 };
374+
375+ int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0);
376+
377+ yaml_node_pair_t *pair;
378+
379+ MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit,
380+ node->data.mapping.style, mark, mark);
381+ if (!yaml_emitter_emit(emitter, &event)) return 0;
382+
383+ for (pair = node->data.mapping.pairs.start;
384+ pair < node->data.mapping.pairs.top; pair ++) {
385+ if (!yaml_emitter_dump_node(emitter, pair->key)) return 0;
386+ if (!yaml_emitter_dump_node(emitter, pair->value)) return 0;
387+ }
388+
389+ MAPPING_END_EVENT_INIT(event, mark, mark);
390+ if (!yaml_emitter_emit(emitter, &event)) return 0;
391+
392+ return 1;
393+}
394+
c/emitter.cnew file+2297
@@ -0,0 +1,2297 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * Flush the buffer if needed.
6+ */
7+
8+#define FLUSH(emitter) \
9+ ((emitter->buffer.pointer+5 < emitter->buffer.end) \
10+ || yaml_emitter_flush(emitter))
11+
12+/*
13+ * Put a character to the output buffer.
14+ */
15+
16+#define PUT(emitter,value) \
17+ (FLUSH(emitter) \
18+ && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \
19+ emitter->column ++, \
20+ 1))
21+
22+/*
23+ * Put a line break to the output buffer.
24+ */
25+
26+#define PUT_BREAK(emitter) \
27+ (FLUSH(emitter) \
28+ && ((emitter->line_break == YAML_CR_BREAK ? \
29+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \
30+ emitter->line_break == YAML_LN_BREAK ? \
31+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \
32+ emitter->line_break == YAML_CRLN_BREAK ? \
33+ (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \
34+ *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \
35+ emitter->column = 0, \
36+ emitter->line ++, \
37+ 1))
38+
39+/*
40+ * Copy a character from a string into buffer.
41+ */
42+
43+#define WRITE(emitter,string) \
44+ (FLUSH(emitter) \
45+ && (COPY(emitter->buffer,string), \
46+ emitter->column ++, \
47+ 1))
48+
49+/*
50+ * Copy a line break character from a string into buffer.
51+ */
52+
53+#define WRITE_BREAK(emitter,string) \
54+ (FLUSH(emitter) \
55+ && (CHECK(string,'\n') ? \
56+ (PUT_BREAK(emitter), \
57+ string.pointer ++, \
58+ 1) : \
59+ (COPY(emitter->buffer,string), \
60+ emitter->column = 0, \
61+ emitter->line ++, \
62+ 1)))
63+
64+/*
65+ * API functions.
66+ */
67+
68+YAML_DECLARE(int)
69+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
70+
71+/*
72+ * Utility functions.
73+ */
74+
75+static int
76+yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem);
77+
78+static int
79+yaml_emitter_need_more_events(yaml_emitter_t *emitter);
80+
81+static int
82+yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
83+ yaml_tag_directive_t value, int allow_duplicates);
84+
85+static int
86+yaml_emitter_increase_indent(yaml_emitter_t *emitter,
87+ int flow, int indentless);
88+
89+/*
90+ * State functions.
91+ */
92+
93+static int
94+yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event);
95+
96+static int
97+yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
98+ yaml_event_t *event);
99+
100+static int
101+yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
102+ yaml_event_t *event, int first);
103+
104+static int
105+yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
106+ yaml_event_t *event);
107+
108+static int
109+yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
110+ yaml_event_t *event);
111+
112+static int
113+yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
114+ yaml_event_t *event, int first);
115+
116+static int
117+yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
118+ yaml_event_t *event, int first);
119+
120+static int
121+yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
122+ yaml_event_t *event, int simple);
123+
124+static int
125+yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
126+ yaml_event_t *event, int first);
127+
128+static int
129+yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
130+ yaml_event_t *event, int first);
131+
132+static int
133+yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
134+ yaml_event_t *event, int simple);
135+
136+static int
137+yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
138+ int root, int sequence, int mapping, int simple_key);
139+
140+static int
141+yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event);
142+
143+static int
144+yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event);
145+
146+static int
147+yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event);
148+
149+static int
150+yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event);
151+
152+/*
153+ * Checkers.
154+ */
155+
156+static int
157+yaml_emitter_check_empty_document(yaml_emitter_t *emitter);
158+
159+static int
160+yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter);
161+
162+static int
163+yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter);
164+
165+static int
166+yaml_emitter_check_simple_key(yaml_emitter_t *emitter);
167+
168+static int
169+yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event);
170+
171+/*
172+ * Processors.
173+ */
174+
175+static int
176+yaml_emitter_process_anchor(yaml_emitter_t *emitter);
177+
178+static int
179+yaml_emitter_process_tag(yaml_emitter_t *emitter);
180+
181+static int
182+yaml_emitter_process_scalar(yaml_emitter_t *emitter);
183+
184+/*
185+ * Analyzers.
186+ */
187+
188+static int
189+yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
190+ yaml_version_directive_t version_directive);
191+
192+static int
193+yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
194+ yaml_tag_directive_t tag_directive);
195+
196+static int
197+yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
198+ yaml_char_t *anchor, int alias);
199+
200+static int
201+yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
202+ yaml_char_t *tag);
203+
204+static int
205+yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
206+ yaml_char_t *value, size_t length);
207+
208+static int
209+yaml_emitter_analyze_event(yaml_emitter_t *emitter,
210+ yaml_event_t *event);
211+
212+/*
213+ * Writers.
214+ */
215+
216+static int
217+yaml_emitter_write_bom(yaml_emitter_t *emitter);
218+
219+static int
220+yaml_emitter_write_indent(yaml_emitter_t *emitter);
221+
222+static int
223+yaml_emitter_write_indicator(yaml_emitter_t *emitter,
224+ char *indicator, int need_whitespace,
225+ int is_whitespace, int is_indention);
226+
227+static int
228+yaml_emitter_write_anchor(yaml_emitter_t *emitter,
229+ yaml_char_t *value, size_t length);
230+
231+static int
232+yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
233+ yaml_char_t *value, size_t length);
234+
235+static int
236+yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
237+ yaml_char_t *value, size_t length, int need_whitespace);
238+
239+static int
240+yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
241+ yaml_char_t *value, size_t length, int allow_breaks);
242+
243+static int
244+yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
245+ yaml_char_t *value, size_t length, int allow_breaks);
246+
247+static int
248+yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
249+ yaml_char_t *value, size_t length, int allow_breaks);
250+
251+static int
252+yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
253+ yaml_string_t string);
254+
255+static int
256+yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
257+ yaml_char_t *value, size_t length);
258+
259+static int
260+yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
261+ yaml_char_t *value, size_t length);
262+
263+/*
264+ * Set an emitter error and return 0.
265+ */
266+
267+static int
268+yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem)
269+{
270+ emitter->error = YAML_EMITTER_ERROR;
271+ emitter->problem = problem;
272+
273+ return 0;
274+}
275+
276+/*
277+ * Emit an event.
278+ */
279+
280+YAML_DECLARE(int)
281+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event)
282+{
283+ if (!ENQUEUE(emitter, emitter->events, *event)) {
284+ yaml_event_delete(event);
285+ return 0;
286+ }
287+
288+ while (!yaml_emitter_need_more_events(emitter)) {
289+ if (!yaml_emitter_analyze_event(emitter, emitter->events.head))
290+ return 0;
291+ if (!yaml_emitter_state_machine(emitter, emitter->events.head))
292+ return 0;
293+ yaml_event_delete(&DEQUEUE(emitter, emitter->events));
294+ }
295+
296+ return 1;
297+}
298+
299+/*
300+ * Check if we need to accumulate more events before emitting.
301+ *
302+ * We accumulate extra
303+ * - 1 event for DOCUMENT-START
304+ * - 2 events for SEQUENCE-START
305+ * - 3 events for MAPPING-START
306+ */
307+
308+static int
309+yaml_emitter_need_more_events(yaml_emitter_t *emitter)
310+{
311+ int level = 0;
312+ int accumulate = 0;
313+ yaml_event_t *event;
314+
315+ if (QUEUE_EMPTY(emitter, emitter->events))
316+ return 1;
317+
318+ switch (emitter->events.head->type) {
319+ case YAML_DOCUMENT_START_EVENT:
320+ accumulate = 1;
321+ break;
322+ case YAML_SEQUENCE_START_EVENT:
323+ accumulate = 2;
324+ break;
325+ case YAML_MAPPING_START_EVENT:
326+ accumulate = 3;
327+ break;
328+ default:
329+ return 0;
330+ }
331+
332+ if (emitter->events.tail - emitter->events.head > accumulate)
333+ return 0;
334+
335+ for (event = emitter->events.head; event != emitter->events.tail; event ++) {
336+ switch (event->type) {
337+ case YAML_STREAM_START_EVENT:
338+ case YAML_DOCUMENT_START_EVENT:
339+ case YAML_SEQUENCE_START_EVENT:
340+ case YAML_MAPPING_START_EVENT:
341+ level += 1;
342+ break;
343+ case YAML_STREAM_END_EVENT:
344+ case YAML_DOCUMENT_END_EVENT:
345+ case YAML_SEQUENCE_END_EVENT:
346+ case YAML_MAPPING_END_EVENT:
347+ level -= 1;
348+ break;
349+ default:
350+ break;
351+ }
352+ if (!level)
353+ return 0;
354+ }
355+
356+ return 1;
357+}
358+
359+/*
360+ * Append a directive to the directives stack.
361+ */
362+
363+static int
364+yaml_emitter_append_tag_directive(yaml_emitter_t *emitter,
365+ yaml_tag_directive_t value, int allow_duplicates)
366+{
367+ yaml_tag_directive_t *tag_directive;
368+ yaml_tag_directive_t copy = { NULL, NULL };
369+
370+ for (tag_directive = emitter->tag_directives.start;
371+ tag_directive != emitter->tag_directives.top; tag_directive ++) {
372+ if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
373+ if (allow_duplicates)
374+ return 1;
375+ return yaml_emitter_set_emitter_error(emitter,
376+ "duplicate %TAG directive");
377+ }
378+ }
379+
380+ copy.handle = yaml_strdup(value.handle);
381+ copy.prefix = yaml_strdup(value.prefix);
382+ if (!copy.handle || !copy.prefix) {
383+ emitter->error = YAML_MEMORY_ERROR;
384+ goto error;
385+ }
386+
387+ if (!PUSH(emitter, emitter->tag_directives, copy))
388+ goto error;
389+
390+ return 1;
391+
392+error:
393+ yaml_free(copy.handle);
394+ yaml_free(copy.prefix);
395+ return 0;
396+}
397+
398+/*
399+ * Increase the indentation level.
400+ */
401+
402+static int
403+yaml_emitter_increase_indent(yaml_emitter_t *emitter,
404+ int flow, int indentless)
405+{
406+ if (!PUSH(emitter, emitter->indents, emitter->indent))
407+ return 0;
408+
409+ if (emitter->indent < 0) {
410+ emitter->indent = flow ? emitter->best_indent : 0;
411+ }
412+ else if (!indentless) {
413+ emitter->indent += emitter->best_indent;
414+ }
415+
416+ return 1;
417+}
418+
419+/*
420+ * State dispatcher.
421+ */
422+
423+static int
424+yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event)
425+{
426+ switch (emitter->state)
427+ {
428+ case YAML_EMIT_STREAM_START_STATE:
429+ return yaml_emitter_emit_stream_start(emitter, event);
430+
431+ case YAML_EMIT_FIRST_DOCUMENT_START_STATE:
432+ return yaml_emitter_emit_document_start(emitter, event, 1);
433+
434+ case YAML_EMIT_DOCUMENT_START_STATE:
435+ return yaml_emitter_emit_document_start(emitter, event, 0);
436+
437+ case YAML_EMIT_DOCUMENT_CONTENT_STATE:
438+ return yaml_emitter_emit_document_content(emitter, event);
439+
440+ case YAML_EMIT_DOCUMENT_END_STATE:
441+ return yaml_emitter_emit_document_end(emitter, event);
442+
443+ case YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
444+ return yaml_emitter_emit_flow_sequence_item(emitter, event, 1);
445+
446+ case YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE:
447+ return yaml_emitter_emit_flow_sequence_item(emitter, event, 0);
448+
449+ case YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
450+ return yaml_emitter_emit_flow_mapping_key(emitter, event, 1);
451+
452+ case YAML_EMIT_FLOW_MAPPING_KEY_STATE:
453+ return yaml_emitter_emit_flow_mapping_key(emitter, event, 0);
454+
455+ case YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
456+ return yaml_emitter_emit_flow_mapping_value(emitter, event, 1);
457+
458+ case YAML_EMIT_FLOW_MAPPING_VALUE_STATE:
459+ return yaml_emitter_emit_flow_mapping_value(emitter, event, 0);
460+
461+ case YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
462+ return yaml_emitter_emit_block_sequence_item(emitter, event, 1);
463+
464+ case YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
465+ return yaml_emitter_emit_block_sequence_item(emitter, event, 0);
466+
467+ case YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
468+ return yaml_emitter_emit_block_mapping_key(emitter, event, 1);
469+
470+ case YAML_EMIT_BLOCK_MAPPING_KEY_STATE:
471+ return yaml_emitter_emit_block_mapping_key(emitter, event, 0);
472+
473+ case YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
474+ return yaml_emitter_emit_block_mapping_value(emitter, event, 1);
475+
476+ case YAML_EMIT_BLOCK_MAPPING_VALUE_STATE:
477+ return yaml_emitter_emit_block_mapping_value(emitter, event, 0);
478+
479+ case YAML_EMIT_END_STATE:
480+ return yaml_emitter_set_emitter_error(emitter,
481+ "expected nothing after STREAM-END");
482+
483+ default:
484+ assert(1); /* Invalid state. */
485+ }
486+
487+ return 0;
488+}
489+
490+/*
491+ * Expect STREAM-START.
492+ */
493+
494+static int
495+yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
496+ yaml_event_t *event)
497+{
498+ if (event->type == YAML_STREAM_START_EVENT)
499+ {
500+ if (!emitter->encoding) {
501+ emitter->encoding = event->data.stream_start.encoding;
502+ }
503+
504+ if (!emitter->encoding) {
505+ emitter->encoding = YAML_UTF8_ENCODING;
506+ }
507+
508+ if (emitter->best_indent < 2 || emitter->best_indent > 9) {
509+ emitter->best_indent = 2;
510+ }
511+
512+ if (emitter->best_width >= 0
513+ && emitter->best_width <= emitter->best_indent*2) {
514+ emitter->best_width = 80;
515+ }
516+
517+ if (emitter->best_width < 0) {
518+ emitter->best_width = INT_MAX;
519+ }
520+
521+ if (!emitter->line_break) {
522+ emitter->line_break = YAML_LN_BREAK;
523+ }
524+
525+ emitter->indent = -1;
526+
527+ emitter->line = 0;
528+ emitter->column = 0;
529+ emitter->whitespace = 1;
530+ emitter->indention = 1;
531+
532+ if (emitter->encoding != YAML_UTF8_ENCODING) {
533+ if (!yaml_emitter_write_bom(emitter))
534+ return 0;
535+ }
536+
537+ emitter->state = YAML_EMIT_FIRST_DOCUMENT_START_STATE;
538+
539+ return 1;
540+ }
541+
542+ return yaml_emitter_set_emitter_error(emitter,
543+ "expected STREAM-START");
544+}
545+
546+/*
547+ * Expect DOCUMENT-START or STREAM-END.
548+ */
549+
550+static int
551+yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
552+ yaml_event_t *event, int first)
553+{
554+ if (event->type == YAML_DOCUMENT_START_EVENT)
555+ {
556+ yaml_tag_directive_t default_tag_directives[] = {
557+ {(yaml_char_t *)"!", (yaml_char_t *)"!"},
558+ {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
559+ {NULL, NULL}
560+ };
561+ yaml_tag_directive_t *tag_directive;
562+ int implicit;
563+
564+ if (event->data.document_start.version_directive) {
565+ if (!yaml_emitter_analyze_version_directive(emitter,
566+ *event->data.document_start.version_directive))
567+ return 0;
568+ }
569+
570+ for (tag_directive = event->data.document_start.tag_directives.start;
571+ tag_directive != event->data.document_start.tag_directives.end;
572+ tag_directive ++) {
573+ if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive))
574+ return 0;
575+ if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0))
576+ return 0;
577+ }
578+
579+ for (tag_directive = default_tag_directives;
580+ tag_directive->handle; tag_directive ++) {
581+ if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 1))
582+ return 0;
583+ }
584+
585+ implicit = event->data.document_start.implicit;
586+ if (!first || emitter->canonical) {
587+ implicit = 0;
588+ }
589+
590+ if ((event->data.document_start.version_directive ||
591+ (event->data.document_start.tag_directives.start
592+ != event->data.document_start.tag_directives.end)) &&
593+ emitter->open_ended)
594+ {
595+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
596+ return 0;
597+ if (!yaml_emitter_write_indent(emitter))
598+ return 0;
599+ }
600+
601+ if (event->data.document_start.version_directive) {
602+ implicit = 0;
603+ if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0))
604+ return 0;
605+ if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0))
606+ return 0;
607+ if (!yaml_emitter_write_indent(emitter))
608+ return 0;
609+ }
610+
611+ if (event->data.document_start.tag_directives.start
612+ != event->data.document_start.tag_directives.end) {
613+ implicit = 0;
614+ for (tag_directive = event->data.document_start.tag_directives.start;
615+ tag_directive != event->data.document_start.tag_directives.end;
616+ tag_directive ++) {
617+ if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0))
618+ return 0;
619+ if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle,
620+ strlen((char *)tag_directive->handle)))
621+ return 0;
622+ if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix,
623+ strlen((char *)tag_directive->prefix), 1))
624+ return 0;
625+ if (!yaml_emitter_write_indent(emitter))
626+ return 0;
627+ }
628+ }
629+
630+ if (yaml_emitter_check_empty_document(emitter)) {
631+ implicit = 0;
632+ }
633+
634+ if (!implicit) {
635+ if (!yaml_emitter_write_indent(emitter))
636+ return 0;
637+ if (!yaml_emitter_write_indicator(emitter, "---", 1, 0, 0))
638+ return 0;
639+ if (emitter->canonical) {
640+ if (!yaml_emitter_write_indent(emitter))
641+ return 0;
642+ }
643+ }
644+
645+ emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
646+
647+ return 1;
648+ }
649+
650+ else if (event->type == YAML_STREAM_END_EVENT)
651+ {
652+ if (emitter->open_ended)
653+ {
654+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
655+ return 0;
656+ if (!yaml_emitter_write_indent(emitter))
657+ return 0;
658+ }
659+
660+ if (!yaml_emitter_flush(emitter))
661+ return 0;
662+
663+ emitter->state = YAML_EMIT_END_STATE;
664+
665+ return 1;
666+ }
667+
668+ return yaml_emitter_set_emitter_error(emitter,
669+ "expected DOCUMENT-START or STREAM-END");
670+}
671+
672+/*
673+ * Expect the root node.
674+ */
675+
676+static int
677+yaml_emitter_emit_document_content(yaml_emitter_t *emitter,
678+ yaml_event_t *event)
679+{
680+ if (!PUSH(emitter, emitter->states, YAML_EMIT_DOCUMENT_END_STATE))
681+ return 0;
682+
683+ return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0);
684+}
685+
686+/*
687+ * Expect DOCUMENT-END.
688+ */
689+
690+static int
691+yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
692+ yaml_event_t *event)
693+{
694+ if (event->type == YAML_DOCUMENT_END_EVENT)
695+ {
696+ if (!yaml_emitter_write_indent(emitter))
697+ return 0;
698+ if (!event->data.document_end.implicit) {
699+ if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
700+ return 0;
701+ if (!yaml_emitter_write_indent(emitter))
702+ return 0;
703+ }
704+ if (!yaml_emitter_flush(emitter))
705+ return 0;
706+
707+ emitter->state = YAML_EMIT_DOCUMENT_START_STATE;
708+
709+ while (!STACK_EMPTY(emitter, emitter->tag_directives)) {
710+ yaml_tag_directive_t tag_directive = POP(emitter,
711+ emitter->tag_directives);
712+ yaml_free(tag_directive.handle);
713+ yaml_free(tag_directive.prefix);
714+ }
715+
716+ return 1;
717+ }
718+
719+ return yaml_emitter_set_emitter_error(emitter,
720+ "expected DOCUMENT-END");
721+}
722+
723+/*
724+ *
725+ * Expect a flow item node.
726+ */
727+
728+static int
729+yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter,
730+ yaml_event_t *event, int first)
731+{
732+ if (first)
733+ {
734+ if (!yaml_emitter_write_indicator(emitter, "[", 1, 1, 0))
735+ return 0;
736+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
737+ return 0;
738+ emitter->flow_level ++;
739+ }
740+
741+ if (event->type == YAML_SEQUENCE_END_EVENT)
742+ {
743+ emitter->flow_level --;
744+ emitter->indent = POP(emitter, emitter->indents);
745+ if (emitter->canonical && !first) {
746+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
747+ return 0;
748+ if (!yaml_emitter_write_indent(emitter))
749+ return 0;
750+ }
751+ if (!yaml_emitter_write_indicator(emitter, "]", 0, 0, 0))
752+ return 0;
753+ emitter->state = POP(emitter, emitter->states);
754+
755+ return 1;
756+ }
757+
758+ if (!first) {
759+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
760+ return 0;
761+ }
762+
763+ if (emitter->canonical || emitter->column > emitter->best_width) {
764+ if (!yaml_emitter_write_indent(emitter))
765+ return 0;
766+ }
767+ if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE))
768+ return 0;
769+
770+ return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
771+}
772+
773+/*
774+ * Expect a flow key node.
775+ */
776+
777+static int
778+yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter,
779+ yaml_event_t *event, int first)
780+{
781+ if (first)
782+ {
783+ if (!yaml_emitter_write_indicator(emitter, "{", 1, 1, 0))
784+ return 0;
785+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
786+ return 0;
787+ emitter->flow_level ++;
788+ }
789+
790+ if (event->type == YAML_MAPPING_END_EVENT)
791+ {
792+ emitter->flow_level --;
793+ emitter->indent = POP(emitter, emitter->indents);
794+ if (emitter->canonical && !first) {
795+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
796+ return 0;
797+ if (!yaml_emitter_write_indent(emitter))
798+ return 0;
799+ }
800+ if (!yaml_emitter_write_indicator(emitter, "}", 0, 0, 0))
801+ return 0;
802+ emitter->state = POP(emitter, emitter->states);
803+
804+ return 1;
805+ }
806+
807+ if (!first) {
808+ if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0))
809+ return 0;
810+ }
811+ if (emitter->canonical || emitter->column > emitter->best_width) {
812+ if (!yaml_emitter_write_indent(emitter))
813+ return 0;
814+ }
815+
816+ if (!emitter->canonical && yaml_emitter_check_simple_key(emitter))
817+ {
818+ if (!PUSH(emitter, emitter->states,
819+ YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE))
820+ return 0;
821+
822+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
823+ }
824+ else
825+ {
826+ if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 0))
827+ return 0;
828+ if (!PUSH(emitter, emitter->states,
829+ YAML_EMIT_FLOW_MAPPING_VALUE_STATE))
830+ return 0;
831+
832+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
833+ }
834+}
835+
836+/*
837+ * Expect a flow value node.
838+ */
839+
840+static int
841+yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter,
842+ yaml_event_t *event, int simple)
843+{
844+ if (simple) {
845+ if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
846+ return 0;
847+ }
848+ else {
849+ if (emitter->canonical || emitter->column > emitter->best_width) {
850+ if (!yaml_emitter_write_indent(emitter))
851+ return 0;
852+ }
853+ if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 0))
854+ return 0;
855+ }
856+ if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_MAPPING_KEY_STATE))
857+ return 0;
858+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
859+}
860+
861+/*
862+ * Expect a block item node.
863+ */
864+
865+static int
866+yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter,
867+ yaml_event_t *event, int first)
868+{
869+ if (first)
870+ {
871+ if (!yaml_emitter_increase_indent(emitter, 0,
872+ (emitter->mapping_context && !emitter->indention)))
873+ return 0;
874+ }
875+
876+ if (event->type == YAML_SEQUENCE_END_EVENT)
877+ {
878+ emitter->indent = POP(emitter, emitter->indents);
879+ emitter->state = POP(emitter, emitter->states);
880+
881+ return 1;
882+ }
883+
884+ if (!yaml_emitter_write_indent(emitter))
885+ return 0;
886+ if (!yaml_emitter_write_indicator(emitter, "-", 1, 0, 1))
887+ return 0;
888+ if (!PUSH(emitter, emitter->states,
889+ YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE))
890+ return 0;
891+
892+ return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0);
893+}
894+
895+/*
896+ * Expect a block key node.
897+ */
898+
899+static int
900+yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter,
901+ yaml_event_t *event, int first)
902+{
903+ if (first)
904+ {
905+ if (!yaml_emitter_increase_indent(emitter, 0, 0))
906+ return 0;
907+ }
908+
909+ if (event->type == YAML_MAPPING_END_EVENT)
910+ {
911+ emitter->indent = POP(emitter, emitter->indents);
912+ emitter->state = POP(emitter, emitter->states);
913+
914+ return 1;
915+ }
916+
917+ if (!yaml_emitter_write_indent(emitter))
918+ return 0;
919+
920+ if (yaml_emitter_check_simple_key(emitter))
921+ {
922+ if (!PUSH(emitter, emitter->states,
923+ YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE))
924+ return 0;
925+
926+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1);
927+ }
928+ else
929+ {
930+ if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 1))
931+ return 0;
932+ if (!PUSH(emitter, emitter->states,
933+ YAML_EMIT_BLOCK_MAPPING_VALUE_STATE))
934+ return 0;
935+
936+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
937+ }
938+}
939+
940+/*
941+ * Expect a block value node.
942+ */
943+
944+static int
945+yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter,
946+ yaml_event_t *event, int simple)
947+{
948+ if (simple) {
949+ if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0))
950+ return 0;
951+ }
952+ else {
953+ if (!yaml_emitter_write_indent(emitter))
954+ return 0;
955+ if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 1))
956+ return 0;
957+ }
958+ if (!PUSH(emitter, emitter->states,
959+ YAML_EMIT_BLOCK_MAPPING_KEY_STATE))
960+ return 0;
961+
962+ return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0);
963+}
964+
965+/*
966+ * Expect a node.
967+ */
968+
969+static int
970+yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event,
971+ int root, int sequence, int mapping, int simple_key)
972+{
973+ emitter->root_context = root;
974+ emitter->sequence_context = sequence;
975+ emitter->mapping_context = mapping;
976+ emitter->simple_key_context = simple_key;
977+
978+ switch (event->type)
979+ {
980+ case YAML_ALIAS_EVENT:
981+ return yaml_emitter_emit_alias(emitter, event);
982+
983+ case YAML_SCALAR_EVENT:
984+ return yaml_emitter_emit_scalar(emitter, event);
985+
986+ case YAML_SEQUENCE_START_EVENT:
987+ return yaml_emitter_emit_sequence_start(emitter, event);
988+
989+ case YAML_MAPPING_START_EVENT:
990+ return yaml_emitter_emit_mapping_start(emitter, event);
991+
992+ default:
993+ return yaml_emitter_set_emitter_error(emitter,
994+ "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS");
995+ }
996+
997+ return 0;
998+}
999+
1000+/*
1001+ * Expect ALIAS.
1002+ */
1003+
1004+static int
1005+yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event)
1006+{
1007+ if (!yaml_emitter_process_anchor(emitter))
1008+ return 0;
1009+ emitter->state = POP(emitter, emitter->states);
1010+
1011+ return 1;
1012+}
1013+
1014+/*
1015+ * Expect SCALAR.
1016+ */
1017+
1018+static int
1019+yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event)
1020+{
1021+ if (!yaml_emitter_select_scalar_style(emitter, event))
1022+ return 0;
1023+ if (!yaml_emitter_process_anchor(emitter))
1024+ return 0;
1025+ if (!yaml_emitter_process_tag(emitter))
1026+ return 0;
1027+ if (!yaml_emitter_increase_indent(emitter, 1, 0))
1028+ return 0;
1029+ if (!yaml_emitter_process_scalar(emitter))
1030+ return 0;
1031+ emitter->indent = POP(emitter, emitter->indents);
1032+ emitter->state = POP(emitter, emitter->states);
1033+
1034+ return 1;
1035+}
1036+
1037+/*
1038+ * Expect SEQUENCE-START.
1039+ */
1040+
1041+static int
1042+yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event)
1043+{
1044+ if (!yaml_emitter_process_anchor(emitter))
1045+ return 0;
1046+ if (!yaml_emitter_process_tag(emitter))
1047+ return 0;
1048+
1049+ if (emitter->flow_level || emitter->canonical
1050+ || event->data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE
1051+ || yaml_emitter_check_empty_sequence(emitter)) {
1052+ emitter->state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE;
1053+ }
1054+ else {
1055+ emitter->state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE;
1056+ }
1057+
1058+ return 1;
1059+}
1060+
1061+/*
1062+ * Expect MAPPING-START.
1063+ */
1064+
1065+static int
1066+yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event)
1067+{
1068+ if (!yaml_emitter_process_anchor(emitter))
1069+ return 0;
1070+ if (!yaml_emitter_process_tag(emitter))
1071+ return 0;
1072+
1073+ if (emitter->flow_level || emitter->canonical
1074+ || event->data.mapping_start.style == YAML_FLOW_MAPPING_STYLE
1075+ || yaml_emitter_check_empty_mapping(emitter)) {
1076+ emitter->state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE;
1077+ }
1078+ else {
1079+ emitter->state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE;
1080+ }
1081+
1082+ return 1;
1083+}
1084+
1085+/*
1086+ * Check if the document content is an empty scalar.
1087+ */
1088+
1089+static int
1090+yaml_emitter_check_empty_document(yaml_emitter_t *emitter)
1091+{
1092+ return 0;
1093+}
1094+
1095+/*
1096+ * Check if the next events represent an empty sequence.
1097+ */
1098+
1099+static int
1100+yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter)
1101+{
1102+ if (emitter->events.tail - emitter->events.head < 2)
1103+ return 0;
1104+
1105+ return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT
1106+ && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT);
1107+}
1108+
1109+/*
1110+ * Check if the next events represent an empty mapping.
1111+ */
1112+
1113+static int
1114+yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter)
1115+{
1116+ if (emitter->events.tail - emitter->events.head < 2)
1117+ return 0;
1118+
1119+ return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT
1120+ && emitter->events.head[1].type == YAML_MAPPING_END_EVENT);
1121+}
1122+
1123+/*
1124+ * Check if the next node can be expressed as a simple key.
1125+ */
1126+
1127+static int
1128+yaml_emitter_check_simple_key(yaml_emitter_t *emitter)
1129+{
1130+ yaml_event_t *event = emitter->events.head;
1131+ size_t length = 0;
1132+
1133+ switch (event->type)
1134+ {
1135+ case YAML_ALIAS_EVENT:
1136+ length += emitter->anchor_data.anchor_length;
1137+ break;
1138+
1139+ case YAML_SCALAR_EVENT:
1140+ if (emitter->scalar_data.multiline)
1141+ return 0;
1142+ length += emitter->anchor_data.anchor_length
1143+ + emitter->tag_data.handle_length
1144+ + emitter->tag_data.suffix_length
1145+ + emitter->scalar_data.length;
1146+ break;
1147+
1148+ case YAML_SEQUENCE_START_EVENT:
1149+ if (!yaml_emitter_check_empty_sequence(emitter))
1150+ return 0;
1151+ length += emitter->anchor_data.anchor_length
1152+ + emitter->tag_data.handle_length
1153+ + emitter->tag_data.suffix_length;
1154+ break;
1155+
1156+ case YAML_MAPPING_START_EVENT:
1157+ if (!yaml_emitter_check_empty_sequence(emitter))
1158+ return 0;
1159+ length += emitter->anchor_data.anchor_length
1160+ + emitter->tag_data.handle_length
1161+ + emitter->tag_data.suffix_length;
1162+ break;
1163+
1164+ default:
1165+ return 0;
1166+ }
1167+
1168+ if (length > 128)
1169+ return 0;
1170+
1171+ return 1;
1172+}
1173+
1174+/*
1175+ * Determine an acceptable scalar style.
1176+ */
1177+
1178+static int
1179+yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event)
1180+{
1181+ yaml_scalar_style_t style = event->data.scalar.style;
1182+ int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix);
1183+
1184+ if (no_tag && !event->data.scalar.plain_implicit
1185+ && !event->data.scalar.quoted_implicit) {
1186+ return yaml_emitter_set_emitter_error(emitter,
1187+ "neither tag nor implicit flags are specified");
1188+ }
1189+
1190+ if (style == YAML_ANY_SCALAR_STYLE)
1191+ style = YAML_PLAIN_SCALAR_STYLE;
1192+
1193+ if (emitter->canonical)
1194+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
1195+
1196+ if (emitter->simple_key_context && emitter->scalar_data.multiline)
1197+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
1198+
1199+ if (style == YAML_PLAIN_SCALAR_STYLE)
1200+ {
1201+ if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed)
1202+ || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed))
1203+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
1204+ if (!emitter->scalar_data.length
1205+ && (emitter->flow_level || emitter->simple_key_context))
1206+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
1207+ if (no_tag && !event->data.scalar.plain_implicit)
1208+ style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
1209+ }
1210+
1211+ if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE)
1212+ {
1213+ if (!emitter->scalar_data.single_quoted_allowed)
1214+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
1215+ }
1216+
1217+ if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE)
1218+ {
1219+ if (!emitter->scalar_data.block_allowed
1220+ || emitter->flow_level || emitter->simple_key_context)
1221+ style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
1222+ }
1223+
1224+ if (no_tag && !event->data.scalar.quoted_implicit
1225+ && style != YAML_PLAIN_SCALAR_STYLE)
1226+ {
1227+ emitter->tag_data.handle = (yaml_char_t *)"!";
1228+ emitter->tag_data.handle_length = 1;
1229+ }
1230+
1231+ emitter->scalar_data.style = style;
1232+
1233+ return 1;
1234+}
1235+
1236+/*
1237+ * Write an achor.
1238+ */
1239+
1240+static int
1241+yaml_emitter_process_anchor(yaml_emitter_t *emitter)
1242+{
1243+ if (!emitter->anchor_data.anchor)
1244+ return 1;
1245+
1246+ if (!yaml_emitter_write_indicator(emitter,
1247+ (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0))
1248+ return 0;
1249+
1250+ return yaml_emitter_write_anchor(emitter,
1251+ emitter->anchor_data.anchor, emitter->anchor_data.anchor_length);
1252+}
1253+
1254+/*
1255+ * Write a tag.
1256+ */
1257+
1258+static int
1259+yaml_emitter_process_tag(yaml_emitter_t *emitter)
1260+{
1261+ if (!emitter->tag_data.handle && !emitter->tag_data.suffix)
1262+ return 1;
1263+
1264+ if (emitter->tag_data.handle)
1265+ {
1266+ if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle,
1267+ emitter->tag_data.handle_length))
1268+ return 0;
1269+ if (emitter->tag_data.suffix) {
1270+ if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
1271+ emitter->tag_data.suffix_length, 0))
1272+ return 0;
1273+ }
1274+ }
1275+ else
1276+ {
1277+ if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0))
1278+ return 0;
1279+ if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix,
1280+ emitter->tag_data.suffix_length, 0))
1281+ return 0;
1282+ if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0))
1283+ return 0;
1284+ }
1285+
1286+ return 1;
1287+}
1288+
1289+/*
1290+ * Write a scalar.
1291+ */
1292+
1293+static int
1294+yaml_emitter_process_scalar(yaml_emitter_t *emitter)
1295+{
1296+ switch (emitter->scalar_data.style)
1297+ {
1298+ case YAML_PLAIN_SCALAR_STYLE:
1299+ return yaml_emitter_write_plain_scalar(emitter,
1300+ emitter->scalar_data.value, emitter->scalar_data.length,
1301+ !emitter->simple_key_context);
1302+
1303+ case YAML_SINGLE_QUOTED_SCALAR_STYLE:
1304+ return yaml_emitter_write_single_quoted_scalar(emitter,
1305+ emitter->scalar_data.value, emitter->scalar_data.length,
1306+ !emitter->simple_key_context);
1307+
1308+ case YAML_DOUBLE_QUOTED_SCALAR_STYLE:
1309+ return yaml_emitter_write_double_quoted_scalar(emitter,
1310+ emitter->scalar_data.value, emitter->scalar_data.length,
1311+ !emitter->simple_key_context);
1312+
1313+ case YAML_LITERAL_SCALAR_STYLE:
1314+ return yaml_emitter_write_literal_scalar(emitter,
1315+ emitter->scalar_data.value, emitter->scalar_data.length);
1316+
1317+ case YAML_FOLDED_SCALAR_STYLE:
1318+ return yaml_emitter_write_folded_scalar(emitter,
1319+ emitter->scalar_data.value, emitter->scalar_data.length);
1320+
1321+ default:
1322+ assert(1); /* Impossible. */
1323+ }
1324+
1325+ return 0;
1326+}
1327+
1328+/*
1329+ * Check if a %YAML directive is valid.
1330+ */
1331+
1332+static int
1333+yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
1334+ yaml_version_directive_t version_directive)
1335+{
1336+ if (version_directive.major != 1 || version_directive.minor != 1) {
1337+ return yaml_emitter_set_emitter_error(emitter,
1338+ "incompatible %YAML directive");
1339+ }
1340+
1341+ return 1;
1342+}
1343+
1344+/*
1345+ * Check if a %TAG directive is valid.
1346+ */
1347+
1348+static int
1349+yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter,
1350+ yaml_tag_directive_t tag_directive)
1351+{
1352+ yaml_string_t handle = STRING(tag_directive.handle,
1353+ strlen((char *)tag_directive.handle));
1354+ yaml_string_t prefix = STRING(tag_directive.prefix,
1355+ strlen((char *)tag_directive.prefix));
1356+
1357+ if (handle.start == handle.end) {
1358+ return yaml_emitter_set_emitter_error(emitter,
1359+ "tag handle must not be empty");
1360+ }
1361+
1362+ if (handle.start[0] != '!') {
1363+ return yaml_emitter_set_emitter_error(emitter,
1364+ "tag handle must start with '!'");
1365+ }
1366+
1367+ if (handle.end[-1] != '!') {
1368+ return yaml_emitter_set_emitter_error(emitter,
1369+ "tag handle must end with '!'");
1370+ }
1371+
1372+ handle.pointer ++;
1373+
1374+ while (handle.pointer < handle.end-1) {
1375+ if (!IS_ALPHA(handle)) {
1376+ return yaml_emitter_set_emitter_error(emitter,
1377+ "tag handle must contain alphanumerical characters only");
1378+ }
1379+ MOVE(handle);
1380+ }
1381+
1382+ if (prefix.start == prefix.end) {
1383+ return yaml_emitter_set_emitter_error(emitter,
1384+ "tag prefix must not be empty");
1385+ }
1386+
1387+ return 1;
1388+}
1389+
1390+/*
1391+ * Check if an anchor is valid.
1392+ */
1393+
1394+static int
1395+yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
1396+ yaml_char_t *anchor, int alias)
1397+{
1398+ yaml_string_t string = STRING(anchor, strlen((char *)anchor));
1399+
1400+ if (string.start == string.end) {
1401+ return yaml_emitter_set_emitter_error(emitter, alias ?
1402+ "alias value must not be empty" :
1403+ "anchor value must not be empty");
1404+ }
1405+
1406+ while (string.pointer != string.end) {
1407+ if (!IS_ALPHA(string)) {
1408+ return yaml_emitter_set_emitter_error(emitter, alias ?
1409+ "alias value must contain alphanumerical characters only" :
1410+ "anchor value must contain alphanumerical characters only");
1411+ }
1412+ MOVE(string);
1413+ }
1414+
1415+ emitter->anchor_data.anchor = string.start;
1416+ emitter->anchor_data.anchor_length = string.end - string.start;
1417+ emitter->anchor_data.alias = alias;
1418+
1419+ return 1;
1420+}
1421+
1422+/*
1423+ * Check if a tag is valid.
1424+ */
1425+
1426+static int
1427+yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
1428+ yaml_char_t *tag)
1429+{
1430+ yaml_string_t string = STRING(tag, strlen((char *)tag));
1431+ yaml_tag_directive_t *tag_directive;
1432+
1433+ if (string.start == string.end) {
1434+ return yaml_emitter_set_emitter_error(emitter,
1435+ "tag value must not be empty");
1436+ }
1437+
1438+ for (tag_directive = emitter->tag_directives.start;
1439+ tag_directive != emitter->tag_directives.top; tag_directive ++) {
1440+ size_t prefix_length = strlen((char *)tag_directive->prefix);
1441+ if (prefix_length < (size_t)(string.end - string.start)
1442+ && strncmp((char *)tag_directive->prefix, (char *)string.start,
1443+ prefix_length) == 0)
1444+ {
1445+ emitter->tag_data.handle = tag_directive->handle;
1446+ emitter->tag_data.handle_length =
1447+ strlen((char *)tag_directive->handle);
1448+ emitter->tag_data.suffix = string.start + prefix_length;
1449+ emitter->tag_data.suffix_length =
1450+ (string.end - string.start) - prefix_length;
1451+ return 1;
1452+ }
1453+ }
1454+
1455+ emitter->tag_data.suffix = string.start;
1456+ emitter->tag_data.suffix_length = string.end - string.start;
1457+
1458+ return 1;
1459+}
1460+
1461+/*
1462+ * Check if a scalar is valid.
1463+ */
1464+
1465+static int
1466+yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
1467+ yaml_char_t *value, size_t length)
1468+{
1469+ yaml_string_t string = STRING(value, length);
1470+
1471+ int block_indicators = 0;
1472+ int flow_indicators = 0;
1473+ int line_breaks = 0;
1474+ int special_characters = 0;
1475+
1476+ int leading_space = 0;
1477+ int leading_break = 0;
1478+ int trailing_space = 0;
1479+ int trailing_break = 0;
1480+ int break_space = 0;
1481+ int space_break = 0;
1482+
1483+ int preceeded_by_whitespace = 0;
1484+ int followed_by_whitespace = 0;
1485+ int previous_space = 0;
1486+ int previous_break = 0;
1487+
1488+ emitter->scalar_data.value = value;
1489+ emitter->scalar_data.length = length;
1490+
1491+ if (string.start == string.end)
1492+ {
1493+ emitter->scalar_data.multiline = 0;
1494+ emitter->scalar_data.flow_plain_allowed = 0;
1495+ emitter->scalar_data.block_plain_allowed = 1;
1496+ emitter->scalar_data.single_quoted_allowed = 1;
1497+ emitter->scalar_data.block_allowed = 0;
1498+
1499+ return 1;
1500+ }
1501+
1502+ if ((CHECK_AT(string, '-', 0)
1503+ && CHECK_AT(string, '-', 1)
1504+ && CHECK_AT(string, '-', 2))
1505+ || (CHECK_AT(string, '.', 0)
1506+ && CHECK_AT(string, '.', 1)
1507+ && CHECK_AT(string, '.', 2))) {
1508+ block_indicators = 1;
1509+ flow_indicators = 1;
1510+ }
1511+
1512+ preceeded_by_whitespace = 1;
1513+ followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
1514+
1515+ while (string.pointer != string.end)
1516+ {
1517+ if (string.start == string.pointer)
1518+ {
1519+ if (CHECK(string, '#') || CHECK(string, ',')
1520+ || CHECK(string, '[') || CHECK(string, ']')
1521+ || CHECK(string, '{') || CHECK(string, '}')
1522+ || CHECK(string, '&') || CHECK(string, '*')
1523+ || CHECK(string, '!') || CHECK(string, '|')
1524+ || CHECK(string, '>') || CHECK(string, '\'')
1525+ || CHECK(string, '"') || CHECK(string, '%')
1526+ || CHECK(string, '@') || CHECK(string, '`')) {
1527+ flow_indicators = 1;
1528+ block_indicators = 1;
1529+ }
1530+
1531+ if (CHECK(string, '?') || CHECK(string, ':')) {
1532+ flow_indicators = 1;
1533+ if (followed_by_whitespace) {
1534+ block_indicators = 1;
1535+ }
1536+ }
1537+
1538+ if (CHECK(string, '-') && followed_by_whitespace) {
1539+ flow_indicators = 1;
1540+ block_indicators = 1;
1541+ }
1542+ }
1543+ else
1544+ {
1545+ if (CHECK(string, ',') || CHECK(string, '?')
1546+ || CHECK(string, '[') || CHECK(string, ']')
1547+ || CHECK(string, '{') || CHECK(string, '}')) {
1548+ flow_indicators = 1;
1549+ }
1550+
1551+ if (CHECK(string, ':')) {
1552+ flow_indicators = 1;
1553+ if (followed_by_whitespace) {
1554+ block_indicators = 1;
1555+ }
1556+ }
1557+
1558+ if (CHECK(string, '#') && preceeded_by_whitespace) {
1559+ flow_indicators = 1;
1560+ block_indicators = 1;
1561+ }
1562+ }
1563+
1564+ if (!IS_PRINTABLE(string)
1565+ || (!IS_ASCII(string) && !emitter->unicode)) {
1566+ special_characters = 1;
1567+ }
1568+
1569+ if (IS_BREAK(string)) {
1570+ line_breaks = 1;
1571+ }
1572+
1573+ if (IS_SPACE(string))
1574+ {
1575+ if (string.start == string.pointer) {
1576+ leading_space = 1;
1577+ }
1578+ if (string.pointer+WIDTH(string) == string.end) {
1579+ trailing_space = 1;
1580+ }
1581+ if (previous_break) {
1582+ break_space = 1;
1583+ }
1584+ previous_space = 1;
1585+ previous_break = 0;
1586+ }
1587+ else if (IS_BREAK(string))
1588+ {
1589+ if (string.start == string.pointer) {
1590+ leading_break = 1;
1591+ }
1592+ if (string.pointer+WIDTH(string) == string.end) {
1593+ trailing_break = 1;
1594+ }
1595+ if (previous_space) {
1596+ space_break = 1;
1597+ }
1598+ previous_space = 0;
1599+ previous_break = 1;
1600+ }
1601+ else
1602+ {
1603+ previous_space = 0;
1604+ previous_break = 0;
1605+ }
1606+
1607+ preceeded_by_whitespace = IS_BLANKZ(string);
1608+ MOVE(string);
1609+ if (string.pointer != string.end) {
1610+ followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
1611+ }
1612+ }
1613+
1614+ emitter->scalar_data.multiline = line_breaks;
1615+
1616+ emitter->scalar_data.flow_plain_allowed = 1;
1617+ emitter->scalar_data.block_plain_allowed = 1;
1618+ emitter->scalar_data.single_quoted_allowed = 1;
1619+ emitter->scalar_data.block_allowed = 1;
1620+
1621+ if (leading_space || leading_break || trailing_space || trailing_break) {
1622+ emitter->scalar_data.flow_plain_allowed = 0;
1623+ emitter->scalar_data.block_plain_allowed = 0;
1624+ }
1625+
1626+ if (trailing_space) {
1627+ emitter->scalar_data.block_allowed = 0;
1628+ }
1629+
1630+ if (break_space) {
1631+ emitter->scalar_data.flow_plain_allowed = 0;
1632+ emitter->scalar_data.block_plain_allowed = 0;
1633+ emitter->scalar_data.single_quoted_allowed = 0;
1634+ }
1635+
1636+ if (space_break || special_characters) {
1637+ emitter->scalar_data.flow_plain_allowed = 0;
1638+ emitter->scalar_data.block_plain_allowed = 0;
1639+ emitter->scalar_data.single_quoted_allowed = 0;
1640+ emitter->scalar_data.block_allowed = 0;
1641+ }
1642+
1643+ if (line_breaks) {
1644+ emitter->scalar_data.flow_plain_allowed = 0;
1645+ emitter->scalar_data.block_plain_allowed = 0;
1646+ }
1647+
1648+ if (flow_indicators) {
1649+ emitter->scalar_data.flow_plain_allowed = 0;
1650+ }
1651+
1652+ if (block_indicators) {
1653+ emitter->scalar_data.block_plain_allowed = 0;
1654+ }
1655+
1656+ return 1;
1657+}
1658+
1659+/*
1660+ * Check if the event data is valid.
1661+ */
1662+
1663+static int
1664+yaml_emitter_analyze_event(yaml_emitter_t *emitter,
1665+ yaml_event_t *event)
1666+{
1667+ emitter->anchor_data.anchor = NULL;
1668+ emitter->anchor_data.anchor_length = 0;
1669+ emitter->tag_data.handle = NULL;
1670+ emitter->tag_data.handle_length = 0;
1671+ emitter->tag_data.suffix = NULL;
1672+ emitter->tag_data.suffix_length = 0;
1673+ emitter->scalar_data.value = NULL;
1674+ emitter->scalar_data.length = 0;
1675+
1676+ switch (event->type)
1677+ {
1678+ case YAML_ALIAS_EVENT:
1679+ if (!yaml_emitter_analyze_anchor(emitter,
1680+ event->data.alias.anchor, 1))
1681+ return 0;
1682+ return 1;
1683+
1684+ case YAML_SCALAR_EVENT:
1685+ if (event->data.scalar.anchor) {
1686+ if (!yaml_emitter_analyze_anchor(emitter,
1687+ event->data.scalar.anchor, 0))
1688+ return 0;
1689+ }
1690+ if (event->data.scalar.tag && (emitter->canonical ||
1691+ (!event->data.scalar.plain_implicit
1692+ && !event->data.scalar.quoted_implicit))) {
1693+ if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
1694+ return 0;
1695+ }
1696+ if (!yaml_emitter_analyze_scalar(emitter,
1697+ event->data.scalar.value, event->data.scalar.length))
1698+ return 0;
1699+ return 1;
1700+
1701+ case YAML_SEQUENCE_START_EVENT:
1702+ if (event->data.sequence_start.anchor) {
1703+ if (!yaml_emitter_analyze_anchor(emitter,
1704+ event->data.sequence_start.anchor, 0))
1705+ return 0;
1706+ }
1707+ if (event->data.sequence_start.tag && (emitter->canonical ||
1708+ !event->data.sequence_start.implicit)) {
1709+ if (!yaml_emitter_analyze_tag(emitter,
1710+ event->data.sequence_start.tag))
1711+ return 0;
1712+ }
1713+ return 1;
1714+
1715+ case YAML_MAPPING_START_EVENT:
1716+ if (event->data.mapping_start.anchor) {
1717+ if (!yaml_emitter_analyze_anchor(emitter,
1718+ event->data.mapping_start.anchor, 0))
1719+ return 0;
1720+ }
1721+ if (event->data.mapping_start.tag && (emitter->canonical ||
1722+ !event->data.mapping_start.implicit)) {
1723+ if (!yaml_emitter_analyze_tag(emitter,
1724+ event->data.mapping_start.tag))
1725+ return 0;
1726+ }
1727+ return 1;
1728+
1729+ default:
1730+ return 1;
1731+ }
1732+}
1733+
1734+/*
1735+ * Write the BOM character.
1736+ */
1737+
1738+static int
1739+yaml_emitter_write_bom(yaml_emitter_t *emitter)
1740+{
1741+ if (!FLUSH(emitter)) return 0;
1742+
1743+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF';
1744+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB';
1745+ *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF';
1746+
1747+ return 1;
1748+}
1749+
1750+static int
1751+yaml_emitter_write_indent(yaml_emitter_t *emitter)
1752+{
1753+ int indent = (emitter->indent >= 0) ? emitter->indent : 0;
1754+
1755+ if (!emitter->indention || emitter->column > indent
1756+ || (emitter->column == indent && !emitter->whitespace)) {
1757+ if (!PUT_BREAK(emitter)) return 0;
1758+ }
1759+
1760+ while (emitter->column < indent) {
1761+ if (!PUT(emitter, ' ')) return 0;
1762+ }
1763+
1764+ emitter->whitespace = 1;
1765+ emitter->indention = 1;
1766+
1767+ return 1;
1768+}
1769+
1770+static int
1771+yaml_emitter_write_indicator(yaml_emitter_t *emitter,
1772+ char *indicator, int need_whitespace,
1773+ int is_whitespace, int is_indention)
1774+{
1775+ yaml_string_t string = STRING((yaml_char_t *)indicator, strlen(indicator));
1776+
1777+ if (need_whitespace && !emitter->whitespace) {
1778+ if (!PUT(emitter, ' ')) return 0;
1779+ }
1780+
1781+ while (string.pointer != string.end) {
1782+ if (!WRITE(emitter, string)) return 0;
1783+ }
1784+
1785+ emitter->whitespace = is_whitespace;
1786+ emitter->indention = (emitter->indention && is_indention);
1787+ emitter->open_ended = 0;
1788+
1789+ return 1;
1790+}
1791+
1792+static int
1793+yaml_emitter_write_anchor(yaml_emitter_t *emitter,
1794+ yaml_char_t *value, size_t length)
1795+{
1796+ yaml_string_t string = STRING(value, length);
1797+
1798+ while (string.pointer != string.end) {
1799+ if (!WRITE(emitter, string)) return 0;
1800+ }
1801+
1802+ emitter->whitespace = 0;
1803+ emitter->indention = 0;
1804+
1805+ return 1;
1806+}
1807+
1808+static int
1809+yaml_emitter_write_tag_handle(yaml_emitter_t *emitter,
1810+ yaml_char_t *value, size_t length)
1811+{
1812+ yaml_string_t string = STRING(value, length);
1813+
1814+ if (!emitter->whitespace) {
1815+ if (!PUT(emitter, ' ')) return 0;
1816+ }
1817+
1818+ while (string.pointer != string.end) {
1819+ if (!WRITE(emitter, string)) return 0;
1820+ }
1821+
1822+ emitter->whitespace = 0;
1823+ emitter->indention = 0;
1824+
1825+ return 1;
1826+}
1827+
1828+static int
1829+yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
1830+ yaml_char_t *value, size_t length,
1831+ int need_whitespace)
1832+{
1833+ yaml_string_t string = STRING(value, length);
1834+
1835+ if (need_whitespace && !emitter->whitespace) {
1836+ if (!PUT(emitter, ' ')) return 0;
1837+ }
1838+
1839+ while (string.pointer != string.end) {
1840+ if (IS_ALPHA(string)
1841+ || CHECK(string, ';') || CHECK(string, '/')
1842+ || CHECK(string, '?') || CHECK(string, ':')
1843+ || CHECK(string, '@') || CHECK(string, '&')
1844+ || CHECK(string, '=') || CHECK(string, '+')
1845+ || CHECK(string, '$') || CHECK(string, ',')
1846+ || CHECK(string, '_') || CHECK(string, '.')
1847+ || CHECK(string, '~') || CHECK(string, '*')
1848+ || CHECK(string, '\'') || CHECK(string, '(')
1849+ || CHECK(string, ')') || CHECK(string, '[')
1850+ || CHECK(string, ']')) {
1851+ if (!WRITE(emitter, string)) return 0;
1852+ }
1853+ else {
1854+ int width = WIDTH(string);
1855+ unsigned int value;
1856+ while (width --) {
1857+ value = *(string.pointer++);
1858+ if (!PUT(emitter, '%')) return 0;
1859+ if (!PUT(emitter, (value >> 4)
1860+ + ((value >> 4) < 10 ? '0' : 'A' - 10)))
1861+ return 0;
1862+ if (!PUT(emitter, (value & 0x0F)
1863+ + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
1864+ return 0;
1865+ }
1866+ }
1867+ }
1868+
1869+ emitter->whitespace = 0;
1870+ emitter->indention = 0;
1871+
1872+ return 1;
1873+}
1874+
1875+static int
1876+yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
1877+ yaml_char_t *value, size_t length, int allow_breaks)
1878+{
1879+ yaml_string_t string = STRING(value, length);
1880+ int spaces = 0;
1881+ int breaks = 0;
1882+
1883+ if (!emitter->whitespace) {
1884+ if (!PUT(emitter, ' ')) return 0;
1885+ }
1886+
1887+ while (string.pointer != string.end)
1888+ {
1889+ if (IS_SPACE(string))
1890+ {
1891+ if (allow_breaks && !spaces
1892+ && emitter->column > emitter->best_width
1893+ && !IS_SPACE_AT(string, 1)) {
1894+ if (!yaml_emitter_write_indent(emitter)) return 0;
1895+ MOVE(string);
1896+ }
1897+ else {
1898+ if (!WRITE(emitter, string)) return 0;
1899+ }
1900+ spaces = 1;
1901+ }
1902+ else if (IS_BREAK(string))
1903+ {
1904+ if (!breaks && CHECK(string, '\n')) {
1905+ if (!PUT_BREAK(emitter)) return 0;
1906+ }
1907+ if (!WRITE_BREAK(emitter, string)) return 0;
1908+ emitter->indention = 1;
1909+ breaks = 1;
1910+ }
1911+ else
1912+ {
1913+ if (breaks) {
1914+ if (!yaml_emitter_write_indent(emitter)) return 0;
1915+ }
1916+ if (!WRITE(emitter, string)) return 0;
1917+ emitter->indention = 0;
1918+ spaces = 0;
1919+ breaks = 0;
1920+ }
1921+ }
1922+
1923+ emitter->whitespace = 0;
1924+ emitter->indention = 0;
1925+ if (emitter->root_context)
1926+ {
1927+ emitter->open_ended = 1;
1928+ }
1929+
1930+ return 1;
1931+}
1932+
1933+static int
1934+yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
1935+ yaml_char_t *value, size_t length, int allow_breaks)
1936+{
1937+ yaml_string_t string = STRING(value, length);
1938+ int spaces = 0;
1939+ int breaks = 0;
1940+
1941+ if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
1942+ return 0;
1943+
1944+ while (string.pointer != string.end)
1945+ {
1946+ if (IS_SPACE(string))
1947+ {
1948+ if (allow_breaks && !spaces
1949+ && emitter->column > emitter->best_width
1950+ && string.pointer != string.start
1951+ && string.pointer != string.end - 1
1952+ && !IS_SPACE_AT(string, 1)) {
1953+ if (!yaml_emitter_write_indent(emitter)) return 0;
1954+ MOVE(string);
1955+ }
1956+ else {
1957+ if (!WRITE(emitter, string)) return 0;
1958+ }
1959+ spaces = 1;
1960+ }
1961+ else if (IS_BREAK(string))
1962+ {
1963+ if (!breaks && CHECK(string, '\n')) {
1964+ if (!PUT_BREAK(emitter)) return 0;
1965+ }
1966+ if (!WRITE_BREAK(emitter, string)) return 0;
1967+ emitter->indention = 1;
1968+ breaks = 1;
1969+ }
1970+ else
1971+ {
1972+ if (breaks) {
1973+ if (!yaml_emitter_write_indent(emitter)) return 0;
1974+ }
1975+ if (CHECK(string, '\'')) {
1976+ if (!PUT(emitter, '\'')) return 0;
1977+ }
1978+ if (!WRITE(emitter, string)) return 0;
1979+ emitter->indention = 0;
1980+ spaces = 0;
1981+ breaks = 0;
1982+ }
1983+ }
1984+
1985+ if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
1986+ return 0;
1987+
1988+ emitter->whitespace = 0;
1989+ emitter->indention = 0;
1990+
1991+ return 1;
1992+}
1993+
1994+static int
1995+yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
1996+ yaml_char_t *value, size_t length, int allow_breaks)
1997+{
1998+ yaml_string_t string = STRING(value, length);
1999+ int spaces = 0;
2000+
2001+ if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
2002+ return 0;
2003+
2004+ while (string.pointer != string.end)
2005+ {
2006+ if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
2007+ || IS_BOM(string) || IS_BREAK(string)
2008+ || CHECK(string, '"') || CHECK(string, '\\'))
2009+ {
2010+ unsigned char octet;
2011+ unsigned int width;
2012+ unsigned int value;
2013+ int k;
2014+
2015+ octet = string.pointer[0];
2016+ width = (octet & 0x80) == 0x00 ? 1 :
2017+ (octet & 0xE0) == 0xC0 ? 2 :
2018+ (octet & 0xF0) == 0xE0 ? 3 :
2019+ (octet & 0xF8) == 0xF0 ? 4 : 0;
2020+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
2021+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
2022+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
2023+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
2024+ for (k = 1; k < (int)width; k ++) {
2025+ octet = string.pointer[k];
2026+ value = (value << 6) + (octet & 0x3F);
2027+ }
2028+ string.pointer += width;
2029+
2030+ if (!PUT(emitter, '\\')) return 0;
2031+
2032+ switch (value)
2033+ {
2034+ case 0x00:
2035+ if (!PUT(emitter, '0')) return 0;
2036+ break;
2037+
2038+ case 0x07:
2039+ if (!PUT(emitter, 'a')) return 0;
2040+ break;
2041+
2042+ case 0x08:
2043+ if (!PUT(emitter, 'b')) return 0;
2044+ break;
2045+
2046+ case 0x09:
2047+ if (!PUT(emitter, 't')) return 0;
2048+ break;
2049+
2050+ case 0x0A:
2051+ if (!PUT(emitter, 'n')) return 0;
2052+ break;
2053+
2054+ case 0x0B:
2055+ if (!PUT(emitter, 'v')) return 0;
2056+ break;
2057+
2058+ case 0x0C:
2059+ if (!PUT(emitter, 'f')) return 0;
2060+ break;
2061+
2062+ case 0x0D:
2063+ if (!PUT(emitter, 'r')) return 0;
2064+ break;
2065+
2066+ case 0x1B:
2067+ if (!PUT(emitter, 'e')) return 0;
2068+ break;
2069+
2070+ case 0x22:
2071+ if (!PUT(emitter, '\"')) return 0;
2072+ break;
2073+
2074+ case 0x5C:
2075+ if (!PUT(emitter, '\\')) return 0;
2076+ break;
2077+
2078+ case 0x85:
2079+ if (!PUT(emitter, 'N')) return 0;
2080+ break;
2081+
2082+ case 0xA0:
2083+ if (!PUT(emitter, '_')) return 0;
2084+ break;
2085+
2086+ case 0x2028:
2087+ if (!PUT(emitter, 'L')) return 0;
2088+ break;
2089+
2090+ case 0x2029:
2091+ if (!PUT(emitter, 'P')) return 0;
2092+ break;
2093+
2094+ default:
2095+ if (value <= 0xFF) {
2096+ if (!PUT(emitter, 'x')) return 0;
2097+ width = 2;
2098+ }
2099+ else if (value <= 0xFFFF) {
2100+ if (!PUT(emitter, 'u')) return 0;
2101+ width = 4;
2102+ }
2103+ else {
2104+ if (!PUT(emitter, 'U')) return 0;
2105+ width = 8;
2106+ }
2107+ for (k = (width-1)*4; k >= 0; k -= 4) {
2108+ int digit = (value >> k) & 0x0F;
2109+ if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
2110+ return 0;
2111+ }
2112+ }
2113+ spaces = 0;
2114+ }
2115+ else if (IS_SPACE(string))
2116+ {
2117+ if (allow_breaks && !spaces
2118+ && emitter->column > emitter->best_width
2119+ && string.pointer != string.start
2120+ && string.pointer != string.end - 1) {
2121+ if (!yaml_emitter_write_indent(emitter)) return 0;
2122+ if (IS_SPACE_AT(string, 1)) {
2123+ if (!PUT(emitter, '\\')) return 0;
2124+ }
2125+ MOVE(string);
2126+ }
2127+ else {
2128+ if (!WRITE(emitter, string)) return 0;
2129+ }
2130+ spaces = 1;
2131+ }
2132+ else
2133+ {
2134+ if (!WRITE(emitter, string)) return 0;
2135+ spaces = 0;
2136+ }
2137+ }
2138+
2139+ if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
2140+ return 0;
2141+
2142+ emitter->whitespace = 0;
2143+ emitter->indention = 0;
2144+
2145+ return 1;
2146+}
2147+
2148+static int
2149+yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
2150+ yaml_string_t string)
2151+{
2152+ char indent_hint[2];
2153+ char *chomp_hint = NULL;
2154+
2155+ if (IS_SPACE(string) || IS_BREAK(string))
2156+ {
2157+ indent_hint[0] = '0' + (char)emitter->best_indent;
2158+ indent_hint[1] = '\0';
2159+ if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
2160+ return 0;
2161+ }
2162+
2163+ emitter->open_ended = 0;
2164+
2165+ string.pointer = string.end;
2166+ if (string.start == string.pointer)
2167+ {
2168+ chomp_hint = "-";
2169+ }
2170+ else
2171+ {
2172+ do {
2173+ string.pointer --;
2174+ } while ((*string.pointer & 0xC0) == 0x80);
2175+ if (!IS_BREAK(string))
2176+ {
2177+ chomp_hint = "-";
2178+ }
2179+ else if (string.start == string.pointer)
2180+ {
2181+ chomp_hint = "+";
2182+ emitter->open_ended = 1;
2183+ }
2184+ else
2185+ {
2186+ do {
2187+ string.pointer --;
2188+ } while ((*string.pointer & 0xC0) == 0x80);
2189+ if (IS_BREAK(string))
2190+ {
2191+ chomp_hint = "+";
2192+ emitter->open_ended = 1;
2193+ }
2194+ }
2195+ }
2196+
2197+ if (chomp_hint)
2198+ {
2199+ if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
2200+ return 0;
2201+ }
2202+
2203+ return 1;
2204+}
2205+
2206+static int
2207+yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
2208+ yaml_char_t *value, size_t length)
2209+{
2210+ yaml_string_t string = STRING(value, length);
2211+ int breaks = 1;
2212+
2213+ if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
2214+ return 0;
2215+ if (!yaml_emitter_write_block_scalar_hints(emitter, string))
2216+ return 0;
2217+ if (!PUT_BREAK(emitter)) return 0;
2218+ emitter->indention = 1;
2219+ emitter->whitespace = 1;
2220+
2221+ while (string.pointer != string.end)
2222+ {
2223+ if (IS_BREAK(string))
2224+ {
2225+ if (!WRITE_BREAK(emitter, string)) return 0;
2226+ emitter->indention = 1;
2227+ breaks = 1;
2228+ }
2229+ else
2230+ {
2231+ if (breaks) {
2232+ if (!yaml_emitter_write_indent(emitter)) return 0;
2233+ }
2234+ if (!WRITE(emitter, string)) return 0;
2235+ emitter->indention = 0;
2236+ breaks = 0;
2237+ }
2238+ }
2239+
2240+ return 1;
2241+}
2242+
2243+static int
2244+yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
2245+ yaml_char_t *value, size_t length)
2246+{
2247+ yaml_string_t string = STRING(value, length);
2248+ int breaks = 1;
2249+ int leading_spaces = 1;
2250+
2251+ if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
2252+ return 0;
2253+ if (!yaml_emitter_write_block_scalar_hints(emitter, string))
2254+ return 0;
2255+ if (!PUT_BREAK(emitter)) return 0;
2256+ emitter->indention = 1;
2257+ emitter->whitespace = 1;
2258+
2259+ while (string.pointer != string.end)
2260+ {
2261+ if (IS_BREAK(string))
2262+ {
2263+ if (!breaks && !leading_spaces && CHECK(string, '\n')) {
2264+ int k = 0;
2265+ while (IS_BREAK_AT(string, k)) {
2266+ k += WIDTH_AT(string, k);
2267+ }
2268+ if (!IS_BLANKZ_AT(string, k)) {
2269+ if (!PUT_BREAK(emitter)) return 0;
2270+ }
2271+ }
2272+ if (!WRITE_BREAK(emitter, string)) return 0;
2273+ emitter->indention = 1;
2274+ breaks = 1;
2275+ }
2276+ else
2277+ {
2278+ if (breaks) {
2279+ if (!yaml_emitter_write_indent(emitter)) return 0;
2280+ leading_spaces = IS_BLANK(string);
2281+ }
2282+ if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
2283+ && emitter->column > emitter->best_width) {
2284+ if (!yaml_emitter_write_indent(emitter)) return 0;
2285+ MOVE(string);
2286+ }
2287+ else {
2288+ if (!WRITE(emitter, string)) return 0;
2289+ }
2290+ emitter->indention = 0;
2291+ breaks = 0;
2292+ }
2293+ }
2294+
2295+ return 1;
2296+}
2297+
libyaml/c/helper.c → c/helper.crenamed+13−64
@@ -13,10 +13,10 @@ int buffer_append(void *ext, unsigned char *str, size_t size)
13{
13{
14 buffer_t *b = ext;
14 buffer_t *b = ext;
15 int new_size, new_used;
15 int new_size, new_used;
16− unsigned char *tmp;
16+ char *tmp;
17
17
18 new_used = b->used + size;
18 new_used = b->used + size;
19− for (new_size = b->size ? b->size : 8; new_size < new_used; new_size *= 2);
19+ for (new_size = b->size || 8; new_size < new_used; new_size *= 2);
20
20
21 if (new_size != b->size) {
21 if (new_size != b->size) {
22 tmp = realloc(b->buff, new_size);
22 tmp = realloc(b->buff, new_size);
@@ -46,22 +46,22 @@ void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b)
46 yaml_emitter_set_output(e, buffer_append, b);
46 yaml_emitter_set_output(e, buffer_append, b);
47}
47}
48
48
49−char const * get_parser_error_problem(yaml_parser_t *p)
49+unsigned char const * get_parser_error_problem(yaml_parser_t *p)
50{
50{
51 return p->problem;
51 return p->problem;
52}
52}
53
53
54−char const * get_parser_error_context(yaml_parser_t *p)
54+unsigned char const * get_parser_error_context(yaml_parser_t *p)
55{
55{
56 return p->context;
56 return p->context;
57}
57}
58
58
59−const yaml_mark_t * get_parser_error_mark(yaml_parser_t *p)
59+unsigned int get_parser_error_offset(yaml_parser_t *p)
60{
60{
61− return &p->problem_mark;
61+ return p->offset;
62}
62}
63
63
64−char const * get_emitter_error(yaml_emitter_t *e)
64+unsigned char const * get_emitter_error(yaml_emitter_t *e)
65{
65{
66 return e->problem;
66 return e->problem;
67}
67}
@@ -94,10 +94,15 @@ unsigned long get_scalar_length(yaml_event_t *e)
94unsigned char * get_scalar_tag(yaml_event_t *e)
94unsigned char * get_scalar_tag(yaml_event_t *e)
95{
95{
96 unsigned char *s = e->data.scalar.tag;
96 unsigned char *s = e->data.scalar.tag;
97− if (!s) s = (unsigned char *) "";
97+ if (!s) s = "";
98 return s;
98 return s;
99}
99}
100
100
101+unsigned long get_scalar_tag_len(yaml_event_t *e)
102+{
103+ return strlen(get_scalar_tag(e));
104+}
105+
101int get_scalar_style(yaml_event_t *e)
106int get_scalar_style(yaml_event_t *e)
102{
107{
103 return e->data.scalar.style;
108 return e->data.scalar.style;
@@ -113,75 +118,19 @@ unsigned char * get_sequence_start_anchor(yaml_event_t *e)
113 return e->data.sequence_start.anchor;
118 return e->data.sequence_start.anchor;
114}
119}
115
120
116−int get_sequence_start_style(yaml_event_t *e)
117−{
118− return e->data.sequence_start.style;
119−}
120−
121−unsigned char * get_sequence_start_tag(yaml_event_t *e)
122−{
123− unsigned char *s = e->data.sequence_start.tag;
124− if (!s) s = (unsigned char *) "";
125− return s;
126−}
127−
128unsigned char * get_mapping_start_anchor(yaml_event_t *e)
121unsigned char * get_mapping_start_anchor(yaml_event_t *e)
129{
122{
130 return e->data.mapping_start.anchor;
123 return e->data.mapping_start.anchor;
131}
124}
132
125
133−int get_mapping_start_style(yaml_event_t *e)
134−{
135− return e->data.mapping_start.style;
136−}
137−
138−unsigned char * get_mapping_start_tag(yaml_event_t *e)
139−{
140− unsigned char *s = e->data.mapping_start.tag;
141− if (!s) s = (unsigned char *) "";
142− return s;
143−}
144−
145unsigned char * get_alias_anchor(yaml_event_t *e)
126unsigned char * get_alias_anchor(yaml_event_t *e)
146{
127{
147 return e->data.alias.anchor;
128 return e->data.alias.anchor;
148}
129}
149
130
150−const yaml_mark_t * get_start_mark(yaml_event_t *e)
151−{
152− return &e->start_mark;
153−}
154−
155−const yaml_mark_t * get_end_mark(yaml_event_t *e)
156−{
157− return &e->end_mark;
158−}
159−
160−unsigned int get_mark_index(yaml_mark_t *m)
161−{
162− return m->index;
163−}
164−
165−unsigned int get_mark_line(yaml_mark_t *m)
166−{
167− return m->line;
168−}
169−
170−unsigned int get_mark_column(yaml_mark_t *m)
171−{
172− return m->column;
173−}
174−
175int yaml_parser_set_input_filename(yaml_parser_t *parser, const char *filename)
131int yaml_parser_set_input_filename(yaml_parser_t *parser, const char *filename)
176{
132{
177 FILE *in = fopen(filename, "r");
133 FILE *in = fopen(filename, "r");
178 if (!in) return 0;
134 if (!in) return 0;
179 yaml_parser_set_input_file(parser, in);
135 yaml_parser_set_input_file(parser, in);
180− return 1;
181−}
182−
183−int fclose_helper(FILE *file)
184−{
185− if (! file) return 0;
186− return fclose(file);
187}
136}
libyaml/include/helper.h → c/helper.hrenamed+4−7
@@ -14,11 +14,11 @@ unsigned int get_buffer_used(buffer_t *b);
14
14
15void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b);
15void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b);
16
16
17−char const * get_parser_error_problem(yaml_parser_t *p);
17+unsigned char const * get_parser_error_problem(yaml_parser_t *p);
18−char const * get_parser_error_context(yaml_parser_t *p);
18+unsigned char const * get_parser_error_context(yaml_parser_t *p);
19unsigned int get_parser_error_offset(yaml_parser_t *p);
19unsigned int get_parser_error_offset(yaml_parser_t *p);
20
20
21−char const * get_emitter_error(yaml_emitter_t *e);
21+unsigned char const * get_emitter_error(yaml_emitter_t *e);
22
22
23int simple_document_start(yaml_event_t *e);
23int simple_document_start(yaml_event_t *e);
24
24
@@ -28,12 +28,9 @@ unsigned char * get_scalar_value(yaml_event_t *e);
28unsigned long get_scalar_length(yaml_event_t *e);
28unsigned long get_scalar_length(yaml_event_t *e);
29
29
30unsigned char * get_scalar_tag(yaml_event_t *e);
30unsigned char * get_scalar_tag(yaml_event_t *e);
31−unsigned char * get_sequence_start_tag(yaml_event_t *e);
31+unsigned long get_scalar_tag_len(yaml_event_t *e);
32−unsigned char * get_mapping_start_tag(yaml_event_t *e);
33
32
34int get_scalar_style(yaml_event_t *e);
33int get_scalar_style(yaml_event_t *e);
35−int get_sequence_start_style(yaml_event_t *e);
36−int get_mapping_start_style(yaml_event_t *e);
37
34
38unsigned char * get_scalar_anchor(yaml_event_t *e);
35unsigned char * get_scalar_anchor(yaml_event_t *e);
39unsigned char * get_sequence_start_anchor(yaml_event_t *e);
36unsigned char * get_sequence_start_anchor(yaml_event_t *e);
c/loader.cnew file+430
@@ -0,0 +1,430 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * API functions.
6+ */
7+
8+YAML_DECLARE(int)
9+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
10+
11+/*
12+ * Error handling.
13+ */
14+
15+static int
16+yaml_parser_set_composer_error(yaml_parser_t *parser,
17+ const char *problem, yaml_mark_t problem_mark);
18+
19+static int
20+yaml_parser_set_composer_error_context(yaml_parser_t *parser,
21+ const char *context, yaml_mark_t context_mark,
22+ const char *problem, yaml_mark_t problem_mark);
23+
24+
25+/*
26+ * Alias handling.
27+ */
28+
29+static int
30+yaml_parser_register_anchor(yaml_parser_t *parser,
31+ int index, yaml_char_t *anchor);
32+
33+/*
34+ * Clean up functions.
35+ */
36+
37+static void
38+yaml_parser_delete_aliases(yaml_parser_t *parser);
39+
40+/*
41+ * Composer functions.
42+ */
43+
44+static int
45+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
46+
47+static int
48+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
49+
50+static int
51+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
52+
53+static int
54+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
55+
56+static int
57+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
58+
59+static int
60+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
61+
62+/*
63+ * Load the next document of the stream.
64+ */
65+
66+YAML_DECLARE(int)
67+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document)
68+{
69+ yaml_event_t event;
70+
71+ assert(parser); /* Non-NULL parser object is expected. */
72+ assert(document); /* Non-NULL document object is expected. */
73+
74+ memset(document, 0, sizeof(yaml_document_t));
75+ if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))
76+ goto error;
77+
78+ if (!parser->stream_start_produced) {
79+ if (!yaml_parser_parse(parser, &event)) goto error;
80+ assert(event.type == YAML_STREAM_START_EVENT);
81+ /* STREAM-START is expected. */
82+ }
83+
84+ if (parser->stream_end_produced) {
85+ return 1;
86+ }
87+
88+ if (!yaml_parser_parse(parser, &event)) goto error;
89+ if (event.type == YAML_STREAM_END_EVENT) {
90+ return 1;
91+ }
92+
93+ if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))
94+ goto error;
95+
96+ parser->document = document;
97+
98+ if (!yaml_parser_load_document(parser, &event)) goto error;
99+
100+ yaml_parser_delete_aliases(parser);
101+ parser->document = NULL;
102+
103+ return 1;
104+
105+error:
106+
107+ yaml_parser_delete_aliases(parser);
108+ yaml_document_delete(document);
109+ parser->document = NULL;
110+
111+ return 0;
112+}
113+
114+/*
115+ * Set composer error.
116+ */
117+
118+static int
119+yaml_parser_set_composer_error(yaml_parser_t *parser,
120+ const char *problem, yaml_mark_t problem_mark)
121+{
122+ parser->error = YAML_COMPOSER_ERROR;
123+ parser->problem = problem;
124+ parser->problem_mark = problem_mark;
125+
126+ return 0;
127+}
128+
129+/*
130+ * Set composer error with context.
131+ */
132+
133+static int
134+yaml_parser_set_composer_error_context(yaml_parser_t *parser,
135+ const char *context, yaml_mark_t context_mark,
136+ const char *problem, yaml_mark_t problem_mark)
137+{
138+ parser->error = YAML_COMPOSER_ERROR;
139+ parser->context = context;
140+ parser->context_mark = context_mark;
141+ parser->problem = problem;
142+ parser->problem_mark = problem_mark;
143+
144+ return 0;
145+}
146+
147+/*
148+ * Delete the stack of aliases.
149+ */
150+
151+static void
152+yaml_parser_delete_aliases(yaml_parser_t *parser)
153+{
154+ while (!STACK_EMPTY(parser, parser->aliases)) {
155+ yaml_free(POP(parser, parser->aliases).anchor);
156+ }
157+ STACK_DEL(parser, parser->aliases);
158+}
159+
160+/*
161+ * Compose a document object.
162+ */
163+
164+static int
165+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
166+{
167+ yaml_event_t event;
168+
169+ assert(first_event->type == YAML_DOCUMENT_START_EVENT);
170+ /* DOCUMENT-START is expected. */
171+
172+ parser->document->version_directive
173+ = first_event->data.document_start.version_directive;
174+ parser->document->tag_directives.start
175+ = first_event->data.document_start.tag_directives.start;
176+ parser->document->tag_directives.end
177+ = first_event->data.document_start.tag_directives.end;
178+ parser->document->start_implicit
179+ = first_event->data.document_start.implicit;
180+ parser->document->start_mark = first_event->start_mark;
181+
182+ if (!yaml_parser_parse(parser, &event)) return 0;
183+
184+ if (!yaml_parser_load_node(parser, &event)) return 0;
185+
186+ if (!yaml_parser_parse(parser, &event)) return 0;
187+ assert(event.type == YAML_DOCUMENT_END_EVENT);
188+ /* DOCUMENT-END is expected. */
189+
190+ parser->document->end_implicit = event.data.document_end.implicit;
191+ parser->document->end_mark = event.end_mark;
192+
193+ return 1;
194+}
195+
196+/*
197+ * Compose a node.
198+ */
199+
200+static int
201+yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
202+{
203+ switch (first_event->type) {
204+ case YAML_ALIAS_EVENT:
205+ return yaml_parser_load_alias(parser, first_event);
206+ case YAML_SCALAR_EVENT:
207+ return yaml_parser_load_scalar(parser, first_event);
208+ case YAML_SEQUENCE_START_EVENT:
209+ return yaml_parser_load_sequence(parser, first_event);
210+ case YAML_MAPPING_START_EVENT:
211+ return yaml_parser_load_mapping(parser, first_event);
212+ default:
213+ assert(0); /* Could not happen. */
214+ return 0;
215+ }
216+
217+ return 0;
218+}
219+
220+/*
221+ * Add an anchor.
222+ */
223+
224+static int
225+yaml_parser_register_anchor(yaml_parser_t *parser,
226+ int index, yaml_char_t *anchor)
227+{
228+ yaml_alias_data_t data = { anchor, index, { 0, 0, 0 } };
229+ yaml_alias_data_t *alias_data;
230+
231+ if (!anchor) return 1;
232+
233+ data.mark = parser->document->nodes.start[index-1].start_mark;
234+
235+ for (alias_data = parser->aliases.start;
236+ alias_data != parser->aliases.top; alias_data ++) {
237+ if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
238+ yaml_free(anchor);
239+ return yaml_parser_set_composer_error_context(parser,
240+ "found duplicate anchor; first occurence",
241+ alias_data->mark, "second occurence", data.mark);
242+ }
243+ }
244+
245+ if (!PUSH(parser, parser->aliases, data)) {
246+ yaml_free(anchor);
247+ return 0;
248+ }
249+
250+ return 1;
251+}
252+
253+/*
254+ * Compose a node corresponding to an alias.
255+ */
256+
257+static int
258+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
259+{
260+ yaml_char_t *anchor = first_event->data.alias.anchor;
261+ yaml_alias_data_t *alias_data;
262+
263+ for (alias_data = parser->aliases.start;
264+ alias_data != parser->aliases.top; alias_data ++) {
265+ if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
266+ yaml_free(anchor);
267+ return alias_data->index;
268+ }
269+ }
270+
271+ yaml_free(anchor);
272+ return yaml_parser_set_composer_error(parser, "found undefined alias",
273+ first_event->start_mark);
274+}
275+
276+/*
277+ * Compose a scalar node.
278+ */
279+
280+static int
281+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
282+{
283+ yaml_node_t node;
284+ int index;
285+ yaml_char_t *tag = first_event->data.scalar.tag;
286+
287+ if (!tag || strcmp((char *)tag, "!") == 0) {
288+ yaml_free(tag);
289+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
290+ if (!tag) goto error;
291+ }
292+
293+ SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
294+ first_event->data.scalar.length, first_event->data.scalar.style,
295+ first_event->start_mark, first_event->end_mark);
296+
297+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
298+
299+ index = parser->document->nodes.top - parser->document->nodes.start;
300+
301+ if (!yaml_parser_register_anchor(parser, index,
302+ first_event->data.scalar.anchor)) return 0;
303+
304+ return index;
305+
306+error:
307+ yaml_free(tag);
308+ yaml_free(first_event->data.scalar.anchor);
309+ yaml_free(first_event->data.scalar.value);
310+ return 0;
311+}
312+
313+/*
314+ * Compose a sequence node.
315+ */
316+
317+static int
318+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
319+{
320+ yaml_event_t event;
321+ yaml_node_t node;
322+ struct {
323+ yaml_node_item_t *start;
324+ yaml_node_item_t *end;
325+ yaml_node_item_t *top;
326+ } items = { NULL, NULL, NULL };
327+ int index, item_index;
328+ yaml_char_t *tag = first_event->data.sequence_start.tag;
329+
330+ if (!tag || strcmp((char *)tag, "!") == 0) {
331+ yaml_free(tag);
332+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
333+ if (!tag) goto error;
334+ }
335+
336+ if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
337+
338+ SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
339+ first_event->data.sequence_start.style,
340+ first_event->start_mark, first_event->end_mark);
341+
342+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
343+
344+ index = parser->document->nodes.top - parser->document->nodes.start;
345+
346+ if (!yaml_parser_register_anchor(parser, index,
347+ first_event->data.sequence_start.anchor)) return 0;
348+
349+ if (!yaml_parser_parse(parser, &event)) return 0;
350+
351+ while (event.type != YAML_SEQUENCE_END_EVENT) {
352+ item_index = yaml_parser_load_node(parser, &event);
353+ if (!item_index) return 0;
354+ if (!PUSH(parser,
355+ parser->document->nodes.start[index-1].data.sequence.items,
356+ item_index)) return 0;
357+ if (!yaml_parser_parse(parser, &event)) return 0;
358+ }
359+
360+ parser->document->nodes.start[index-1].end_mark = event.end_mark;
361+
362+ return index;
363+
364+error:
365+ yaml_free(tag);
366+ yaml_free(first_event->data.sequence_start.anchor);
367+ return 0;
368+}
369+
370+/*
371+ * Compose a mapping node.
372+ */
373+
374+static int
375+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
376+{
377+ yaml_event_t event;
378+ yaml_node_t node;
379+ struct {
380+ yaml_node_pair_t *start;
381+ yaml_node_pair_t *end;
382+ yaml_node_pair_t *top;
383+ } pairs = { NULL, NULL, NULL };
384+ int index;
385+ yaml_node_pair_t pair;
386+ yaml_char_t *tag = first_event->data.mapping_start.tag;
387+
388+ if (!tag || strcmp((char *)tag, "!") == 0) {
389+ yaml_free(tag);
390+ tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
391+ if (!tag) goto error;
392+ }
393+
394+ if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
395+
396+ MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
397+ first_event->data.mapping_start.style,
398+ first_event->start_mark, first_event->end_mark);
399+
400+ if (!PUSH(parser, parser->document->nodes, node)) goto error;
401+
402+ index = parser->document->nodes.top - parser->document->nodes.start;
403+
404+ if (!yaml_parser_register_anchor(parser, index,
405+ first_event->data.mapping_start.anchor)) return 0;
406+
407+ if (!yaml_parser_parse(parser, &event)) return 0;
408+
409+ while (event.type != YAML_MAPPING_END_EVENT) {
410+ pair.key = yaml_parser_load_node(parser, &event);
411+ if (!pair.key) return 0;
412+ if (!yaml_parser_parse(parser, &event)) return 0;
413+ pair.value = yaml_parser_load_node(parser, &event);
414+ if (!pair.value) return 0;
415+ if (!PUSH(parser,
416+ parser->document->nodes.start[index-1].data.mapping.pairs,
417+ pair)) return 0;
418+ if (!yaml_parser_parse(parser, &event)) return 0;
419+ }
420+
421+ parser->document->nodes.start[index-1].end_mark = event.end_mark;
422+
423+ return index;
424+
425+error:
426+ yaml_free(tag);
427+ yaml_free(first_event->data.mapping_start.anchor);
428+ return 0;
429+}
430+
c/parser.cnew file+1374
@@ -0,0 +1,1374 @@
1+
2+/*
3+ * The parser implements the following grammar:
4+ *
5+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
6+ * implicit_document ::= block_node DOCUMENT-END*
7+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
8+ * block_node_or_indentless_sequence ::=
9+ * ALIAS
10+ * | properties (block_content | indentless_block_sequence)?
11+ * | block_content
12+ * | indentless_block_sequence
13+ * block_node ::= ALIAS
14+ * | properties block_content?
15+ * | block_content
16+ * flow_node ::= ALIAS
17+ * | properties flow_content?
18+ * | flow_content
19+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
20+ * block_content ::= block_collection | flow_collection | SCALAR
21+ * flow_content ::= flow_collection | SCALAR
22+ * block_collection ::= block_sequence | block_mapping
23+ * flow_collection ::= flow_sequence | flow_mapping
24+ * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
25+ * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
26+ * block_mapping ::= BLOCK-MAPPING_START
27+ * ((KEY block_node_or_indentless_sequence?)?
28+ * (VALUE block_node_or_indentless_sequence?)?)*
29+ * BLOCK-END
30+ * flow_sequence ::= FLOW-SEQUENCE-START
31+ * (flow_sequence_entry FLOW-ENTRY)*
32+ * flow_sequence_entry?
33+ * FLOW-SEQUENCE-END
34+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
35+ * flow_mapping ::= FLOW-MAPPING-START
36+ * (flow_mapping_entry FLOW-ENTRY)*
37+ * flow_mapping_entry?
38+ * FLOW-MAPPING-END
39+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
40+ */
41+
42+#include "yaml_private.h"
43+
44+/*
45+ * Peek the next token in the token queue.
46+ */
47+
48+#define PEEK_TOKEN(parser) \
49+ ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ? \
50+ parser->tokens.head : NULL)
51+
52+/*
53+ * Remove the next token from the queue (must be called after PEEK_TOKEN).
54+ */
55+
56+#define SKIP_TOKEN(parser) \
57+ (parser->token_available = 0, \
58+ parser->tokens_parsed ++, \
59+ parser->stream_end_produced = \
60+ (parser->tokens.head->type == YAML_STREAM_END_TOKEN), \
61+ parser->tokens.head ++)
62+
63+/*
64+ * Public API declarations.
65+ */
66+
67+YAML_DECLARE(int)
68+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
69+
70+/*
71+ * Error handling.
72+ */
73+
74+static int
75+yaml_parser_set_parser_error(yaml_parser_t *parser,
76+ const char *problem, yaml_mark_t problem_mark);
77+
78+static int
79+yaml_parser_set_parser_error_context(yaml_parser_t *parser,
80+ const char *context, yaml_mark_t context_mark,
81+ const char *problem, yaml_mark_t problem_mark);
82+
83+/*
84+ * State functions.
85+ */
86+
87+static int
88+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event);
89+
90+static int
91+yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event);
92+
93+static int
94+yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
95+ int implicit);
96+
97+static int
98+yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event);
99+
100+static int
101+yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event);
102+
103+static int
104+yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
105+ int block, int indentless_sequence);
106+
107+static int
108+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
109+ yaml_event_t *event, int first);
110+
111+static int
112+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
113+ yaml_event_t *event);
114+
115+static int
116+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
117+ yaml_event_t *event, int first);
118+
119+static int
120+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
121+ yaml_event_t *event);
122+
123+static int
124+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
125+ yaml_event_t *event, int first);
126+
127+static int
128+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
129+ yaml_event_t *event);
130+
131+static int
132+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
133+ yaml_event_t *event);
134+
135+static int
136+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
137+ yaml_event_t *event);
138+
139+static int
140+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
141+ yaml_event_t *event, int first);
142+
143+static int
144+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
145+ yaml_event_t *event, int empty);
146+
147+/*
148+ * Utility functions.
149+ */
150+
151+static int
152+yaml_parser_process_empty_scalar(yaml_parser_t *parser,
153+ yaml_event_t *event, yaml_mark_t mark);
154+
155+static int
156+yaml_parser_process_directives(yaml_parser_t *parser,
157+ yaml_version_directive_t **version_directive_ref,
158+ yaml_tag_directive_t **tag_directives_start_ref,
159+ yaml_tag_directive_t **tag_directives_end_ref);
160+
161+static int
162+yaml_parser_append_tag_directive(yaml_parser_t *parser,
163+ yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark);
164+
165+/*
166+ * Get the next event.
167+ */
168+
169+YAML_DECLARE(int)
170+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event)
171+{
172+ assert(parser); /* Non-NULL parser object is expected. */
173+ assert(event); /* Non-NULL event object is expected. */
174+
175+ /* Erase the event object. */
176+
177+ memset(event, 0, sizeof(yaml_event_t));
178+
179+ /* No events after the end of the stream or error. */
180+
181+ if (parser->stream_end_produced || parser->error ||
182+ parser->state == YAML_PARSE_END_STATE) {
183+ return 1;
184+ }
185+
186+ /* Generate the next event. */
187+
188+ return yaml_parser_state_machine(parser, event);
189+}
190+
191+/*
192+ * Set parser error.
193+ */
194+
195+static int
196+yaml_parser_set_parser_error(yaml_parser_t *parser,
197+ const char *problem, yaml_mark_t problem_mark)
198+{
199+ parser->error = YAML_PARSER_ERROR;
200+ parser->problem = problem;
201+ parser->problem_mark = problem_mark;
202+
203+ return 0;
204+}
205+
206+static int
207+yaml_parser_set_parser_error_context(yaml_parser_t *parser,
208+ const char *context, yaml_mark_t context_mark,
209+ const char *problem, yaml_mark_t problem_mark)
210+{
211+ parser->error = YAML_PARSER_ERROR;
212+ parser->context = context;
213+ parser->context_mark = context_mark;
214+ parser->problem = problem;
215+ parser->problem_mark = problem_mark;
216+
217+ return 0;
218+}
219+
220+
221+/*
222+ * State dispatcher.
223+ */
224+
225+static int
226+yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event)
227+{
228+ switch (parser->state)
229+ {
230+ case YAML_PARSE_STREAM_START_STATE:
231+ return yaml_parser_parse_stream_start(parser, event);
232+
233+ case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE:
234+ return yaml_parser_parse_document_start(parser, event, 1);
235+
236+ case YAML_PARSE_DOCUMENT_START_STATE:
237+ return yaml_parser_parse_document_start(parser, event, 0);
238+
239+ case YAML_PARSE_DOCUMENT_CONTENT_STATE:
240+ return yaml_parser_parse_document_content(parser, event);
241+
242+ case YAML_PARSE_DOCUMENT_END_STATE:
243+ return yaml_parser_parse_document_end(parser, event);
244+
245+ case YAML_PARSE_BLOCK_NODE_STATE:
246+ return yaml_parser_parse_node(parser, event, 1, 0);
247+
248+ case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
249+ return yaml_parser_parse_node(parser, event, 1, 1);
250+
251+ case YAML_PARSE_FLOW_NODE_STATE:
252+ return yaml_parser_parse_node(parser, event, 0, 0);
253+
254+ case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
255+ return yaml_parser_parse_block_sequence_entry(parser, event, 1);
256+
257+ case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
258+ return yaml_parser_parse_block_sequence_entry(parser, event, 0);
259+
260+ case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
261+ return yaml_parser_parse_indentless_sequence_entry(parser, event);
262+
263+ case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
264+ return yaml_parser_parse_block_mapping_key(parser, event, 1);
265+
266+ case YAML_PARSE_BLOCK_MAPPING_KEY_STATE:
267+ return yaml_parser_parse_block_mapping_key(parser, event, 0);
268+
269+ case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE:
270+ return yaml_parser_parse_block_mapping_value(parser, event);
271+
272+ case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
273+ return yaml_parser_parse_flow_sequence_entry(parser, event, 1);
274+
275+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
276+ return yaml_parser_parse_flow_sequence_entry(parser, event, 0);
277+
278+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
279+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event);
280+
281+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
282+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event);
283+
284+ case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
285+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event);
286+
287+ case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
288+ return yaml_parser_parse_flow_mapping_key(parser, event, 1);
289+
290+ case YAML_PARSE_FLOW_MAPPING_KEY_STATE:
291+ return yaml_parser_parse_flow_mapping_key(parser, event, 0);
292+
293+ case YAML_PARSE_FLOW_MAPPING_VALUE_STATE:
294+ return yaml_parser_parse_flow_mapping_value(parser, event, 0);
295+
296+ case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
297+ return yaml_parser_parse_flow_mapping_value(parser, event, 1);
298+
299+ default:
300+ assert(1); /* Invalid state. */
301+ }
302+
303+ return 0;
304+}
305+
306+/*
307+ * Parse the production:
308+ * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
309+ * ************
310+ */
311+
312+static int
313+yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event)
314+{
315+ yaml_token_t *token;
316+
317+ token = PEEK_TOKEN(parser);
318+ if (!token) return 0;
319+
320+ if (token->type != YAML_STREAM_START_TOKEN) {
321+ return yaml_parser_set_parser_error(parser,
322+ "did not find expected <stream-start>", token->start_mark);
323+ }
324+
325+ parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE;
326+ STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding,
327+ token->start_mark, token->start_mark);
328+ SKIP_TOKEN(parser);
329+
330+ return 1;
331+}
332+
333+/*
334+ * Parse the productions:
335+ * implicit_document ::= block_node DOCUMENT-END*
336+ * *
337+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
338+ * *************************
339+ */
340+
341+static int
342+yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event,
343+ int implicit)
344+{
345+ yaml_token_t *token;
346+ yaml_version_directive_t *version_directive = NULL;
347+ struct {
348+ yaml_tag_directive_t *start;
349+ yaml_tag_directive_t *end;
350+ } tag_directives = { NULL, NULL };
351+
352+ token = PEEK_TOKEN(parser);
353+ if (!token) return 0;
354+
355+ /* Parse extra document end indicators. */
356+
357+ if (!implicit)
358+ {
359+ while (token->type == YAML_DOCUMENT_END_TOKEN) {
360+ SKIP_TOKEN(parser);
361+ token = PEEK_TOKEN(parser);
362+ if (!token) return 0;
363+ }
364+ }
365+
366+ /* Parse an implicit document. */
367+
368+ if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN &&
369+ token->type != YAML_TAG_DIRECTIVE_TOKEN &&
370+ token->type != YAML_DOCUMENT_START_TOKEN &&
371+ token->type != YAML_STREAM_END_TOKEN)
372+ {
373+ if (!yaml_parser_process_directives(parser, NULL, NULL, NULL))
374+ return 0;
375+ if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
376+ return 0;
377+ parser->state = YAML_PARSE_BLOCK_NODE_STATE;
378+ DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1,
379+ token->start_mark, token->start_mark);
380+ return 1;
381+ }
382+
383+ /* Parse an explicit document. */
384+
385+ else if (token->type != YAML_STREAM_END_TOKEN)
386+ {
387+ yaml_mark_t start_mark, end_mark;
388+ start_mark = token->start_mark;
389+ if (!yaml_parser_process_directives(parser, &version_directive,
390+ &tag_directives.start, &tag_directives.end))
391+ return 0;
392+ token = PEEK_TOKEN(parser);
393+ if (!token) goto error;
394+ if (token->type != YAML_DOCUMENT_START_TOKEN) {
395+ yaml_parser_set_parser_error(parser,
396+ "did not find expected <document start>", token->start_mark);
397+ goto error;
398+ }
399+ if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE))
400+ goto error;
401+ parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE;
402+ end_mark = token->end_mark;
403+ DOCUMENT_START_EVENT_INIT(*event, version_directive,
404+ tag_directives.start, tag_directives.end, 0,
405+ start_mark, end_mark);
406+ SKIP_TOKEN(parser);
407+ version_directive = NULL;
408+ tag_directives.start = tag_directives.end = NULL;
409+ return 1;
410+ }
411+
412+ /* Parse the stream end. */
413+
414+ else
415+ {
416+ parser->state = YAML_PARSE_END_STATE;
417+ STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
418+ SKIP_TOKEN(parser);
419+ return 1;
420+ }
421+
422+error:
423+ yaml_free(version_directive);
424+ while (tag_directives.start != tag_directives.end) {
425+ yaml_free(tag_directives.end[-1].handle);
426+ yaml_free(tag_directives.end[-1].prefix);
427+ tag_directives.end --;
428+ }
429+ yaml_free(tag_directives.start);
430+ return 0;
431+}
432+
433+/*
434+ * Parse the productions:
435+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
436+ * ***********
437+ */
438+
439+static int
440+yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event)
441+{
442+ yaml_token_t *token;
443+
444+ token = PEEK_TOKEN(parser);
445+ if (!token) return 0;
446+
447+ if (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
448+ token->type == YAML_TAG_DIRECTIVE_TOKEN ||
449+ token->type == YAML_DOCUMENT_START_TOKEN ||
450+ token->type == YAML_DOCUMENT_END_TOKEN ||
451+ token->type == YAML_STREAM_END_TOKEN) {
452+ parser->state = POP(parser, parser->states);
453+ return yaml_parser_process_empty_scalar(parser, event,
454+ token->start_mark);
455+ }
456+ else {
457+ return yaml_parser_parse_node(parser, event, 1, 0);
458+ }
459+}
460+
461+/*
462+ * Parse the productions:
463+ * implicit_document ::= block_node DOCUMENT-END*
464+ * *************
465+ * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
466+ * *************
467+ */
468+
469+static int
470+yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event)
471+{
472+ yaml_token_t *token;
473+ yaml_mark_t start_mark, end_mark;
474+ int implicit = 1;
475+
476+ token = PEEK_TOKEN(parser);
477+ if (!token) return 0;
478+
479+ start_mark = end_mark = token->start_mark;
480+
481+ if (token->type == YAML_DOCUMENT_END_TOKEN) {
482+ end_mark = token->end_mark;
483+ SKIP_TOKEN(parser);
484+ implicit = 0;
485+ }
486+
487+ while (!STACK_EMPTY(parser, parser->tag_directives)) {
488+ yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
489+ yaml_free(tag_directive.handle);
490+ yaml_free(tag_directive.prefix);
491+ }
492+
493+ parser->state = YAML_PARSE_DOCUMENT_START_STATE;
494+ DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark);
495+
496+ return 1;
497+}
498+
499+/*
500+ * Parse the productions:
501+ * block_node_or_indentless_sequence ::=
502+ * ALIAS
503+ * *****
504+ * | properties (block_content | indentless_block_sequence)?
505+ * ********** *
506+ * | block_content | indentless_block_sequence
507+ * *
508+ * block_node ::= ALIAS
509+ * *****
510+ * | properties block_content?
511+ * ********** *
512+ * | block_content
513+ * *
514+ * flow_node ::= ALIAS
515+ * *****
516+ * | properties flow_content?
517+ * ********** *
518+ * | flow_content
519+ * *
520+ * properties ::= TAG ANCHOR? | ANCHOR TAG?
521+ * *************************
522+ * block_content ::= block_collection | flow_collection | SCALAR
523+ * ******
524+ * flow_content ::= flow_collection | SCALAR
525+ * ******
526+ */
527+
528+static int
529+yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event,
530+ int block, int indentless_sequence)
531+{
532+ yaml_token_t *token;
533+ yaml_char_t *anchor = NULL;
534+ yaml_char_t *tag_handle = NULL;
535+ yaml_char_t *tag_suffix = NULL;
536+ yaml_char_t *tag = NULL;
537+ yaml_mark_t start_mark, end_mark, tag_mark;
538+ int implicit;
539+
540+ token = PEEK_TOKEN(parser);
541+ if (!token) return 0;
542+
543+ if (token->type == YAML_ALIAS_TOKEN)
544+ {
545+ parser->state = POP(parser, parser->states);
546+ ALIAS_EVENT_INIT(*event, token->data.alias.value,
547+ token->start_mark, token->end_mark);
548+ SKIP_TOKEN(parser);
549+ return 1;
550+ }
551+
552+ else
553+ {
554+ start_mark = end_mark = token->start_mark;
555+
556+ if (token->type == YAML_ANCHOR_TOKEN)
557+ {
558+ anchor = token->data.anchor.value;
559+ start_mark = token->start_mark;
560+ end_mark = token->end_mark;
561+ SKIP_TOKEN(parser);
562+ token = PEEK_TOKEN(parser);
563+ if (!token) goto error;
564+ if (token->type == YAML_TAG_TOKEN)
565+ {
566+ tag_handle = token->data.tag.handle;
567+ tag_suffix = token->data.tag.suffix;
568+ tag_mark = token->start_mark;
569+ end_mark = token->end_mark;
570+ SKIP_TOKEN(parser);
571+ token = PEEK_TOKEN(parser);
572+ if (!token) goto error;
573+ }
574+ }
575+ else if (token->type == YAML_TAG_TOKEN)
576+ {
577+ tag_handle = token->data.tag.handle;
578+ tag_suffix = token->data.tag.suffix;
579+ start_mark = tag_mark = token->start_mark;
580+ end_mark = token->end_mark;
581+ SKIP_TOKEN(parser);
582+ token = PEEK_TOKEN(parser);
583+ if (!token) goto error;
584+ if (token->type == YAML_ANCHOR_TOKEN)
585+ {
586+ anchor = token->data.anchor.value;
587+ end_mark = token->end_mark;
588+ SKIP_TOKEN(parser);
589+ token = PEEK_TOKEN(parser);
590+ if (!token) goto error;
591+ }
592+ }
593+
594+ if (tag_handle) {
595+ if (!*tag_handle) {
596+ tag = tag_suffix;
597+ yaml_free(tag_handle);
598+ tag_handle = tag_suffix = NULL;
599+ }
600+ else {
601+ yaml_tag_directive_t *tag_directive;
602+ for (tag_directive = parser->tag_directives.start;
603+ tag_directive != parser->tag_directives.top;
604+ tag_directive ++) {
605+ if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) {
606+ size_t prefix_len = strlen((char *)tag_directive->prefix);
607+ size_t suffix_len = strlen((char *)tag_suffix);
608+ tag = yaml_malloc(prefix_len+suffix_len+1);
609+ if (!tag) {
610+ parser->error = YAML_MEMORY_ERROR;
611+ goto error;
612+ }
613+ memcpy(tag, tag_directive->prefix, prefix_len);
614+ memcpy(tag+prefix_len, tag_suffix, suffix_len);
615+ tag[prefix_len+suffix_len] = '\0';
616+ yaml_free(tag_handle);
617+ yaml_free(tag_suffix);
618+ tag_handle = tag_suffix = NULL;
619+ break;
620+ }
621+ }
622+ if (!tag) {
623+ yaml_parser_set_parser_error_context(parser,
624+ "while parsing a node", start_mark,
625+ "found undefined tag handle", tag_mark);
626+ goto error;
627+ }
628+ }
629+ }
630+
631+ implicit = (!tag || !*tag);
632+ if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) {
633+ end_mark = token->end_mark;
634+ parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
635+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
636+ YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
637+ return 1;
638+ }
639+ else {
640+ if (token->type == YAML_SCALAR_TOKEN) {
641+ int plain_implicit = 0;
642+ int quoted_implicit = 0;
643+ end_mark = token->end_mark;
644+ if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag)
645+ || (tag && strcmp((char *)tag, "!") == 0)) {
646+ plain_implicit = 1;
647+ }
648+ else if (!tag) {
649+ quoted_implicit = 1;
650+ }
651+ parser->state = POP(parser, parser->states);
652+ SCALAR_EVENT_INIT(*event, anchor, tag,
653+ token->data.scalar.value, token->data.scalar.length,
654+ plain_implicit, quoted_implicit,
655+ token->data.scalar.style, start_mark, end_mark);
656+ SKIP_TOKEN(parser);
657+ return 1;
658+ }
659+ else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) {
660+ end_mark = token->end_mark;
661+ parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE;
662+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
663+ YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark);
664+ return 1;
665+ }
666+ else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) {
667+ end_mark = token->end_mark;
668+ parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE;
669+ MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
670+ YAML_FLOW_MAPPING_STYLE, start_mark, end_mark);
671+ return 1;
672+ }
673+ else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) {
674+ end_mark = token->end_mark;
675+ parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE;
676+ SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit,
677+ YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark);
678+ return 1;
679+ }
680+ else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) {
681+ end_mark = token->end_mark;
682+ parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE;
683+ MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit,
684+ YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark);
685+ return 1;
686+ }
687+ else if (anchor || tag) {
688+ yaml_char_t *value = yaml_malloc(1);
689+ if (!value) {
690+ parser->error = YAML_MEMORY_ERROR;
691+ goto error;
692+ }
693+ value[0] = '\0';
694+ parser->state = POP(parser, parser->states);
695+ SCALAR_EVENT_INIT(*event, anchor, tag, value, 0,
696+ implicit, 0, YAML_PLAIN_SCALAR_STYLE,
697+ start_mark, end_mark);
698+ return 1;
699+ }
700+ else {
701+ yaml_parser_set_parser_error_context(parser,
702+ (block ? "while parsing a block node"
703+ : "while parsing a flow node"), start_mark,
704+ "did not find expected node content", token->start_mark);
705+ goto error;
706+ }
707+ }
708+ }
709+
710+error:
711+ yaml_free(anchor);
712+ yaml_free(tag_handle);
713+ yaml_free(tag_suffix);
714+ yaml_free(tag);
715+
716+ return 0;
717+}
718+
719+/*
720+ * Parse the productions:
721+ * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
722+ * ******************** *********** * *********
723+ */
724+
725+static int
726+yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser,
727+ yaml_event_t *event, int first)
728+{
729+ yaml_token_t *token;
730+
731+ if (first) {
732+ token = PEEK_TOKEN(parser);
733+ if (!PUSH(parser, parser->marks, token->start_mark))
734+ return 0;
735+ SKIP_TOKEN(parser);
736+ }
737+
738+ token = PEEK_TOKEN(parser);
739+ if (!token) return 0;
740+
741+ if (token->type == YAML_BLOCK_ENTRY_TOKEN)
742+ {
743+ yaml_mark_t mark = token->end_mark;
744+ SKIP_TOKEN(parser);
745+ token = PEEK_TOKEN(parser);
746+ if (!token) return 0;
747+ if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
748+ token->type != YAML_BLOCK_END_TOKEN) {
749+ if (!PUSH(parser, parser->states,
750+ YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE))
751+ return 0;
752+ return yaml_parser_parse_node(parser, event, 1, 0);
753+ }
754+ else {
755+ parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE;
756+ return yaml_parser_process_empty_scalar(parser, event, mark);
757+ }
758+ }
759+
760+ else if (token->type == YAML_BLOCK_END_TOKEN)
761+ {
762+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
763+ parser->state = POP(parser, parser->states);
764+ dummy_mark = POP(parser, parser->marks);
765+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
766+ SKIP_TOKEN(parser);
767+ return 1;
768+ }
769+
770+ else
771+ {
772+ return yaml_parser_set_parser_error_context(parser,
773+ "while parsing a block collection", POP(parser, parser->marks),
774+ "did not find expected '-' indicator", token->start_mark);
775+ }
776+}
777+
778+/*
779+ * Parse the productions:
780+ * indentless_sequence ::= (BLOCK-ENTRY block_node?)+
781+ * *********** *
782+ */
783+
784+static int
785+yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser,
786+ yaml_event_t *event)
787+{
788+ yaml_token_t *token;
789+
790+ token = PEEK_TOKEN(parser);
791+ if (!token) return 0;
792+
793+ if (token->type == YAML_BLOCK_ENTRY_TOKEN)
794+ {
795+ yaml_mark_t mark = token->end_mark;
796+ SKIP_TOKEN(parser);
797+ token = PEEK_TOKEN(parser);
798+ if (!token) return 0;
799+ if (token->type != YAML_BLOCK_ENTRY_TOKEN &&
800+ token->type != YAML_KEY_TOKEN &&
801+ token->type != YAML_VALUE_TOKEN &&
802+ token->type != YAML_BLOCK_END_TOKEN) {
803+ if (!PUSH(parser, parser->states,
804+ YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE))
805+ return 0;
806+ return yaml_parser_parse_node(parser, event, 1, 0);
807+ }
808+ else {
809+ parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE;
810+ return yaml_parser_process_empty_scalar(parser, event, mark);
811+ }
812+ }
813+
814+ else
815+ {
816+ parser->state = POP(parser, parser->states);
817+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
818+ return 1;
819+ }
820+}
821+
822+/*
823+ * Parse the productions:
824+ * block_mapping ::= BLOCK-MAPPING_START
825+ * *******************
826+ * ((KEY block_node_or_indentless_sequence?)?
827+ * *** *
828+ * (VALUE block_node_or_indentless_sequence?)?)*
829+ *
830+ * BLOCK-END
831+ * *********
832+ */
833+
834+static int
835+yaml_parser_parse_block_mapping_key(yaml_parser_t *parser,
836+ yaml_event_t *event, int first)
837+{
838+ yaml_token_t *token;
839+
840+ if (first) {
841+ token = PEEK_TOKEN(parser);
842+ if (!PUSH(parser, parser->marks, token->start_mark))
843+ return 0;
844+ SKIP_TOKEN(parser);
845+ }
846+
847+ token = PEEK_TOKEN(parser);
848+ if (!token) return 0;
849+
850+ if (token->type == YAML_KEY_TOKEN)
851+ {
852+ yaml_mark_t mark = token->end_mark;
853+ SKIP_TOKEN(parser);
854+ token = PEEK_TOKEN(parser);
855+ if (!token) return 0;
856+ if (token->type != YAML_KEY_TOKEN &&
857+ token->type != YAML_VALUE_TOKEN &&
858+ token->type != YAML_BLOCK_END_TOKEN) {
859+ if (!PUSH(parser, parser->states,
860+ YAML_PARSE_BLOCK_MAPPING_VALUE_STATE))
861+ return 0;
862+ return yaml_parser_parse_node(parser, event, 1, 1);
863+ }
864+ else {
865+ parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE;
866+ return yaml_parser_process_empty_scalar(parser, event, mark);
867+ }
868+ }
869+
870+ else if (token->type == YAML_BLOCK_END_TOKEN)
871+ {
872+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
873+ parser->state = POP(parser, parser->states);
874+ dummy_mark = POP(parser, parser->marks);
875+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
876+ SKIP_TOKEN(parser);
877+ return 1;
878+ }
879+
880+ else
881+ {
882+ return yaml_parser_set_parser_error_context(parser,
883+ "while parsing a block mapping", POP(parser, parser->marks),
884+ "did not find expected key", token->start_mark);
885+ }
886+}
887+
888+/*
889+ * Parse the productions:
890+ * block_mapping ::= BLOCK-MAPPING_START
891+ *
892+ * ((KEY block_node_or_indentless_sequence?)?
893+ *
894+ * (VALUE block_node_or_indentless_sequence?)?)*
895+ * ***** *
896+ * BLOCK-END
897+ *
898+ */
899+
900+static int
901+yaml_parser_parse_block_mapping_value(yaml_parser_t *parser,
902+ yaml_event_t *event)
903+{
904+ yaml_token_t *token;
905+
906+ token = PEEK_TOKEN(parser);
907+ if (!token) return 0;
908+
909+ if (token->type == YAML_VALUE_TOKEN)
910+ {
911+ yaml_mark_t mark = token->end_mark;
912+ SKIP_TOKEN(parser);
913+ token = PEEK_TOKEN(parser);
914+ if (!token) return 0;
915+ if (token->type != YAML_KEY_TOKEN &&
916+ token->type != YAML_VALUE_TOKEN &&
917+ token->type != YAML_BLOCK_END_TOKEN) {
918+ if (!PUSH(parser, parser->states,
919+ YAML_PARSE_BLOCK_MAPPING_KEY_STATE))
920+ return 0;
921+ return yaml_parser_parse_node(parser, event, 1, 1);
922+ }
923+ else {
924+ parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
925+ return yaml_parser_process_empty_scalar(parser, event, mark);
926+ }
927+ }
928+
929+ else
930+ {
931+ parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE;
932+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
933+ }
934+}
935+
936+/*
937+ * Parse the productions:
938+ * flow_sequence ::= FLOW-SEQUENCE-START
939+ * *******************
940+ * (flow_sequence_entry FLOW-ENTRY)*
941+ * * **********
942+ * flow_sequence_entry?
943+ * *
944+ * FLOW-SEQUENCE-END
945+ * *****************
946+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
947+ * *
948+ */
949+
950+static int
951+yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser,
952+ yaml_event_t *event, int first)
953+{
954+ yaml_token_t *token;
955+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
956+
957+ if (first) {
958+ token = PEEK_TOKEN(parser);
959+ if (!PUSH(parser, parser->marks, token->start_mark))
960+ return 0;
961+ SKIP_TOKEN(parser);
962+ }
963+
964+ token = PEEK_TOKEN(parser);
965+ if (!token) return 0;
966+
967+ if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN)
968+ {
969+ if (!first) {
970+ if (token->type == YAML_FLOW_ENTRY_TOKEN) {
971+ SKIP_TOKEN(parser);
972+ token = PEEK_TOKEN(parser);
973+ if (!token) return 0;
974+ }
975+ else {
976+ return yaml_parser_set_parser_error_context(parser,
977+ "while parsing a flow sequence", POP(parser, parser->marks),
978+ "did not find expected ',' or ']'", token->start_mark);
979+ }
980+ }
981+
982+ if (token->type == YAML_KEY_TOKEN) {
983+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE;
984+ MAPPING_START_EVENT_INIT(*event, NULL, NULL,
985+ 1, YAML_FLOW_MAPPING_STYLE,
986+ token->start_mark, token->end_mark);
987+ SKIP_TOKEN(parser);
988+ return 1;
989+ }
990+
991+ else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
992+ if (!PUSH(parser, parser->states,
993+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE))
994+ return 0;
995+ return yaml_parser_parse_node(parser, event, 0, 0);
996+ }
997+ }
998+
999+ parser->state = POP(parser, parser->states);
1000+ dummy_mark = POP(parser, parser->marks);
1001+ SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
1002+ SKIP_TOKEN(parser);
1003+ return 1;
1004+}
1005+
1006+/*
1007+ * Parse the productions:
1008+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1009+ * *** *
1010+ */
1011+
1012+static int
1013+yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser,
1014+ yaml_event_t *event)
1015+{
1016+ yaml_token_t *token;
1017+
1018+ token = PEEK_TOKEN(parser);
1019+ if (!token) return 0;
1020+
1021+ if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN
1022+ && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
1023+ if (!PUSH(parser, parser->states,
1024+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE))
1025+ return 0;
1026+ return yaml_parser_parse_node(parser, event, 0, 0);
1027+ }
1028+ else {
1029+ yaml_mark_t mark = token->end_mark;
1030+ SKIP_TOKEN(parser);
1031+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE;
1032+ return yaml_parser_process_empty_scalar(parser, event, mark);
1033+ }
1034+}
1035+
1036+/*
1037+ * Parse the productions:
1038+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1039+ * ***** *
1040+ */
1041+
1042+static int
1043+yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser,
1044+ yaml_event_t *event)
1045+{
1046+ yaml_token_t *token;
1047+
1048+ token = PEEK_TOKEN(parser);
1049+ if (!token) return 0;
1050+
1051+ if (token->type == YAML_VALUE_TOKEN) {
1052+ SKIP_TOKEN(parser);
1053+ token = PEEK_TOKEN(parser);
1054+ if (!token) return 0;
1055+ if (token->type != YAML_FLOW_ENTRY_TOKEN
1056+ && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) {
1057+ if (!PUSH(parser, parser->states,
1058+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE))
1059+ return 0;
1060+ return yaml_parser_parse_node(parser, event, 0, 0);
1061+ }
1062+ }
1063+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE;
1064+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1065+}
1066+
1067+/*
1068+ * Parse the productions:
1069+ * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1070+ * *
1071+ */
1072+
1073+static int
1074+yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser,
1075+ yaml_event_t *event)
1076+{
1077+ yaml_token_t *token;
1078+
1079+ token = PEEK_TOKEN(parser);
1080+ if (!token) return 0;
1081+
1082+ parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE;
1083+
1084+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark);
1085+ return 1;
1086+}
1087+
1088+/*
1089+ * Parse the productions:
1090+ * flow_mapping ::= FLOW-MAPPING-START
1091+ * ******************
1092+ * (flow_mapping_entry FLOW-ENTRY)*
1093+ * * **********
1094+ * flow_mapping_entry?
1095+ * ******************
1096+ * FLOW-MAPPING-END
1097+ * ****************
1098+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1099+ * * *** *
1100+ */
1101+
1102+static int
1103+yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser,
1104+ yaml_event_t *event, int first)
1105+{
1106+ yaml_token_t *token;
1107+ yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */
1108+
1109+ if (first) {
1110+ token = PEEK_TOKEN(parser);
1111+ if (!PUSH(parser, parser->marks, token->start_mark))
1112+ return 0;
1113+ SKIP_TOKEN(parser);
1114+ }
1115+
1116+ token = PEEK_TOKEN(parser);
1117+ if (!token) return 0;
1118+
1119+ if (token->type != YAML_FLOW_MAPPING_END_TOKEN)
1120+ {
1121+ if (!first) {
1122+ if (token->type == YAML_FLOW_ENTRY_TOKEN) {
1123+ SKIP_TOKEN(parser);
1124+ token = PEEK_TOKEN(parser);
1125+ if (!token) return 0;
1126+ }
1127+ else {
1128+ return yaml_parser_set_parser_error_context(parser,
1129+ "while parsing a flow mapping", POP(parser, parser->marks),
1130+ "did not find expected ',' or '}'", token->start_mark);
1131+ }
1132+ }
1133+
1134+ if (token->type == YAML_KEY_TOKEN) {
1135+ SKIP_TOKEN(parser);
1136+ token = PEEK_TOKEN(parser);
1137+ if (!token) return 0;
1138+ if (token->type != YAML_VALUE_TOKEN
1139+ && token->type != YAML_FLOW_ENTRY_TOKEN
1140+ && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1141+ if (!PUSH(parser, parser->states,
1142+ YAML_PARSE_FLOW_MAPPING_VALUE_STATE))
1143+ return 0;
1144+ return yaml_parser_parse_node(parser, event, 0, 0);
1145+ }
1146+ else {
1147+ parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE;
1148+ return yaml_parser_process_empty_scalar(parser, event,
1149+ token->start_mark);
1150+ }
1151+ }
1152+ else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1153+ if (!PUSH(parser, parser->states,
1154+ YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE))
1155+ return 0;
1156+ return yaml_parser_parse_node(parser, event, 0, 0);
1157+ }
1158+ }
1159+
1160+ parser->state = POP(parser, parser->states);
1161+ dummy_mark = POP(parser, parser->marks);
1162+ MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark);
1163+ SKIP_TOKEN(parser);
1164+ return 1;
1165+}
1166+
1167+/*
1168+ * Parse the productions:
1169+ * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
1170+ * * ***** *
1171+ */
1172+
1173+static int
1174+yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser,
1175+ yaml_event_t *event, int empty)
1176+{
1177+ yaml_token_t *token;
1178+
1179+ token = PEEK_TOKEN(parser);
1180+ if (!token) return 0;
1181+
1182+ if (empty) {
1183+ parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1184+ return yaml_parser_process_empty_scalar(parser, event,
1185+ token->start_mark);
1186+ }
1187+
1188+ if (token->type == YAML_VALUE_TOKEN) {
1189+ SKIP_TOKEN(parser);
1190+ token = PEEK_TOKEN(parser);
1191+ if (!token) return 0;
1192+ if (token->type != YAML_FLOW_ENTRY_TOKEN
1193+ && token->type != YAML_FLOW_MAPPING_END_TOKEN) {
1194+ if (!PUSH(parser, parser->states,
1195+ YAML_PARSE_FLOW_MAPPING_KEY_STATE))
1196+ return 0;
1197+ return yaml_parser_parse_node(parser, event, 0, 0);
1198+ }
1199+ }
1200+
1201+ parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE;
1202+ return yaml_parser_process_empty_scalar(parser, event, token->start_mark);
1203+}
1204+
1205+/*
1206+ * Generate an empty scalar event.
1207+ */
1208+
1209+static int
1210+yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event,
1211+ yaml_mark_t mark)
1212+{
1213+ yaml_char_t *value;
1214+
1215+ value = yaml_malloc(1);
1216+ if (!value) {
1217+ parser->error = YAML_MEMORY_ERROR;
1218+ return 0;
1219+ }
1220+ value[0] = '\0';
1221+
1222+ SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0,
1223+ 1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark);
1224+
1225+ return 1;
1226+}
1227+
1228+/*
1229+ * Parse directives.
1230+ */
1231+
1232+static int
1233+yaml_parser_process_directives(yaml_parser_t *parser,
1234+ yaml_version_directive_t **version_directive_ref,
1235+ yaml_tag_directive_t **tag_directives_start_ref,
1236+ yaml_tag_directive_t **tag_directives_end_ref)
1237+{
1238+ yaml_tag_directive_t default_tag_directives[] = {
1239+ {(yaml_char_t *)"!", (yaml_char_t *)"!"},
1240+ {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"},
1241+ {NULL, NULL}
1242+ };
1243+ yaml_tag_directive_t *default_tag_directive;
1244+ yaml_version_directive_t *version_directive = NULL;
1245+ struct {
1246+ yaml_tag_directive_t *start;
1247+ yaml_tag_directive_t *end;
1248+ yaml_tag_directive_t *top;
1249+ } tag_directives = { NULL, NULL, NULL };
1250+ yaml_token_t *token;
1251+
1252+ if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE))
1253+ goto error;
1254+
1255+ token = PEEK_TOKEN(parser);
1256+ if (!token) goto error;
1257+
1258+ while (token->type == YAML_VERSION_DIRECTIVE_TOKEN ||
1259+ token->type == YAML_TAG_DIRECTIVE_TOKEN)
1260+ {
1261+ if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) {
1262+ if (version_directive) {
1263+ yaml_parser_set_parser_error(parser,
1264+ "found duplicate %YAML directive", token->start_mark);
1265+ goto error;
1266+ }
1267+ if (token->data.version_directive.major != 1
1268+ || token->data.version_directive.minor != 1) {
1269+ yaml_parser_set_parser_error(parser,
1270+ "found incompatible YAML document", token->start_mark);
1271+ goto error;
1272+ }
1273+ version_directive = yaml_malloc(sizeof(yaml_version_directive_t));
1274+ if (!version_directive) {
1275+ parser->error = YAML_MEMORY_ERROR;
1276+ goto error;
1277+ }
1278+ version_directive->major = token->data.version_directive.major;
1279+ version_directive->minor = token->data.version_directive.minor;
1280+ }
1281+
1282+ else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) {
1283+ yaml_tag_directive_t value = {
1284+ token->data.tag_directive.handle,
1285+ token->data.tag_directive.prefix
1286+ };
1287+ if (!yaml_parser_append_tag_directive(parser, value, 0,
1288+ token->start_mark))
1289+ goto error;
1290+ if (!PUSH(parser, tag_directives, value))
1291+ goto error;
1292+ }
1293+
1294+ SKIP_TOKEN(parser);
1295+ token = PEEK_TOKEN(parser);
1296+ if (!token) goto error;
1297+ }
1298+
1299+ for (default_tag_directive = default_tag_directives;
1300+ default_tag_directive->handle; default_tag_directive++) {
1301+ if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1,
1302+ token->start_mark))
1303+ goto error;
1304+ }
1305+
1306+ if (version_directive_ref) {
1307+ *version_directive_ref = version_directive;
1308+ }
1309+ if (tag_directives_start_ref) {
1310+ if (STACK_EMPTY(parser, tag_directives)) {
1311+ *tag_directives_start_ref = *tag_directives_end_ref = NULL;
1312+ STACK_DEL(parser, tag_directives);
1313+ }
1314+ else {
1315+ *tag_directives_start_ref = tag_directives.start;
1316+ *tag_directives_end_ref = tag_directives.top;
1317+ }
1318+ }
1319+ else {
1320+ STACK_DEL(parser, tag_directives);
1321+ }
1322+
1323+ return 1;
1324+
1325+error:
1326+ yaml_free(version_directive);
1327+ while (!STACK_EMPTY(parser, tag_directives)) {
1328+ yaml_tag_directive_t tag_directive = POP(parser, tag_directives);
1329+ yaml_free(tag_directive.handle);
1330+ yaml_free(tag_directive.prefix);
1331+ }
1332+ STACK_DEL(parser, tag_directives);
1333+ return 0;
1334+}
1335+
1336+/*
1337+ * Append a tag directive to the directives stack.
1338+ */
1339+
1340+static int
1341+yaml_parser_append_tag_directive(yaml_parser_t *parser,
1342+ yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark)
1343+{
1344+ yaml_tag_directive_t *tag_directive;
1345+ yaml_tag_directive_t copy = { NULL, NULL };
1346+
1347+ for (tag_directive = parser->tag_directives.start;
1348+ tag_directive != parser->tag_directives.top; tag_directive ++) {
1349+ if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) {
1350+ if (allow_duplicates)
1351+ return 1;
1352+ return yaml_parser_set_parser_error(parser,
1353+ "found duplicate %TAG directive", mark);
1354+ }
1355+ }
1356+
1357+ copy.handle = yaml_strdup(value.handle);
1358+ copy.prefix = yaml_strdup(value.prefix);
1359+ if (!copy.handle || !copy.prefix) {
1360+ parser->error = YAML_MEMORY_ERROR;
1361+ goto error;
1362+ }
1363+
1364+ if (!PUSH(parser, parser->tag_directives, copy))
1365+ goto error;
1366+
1367+ return 1;
1368+
1369+error:
1370+ yaml_free(copy.handle);
1371+ yaml_free(copy.prefix);
1372+ return 0;
1373+}
1374+
c/reader.cnew file+460
@@ -0,0 +1,460 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * Declarations.
6+ */
7+
8+static int
9+yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
10+ size_t offset, int value);
11+
12+static int
13+yaml_parser_update_raw_buffer(yaml_parser_t *parser);
14+
15+static int
16+yaml_parser_determine_encoding(yaml_parser_t *parser);
17+
18+YAML_DECLARE(int)
19+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
20+
21+/*
22+ * Set the reader error and return 0.
23+ */
24+
25+static int
26+yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
27+ size_t offset, int value)
28+{
29+ parser->error = YAML_READER_ERROR;
30+ parser->problem = problem;
31+ parser->problem_offset = offset;
32+ parser->problem_value = value;
33+
34+ return 0;
35+}
36+
37+/*
38+ * Byte order marks.
39+ */
40+
41+#define BOM_UTF8 "\xef\xbb\xbf"
42+#define BOM_UTF16LE "\xff\xfe"
43+#define BOM_UTF16BE "\xfe\xff"
44+
45+/*
46+ * Determine the input stream encoding by checking the BOM symbol. If no BOM is
47+ * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
48+ */
49+
50+static int
51+yaml_parser_determine_encoding(yaml_parser_t *parser)
52+{
53+ /* Ensure that we had enough bytes in the raw buffer. */
54+
55+ while (!parser->eof
56+ && parser->raw_buffer.last - parser->raw_buffer.pointer < 3) {
57+ if (!yaml_parser_update_raw_buffer(parser)) {
58+ return 0;
59+ }
60+ }
61+
62+ /* Determine the encoding. */
63+
64+ if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
65+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) {
66+ parser->encoding = YAML_UTF16LE_ENCODING;
67+ parser->raw_buffer.pointer += 2;
68+ parser->offset += 2;
69+ }
70+ else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
71+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) {
72+ parser->encoding = YAML_UTF16BE_ENCODING;
73+ parser->raw_buffer.pointer += 2;
74+ parser->offset += 2;
75+ }
76+ else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3
77+ && !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) {
78+ parser->encoding = YAML_UTF8_ENCODING;
79+ parser->raw_buffer.pointer += 3;
80+ parser->offset += 3;
81+ }
82+ else {
83+ parser->encoding = YAML_UTF8_ENCODING;
84+ }
85+
86+ return 1;
87+}
88+
89+/*
90+ * Update the raw buffer.
91+ */
92+
93+static int
94+yaml_parser_update_raw_buffer(yaml_parser_t *parser)
95+{
96+ size_t size_read = 0;
97+
98+ /* Return if the raw buffer is full. */
99+
100+ if (parser->raw_buffer.start == parser->raw_buffer.pointer
101+ && parser->raw_buffer.last == parser->raw_buffer.end)
102+ return 1;
103+
104+ /* Return on EOF. */
105+
106+ if (parser->eof) return 1;
107+
108+ /* Move the remaining bytes in the raw buffer to the beginning. */
109+
110+ if (parser->raw_buffer.start < parser->raw_buffer.pointer
111+ && parser->raw_buffer.pointer < parser->raw_buffer.last) {
112+ memmove(parser->raw_buffer.start, parser->raw_buffer.pointer,
113+ parser->raw_buffer.last - parser->raw_buffer.pointer);
114+ }
115+ parser->raw_buffer.last -=
116+ parser->raw_buffer.pointer - parser->raw_buffer.start;
117+ parser->raw_buffer.pointer = parser->raw_buffer.start;
118+
119+ /* Call the read handler to fill the buffer. */
120+
121+ if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last,
122+ parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) {
123+ return yaml_parser_set_reader_error(parser, "Input error",
124+ parser->offset, -1);
125+ }
126+ parser->raw_buffer.last += size_read;
127+ if (!size_read) {
128+ parser->eof = 1;
129+ }
130+
131+ return 1;
132+}
133+
134+/*
135+ * Ensure that the buffer contains at least `length` characters.
136+ * Return 1 on success, 0 on failure.
137+ *
138+ * The length is supposed to be significantly less that the buffer size.
139+ */
140+
141+YAML_DECLARE(int)
142+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
143+{
144+ assert(parser->read_handler); /* Read handler must be set. */
145+
146+ /* If the EOF flag is set and the raw buffer is empty, do nothing. */
147+
148+ if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
149+ return 1;
150+
151+ /* Return if the buffer contains enough characters. */
152+
153+ if (parser->unread >= length)
154+ return 1;
155+
156+ /* Determine the input encoding if it is not known yet. */
157+
158+ if (!parser->encoding) {
159+ if (!yaml_parser_determine_encoding(parser))
160+ return 0;
161+ }
162+
163+ /* Move the unread characters to the beginning of the buffer. */
164+
165+ if (parser->buffer.start < parser->buffer.pointer
166+ && parser->buffer.pointer < parser->buffer.last) {
167+ size_t size = parser->buffer.last - parser->buffer.pointer;
168+ memmove(parser->buffer.start, parser->buffer.pointer, size);
169+ parser->buffer.pointer = parser->buffer.start;
170+ parser->buffer.last = parser->buffer.start + size;
171+ }
172+ else if (parser->buffer.pointer == parser->buffer.last) {
173+ parser->buffer.pointer = parser->buffer.start;
174+ parser->buffer.last = parser->buffer.start;
175+ }
176+
177+ /* Fill the buffer until it has enough characters. */
178+
179+ while (parser->unread < length)
180+ {
181+ /* Fill the raw buffer. */
182+
183+ if (!yaml_parser_update_raw_buffer(parser)) return 0;
184+
185+ /* Decode the raw buffer. */
186+
187+ while (parser->raw_buffer.pointer != parser->raw_buffer.last)
188+ {
189+ unsigned int value = 0, value2 = 0;
190+ int incomplete = 0;
191+ unsigned char octet;
192+ unsigned int width = 0;
193+ int low, high;
194+ size_t k;
195+ size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
196+
197+ /* Decode the next character. */
198+
199+ switch (parser->encoding)
200+ {
201+ case YAML_UTF8_ENCODING:
202+
203+ /*
204+ * Decode a UTF-8 character. Check RFC 3629
205+ * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
206+ *
207+ * The following table (taken from the RFC) is used for
208+ * decoding.
209+ *
210+ * Char. number range | UTF-8 octet sequence
211+ * (hexadecimal) | (binary)
212+ * --------------------+------------------------------------
213+ * 0000 0000-0000 007F | 0xxxxxxx
214+ * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
215+ * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
216+ * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
217+ *
218+ * Additionally, the characters in the range 0xD800-0xDFFF
219+ * are prohibited as they are reserved for use with UTF-16
220+ * surrogate pairs.
221+ */
222+
223+ /* Determine the length of the UTF-8 sequence. */
224+
225+ octet = parser->raw_buffer.pointer[0];
226+ width = (octet & 0x80) == 0x00 ? 1 :
227+ (octet & 0xE0) == 0xC0 ? 2 :
228+ (octet & 0xF0) == 0xE0 ? 3 :
229+ (octet & 0xF8) == 0xF0 ? 4 : 0;
230+
231+ /* Check if the leading octet is valid. */
232+
233+ if (!width)
234+ return yaml_parser_set_reader_error(parser,
235+ "Invalid leading UTF-8 octet",
236+ parser->offset, octet);
237+
238+ /* Check if the raw buffer contains an incomplete character. */
239+
240+ if (width > raw_unread) {
241+ if (parser->eof) {
242+ return yaml_parser_set_reader_error(parser,
243+ "Incomplete UTF-8 octet sequence",
244+ parser->offset, -1);
245+ }
246+ incomplete = 1;
247+ break;
248+ }
249+
250+ /* Decode the leading octet. */
251+
252+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
253+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
254+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
255+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
256+
257+ /* Check and decode the trailing octets. */
258+
259+ for (k = 1; k < width; k ++)
260+ {
261+ octet = parser->raw_buffer.pointer[k];
262+
263+ /* Check if the octet is valid. */
264+
265+ if ((octet & 0xC0) != 0x80)
266+ return yaml_parser_set_reader_error(parser,
267+ "Invalid trailing UTF-8 octet",
268+ parser->offset+k, octet);
269+
270+ /* Decode the octet. */
271+
272+ value = (value << 6) + (octet & 0x3F);
273+ }
274+
275+ /* Check the length of the sequence against the value. */
276+
277+ if (!((width == 1) ||
278+ (width == 2 && value >= 0x80) ||
279+ (width == 3 && value >= 0x800) ||
280+ (width == 4 && value >= 0x10000)))
281+ return yaml_parser_set_reader_error(parser,
282+ "Invalid length of a UTF-8 sequence",
283+ parser->offset, -1);
284+
285+ /* Check the range of the value. */
286+
287+ if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
288+ return yaml_parser_set_reader_error(parser,
289+ "Invalid Unicode character",
290+ parser->offset, value);
291+
292+ break;
293+
294+ case YAML_UTF16LE_ENCODING:
295+ case YAML_UTF16BE_ENCODING:
296+
297+ low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
298+ high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
299+
300+ /*
301+ * The UTF-16 encoding is not as simple as one might
302+ * naively think. Check RFC 2781
303+ * (http://www.ietf.org/rfc/rfc2781.txt).
304+ *
305+ * Normally, two subsequent bytes describe a Unicode
306+ * character. However a special technique (called a
307+ * surrogate pair) is used for specifying character
308+ * values larger than 0xFFFF.
309+ *
310+ * A surrogate pair consists of two pseudo-characters:
311+ * high surrogate area (0xD800-0xDBFF)
312+ * low surrogate area (0xDC00-0xDFFF)
313+ *
314+ * The following formulas are used for decoding
315+ * and encoding characters using surrogate pairs:
316+ *
317+ * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
318+ * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
319+ * W1 = 110110yyyyyyyyyy
320+ * W2 = 110111xxxxxxxxxx
321+ *
322+ * where U is the character value, W1 is the high surrogate
323+ * area, W2 is the low surrogate area.
324+ */
325+
326+ /* Check for incomplete UTF-16 character. */
327+
328+ if (raw_unread < 2) {
329+ if (parser->eof) {
330+ return yaml_parser_set_reader_error(parser,
331+ "Incomplete UTF-16 character",
332+ parser->offset, -1);
333+ }
334+ incomplete = 1;
335+ break;
336+ }
337+
338+ /* Get the character. */
339+
340+ value = parser->raw_buffer.pointer[low]
341+ + (parser->raw_buffer.pointer[high] << 8);
342+
343+ /* Check for unexpected low surrogate area. */
344+
345+ if ((value & 0xFC00) == 0xDC00)
346+ return yaml_parser_set_reader_error(parser,
347+ "Unexpected low surrogate area",
348+ parser->offset, value);
349+
350+ /* Check for a high surrogate area. */
351+
352+ if ((value & 0xFC00) == 0xD800) {
353+
354+ width = 4;
355+
356+ /* Check for incomplete surrogate pair. */
357+
358+ if (raw_unread < 4) {
359+ if (parser->eof) {
360+ return yaml_parser_set_reader_error(parser,
361+ "Incomplete UTF-16 surrogate pair",
362+ parser->offset, -1);
363+ }
364+ incomplete = 1;
365+ break;
366+ }
367+
368+ /* Get the next character. */
369+
370+ value2 = parser->raw_buffer.pointer[low+2]
371+ + (parser->raw_buffer.pointer[high+2] << 8);
372+
373+ /* Check for a low surrogate area. */
374+
375+ if ((value2 & 0xFC00) != 0xDC00)
376+ return yaml_parser_set_reader_error(parser,
377+ "Expected low surrogate area",
378+ parser->offset+2, value2);
379+
380+ /* Generate the value of the surrogate pair. */
381+
382+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
383+ }
384+
385+ else {
386+ width = 2;
387+ }
388+
389+ break;
390+
391+ default:
392+ assert(1); /* Impossible. */
393+ }
394+
395+ /* Check if the raw buffer contains enough bytes to form a character. */
396+
397+ if (incomplete) break;
398+
399+ /*
400+ * Check if the character is in the allowed range:
401+ * #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
402+ * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
403+ * | [#x10000-#x10FFFF] (32 bit)
404+ */
405+
406+ if (! (value == 0x09 || value == 0x0A || value == 0x0D
407+ || (value >= 0x20 && value <= 0x7E)
408+ || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
409+ || (value >= 0xE000 && value <= 0xFFFD)
410+ || (value >= 0x10000 && value <= 0x10FFFF)))
411+ return yaml_parser_set_reader_error(parser,
412+ "Control characters are not allowed",
413+ parser->offset, value);
414+
415+ /* Move the raw pointers. */
416+
417+ parser->raw_buffer.pointer += width;
418+ parser->offset += width;
419+
420+ /* Finally put the character into the buffer. */
421+
422+ /* 0000 0000-0000 007F -> 0xxxxxxx */
423+ if (value <= 0x7F) {
424+ *(parser->buffer.last++) = value;
425+ }
426+ /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
427+ else if (value <= 0x7FF) {
428+ *(parser->buffer.last++) = 0xC0 + (value >> 6);
429+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
430+ }
431+ /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
432+ else if (value <= 0xFFFF) {
433+ *(parser->buffer.last++) = 0xE0 + (value >> 12);
434+ *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
435+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
436+ }
437+ /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
438+ else {
439+ *(parser->buffer.last++) = 0xF0 + (value >> 18);
440+ *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
441+ *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
442+ *(parser->buffer.last++) = 0x80 + (value & 0x3F);
443+ }
444+
445+ parser->unread ++;
446+ }
447+
448+ /* On EOF, put NUL into the buffer and return. */
449+
450+ if (parser->eof) {
451+ *(parser->buffer.last++) = '\0';
452+ parser->unread ++;
453+ return 1;
454+ }
455+
456+ }
457+
458+ return 1;
459+}
460+
c/scanner.cnew file+3568
@@ -0,0 +1,3568 @@
1+
2+/*
3+ * Introduction
4+ * ************
5+ *
6+ * The following notes assume that you are familiar with the YAML specification
7+ * (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in
8+ * some cases we are less restrictive that it requires.
9+ *
10+ * The process of transforming a YAML stream into a sequence of events is
11+ * divided on two steps: Scanning and Parsing.
12+ *
13+ * The Scanner transforms the input stream into a sequence of tokens, while the
14+ * parser transform the sequence of tokens produced by the Scanner into a
15+ * sequence of parsing events.
16+ *
17+ * The Scanner is rather clever and complicated. The Parser, on the contrary,
18+ * is a straightforward implementation of a recursive-descendant parser (or,
19+ * LL(1) parser, as it is usually called).
20+ *
21+ * Actually there are two issues of Scanning that might be called "clever", the
22+ * rest is quite straightforward. The issues are "block collection start" and
23+ * "simple keys". Both issues are explained below in details.
24+ *
25+ * Here the Scanning step is explained and implemented. We start with the list
26+ * of all the tokens produced by the Scanner together with short descriptions.
27+ *
28+ * Now, tokens:
29+ *
30+ * STREAM-START(encoding) # The stream start.
31+ * STREAM-END # The stream end.
32+ * VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
33+ * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
34+ * DOCUMENT-START # '---'
35+ * DOCUMENT-END # '...'
36+ * BLOCK-SEQUENCE-START # Indentation increase denoting a block
37+ * BLOCK-MAPPING-START # sequence or a block mapping.
38+ * BLOCK-END # Indentation decrease.
39+ * FLOW-SEQUENCE-START # '['
40+ * FLOW-SEQUENCE-END # ']'
41+ * BLOCK-SEQUENCE-START # '{'
42+ * BLOCK-SEQUENCE-END # '}'
43+ * BLOCK-ENTRY # '-'
44+ * FLOW-ENTRY # ','
45+ * KEY # '?' or nothing (simple keys).
46+ * VALUE # ':'
47+ * ALIAS(anchor) # '*anchor'
48+ * ANCHOR(anchor) # '&anchor'
49+ * TAG(handle,suffix) # '!handle!suffix'
50+ * SCALAR(value,style) # A scalar.
51+ *
52+ * The following two tokens are "virtual" tokens denoting the beginning and the
53+ * end of the stream:
54+ *
55+ * STREAM-START(encoding)
56+ * STREAM-END
57+ *
58+ * We pass the information about the input stream encoding with the
59+ * STREAM-START token.
60+ *
61+ * The next two tokens are responsible for tags:
62+ *
63+ * VERSION-DIRECTIVE(major,minor)
64+ * TAG-DIRECTIVE(handle,prefix)
65+ *
66+ * Example:
67+ *
68+ * %YAML 1.1
69+ * %TAG ! !foo
70+ * %TAG !yaml! tag:yaml.org,2002:
71+ * ---
72+ *
73+ * The correspoding sequence of tokens:
74+ *
75+ * STREAM-START(utf-8)
76+ * VERSION-DIRECTIVE(1,1)
77+ * TAG-DIRECTIVE("!","!foo")
78+ * TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
79+ * DOCUMENT-START
80+ * STREAM-END
81+ *
82+ * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
83+ * line.
84+ *
85+ * The document start and end indicators are represented by:
86+ *
87+ * DOCUMENT-START
88+ * DOCUMENT-END
89+ *
90+ * Note that if a YAML stream contains an implicit document (without '---'
91+ * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
92+ * produced.
93+ *
94+ * In the following examples, we present whole documents together with the
95+ * produced tokens.
96+ *
97+ * 1. An implicit document:
98+ *
99+ * 'a scalar'
100+ *
101+ * Tokens:
102+ *
103+ * STREAM-START(utf-8)
104+ * SCALAR("a scalar",single-quoted)
105+ * STREAM-END
106+ *
107+ * 2. An explicit document:
108+ *
109+ * ---
110+ * 'a scalar'
111+ * ...
112+ *
113+ * Tokens:
114+ *
115+ * STREAM-START(utf-8)
116+ * DOCUMENT-START
117+ * SCALAR("a scalar",single-quoted)
118+ * DOCUMENT-END
119+ * STREAM-END
120+ *
121+ * 3. Several documents in a stream:
122+ *
123+ * 'a scalar'
124+ * ---
125+ * 'another scalar'
126+ * ---
127+ * 'yet another scalar'
128+ *
129+ * Tokens:
130+ *
131+ * STREAM-START(utf-8)
132+ * SCALAR("a scalar",single-quoted)
133+ * DOCUMENT-START
134+ * SCALAR("another scalar",single-quoted)
135+ * DOCUMENT-START
136+ * SCALAR("yet another scalar",single-quoted)
137+ * STREAM-END
138+ *
139+ * We have already introduced the SCALAR token above. The following tokens are
140+ * used to describe aliases, anchors, tag, and scalars:
141+ *
142+ * ALIAS(anchor)
143+ * ANCHOR(anchor)
144+ * TAG(handle,suffix)
145+ * SCALAR(value,style)
146+ *
147+ * The following series of examples illustrate the usage of these tokens:
148+ *
149+ * 1. A recursive sequence:
150+ *
151+ * &A [ *A ]
152+ *
153+ * Tokens:
154+ *
155+ * STREAM-START(utf-8)
156+ * ANCHOR("A")
157+ * FLOW-SEQUENCE-START
158+ * ALIAS("A")
159+ * FLOW-SEQUENCE-END
160+ * STREAM-END
161+ *
162+ * 2. A tagged scalar:
163+ *
164+ * !!float "3.14" # A good approximation.
165+ *
166+ * Tokens:
167+ *
168+ * STREAM-START(utf-8)
169+ * TAG("!!","float")
170+ * SCALAR("3.14",double-quoted)
171+ * STREAM-END
172+ *
173+ * 3. Various scalar styles:
174+ *
175+ * --- # Implicit empty plain scalars do not produce tokens.
176+ * --- a plain scalar
177+ * --- 'a single-quoted scalar'
178+ * --- "a double-quoted scalar"
179+ * --- |-
180+ * a literal scalar
181+ * --- >-
182+ * a folded
183+ * scalar
184+ *
185+ * Tokens:
186+ *
187+ * STREAM-START(utf-8)
188+ * DOCUMENT-START
189+ * DOCUMENT-START
190+ * SCALAR("a plain scalar",plain)
191+ * DOCUMENT-START
192+ * SCALAR("a single-quoted scalar",single-quoted)
193+ * DOCUMENT-START
194+ * SCALAR("a double-quoted scalar",double-quoted)
195+ * DOCUMENT-START
196+ * SCALAR("a literal scalar",literal)
197+ * DOCUMENT-START
198+ * SCALAR("a folded scalar",folded)
199+ * STREAM-END
200+ *
201+ * Now it's time to review collection-related tokens. We will start with
202+ * flow collections:
203+ *
204+ * FLOW-SEQUENCE-START
205+ * FLOW-SEQUENCE-END
206+ * FLOW-MAPPING-START
207+ * FLOW-MAPPING-END
208+ * FLOW-ENTRY
209+ * KEY
210+ * VALUE
211+ *
212+ * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
213+ * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
214+ * correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
215+ * indicators '?' and ':', which are used for denoting mapping keys and values,
216+ * are represented by the KEY and VALUE tokens.
217+ *
218+ * The following examples show flow collections:
219+ *
220+ * 1. A flow sequence:
221+ *
222+ * [item 1, item 2, item 3]
223+ *
224+ * Tokens:
225+ *
226+ * STREAM-START(utf-8)
227+ * FLOW-SEQUENCE-START
228+ * SCALAR("item 1",plain)
229+ * FLOW-ENTRY
230+ * SCALAR("item 2",plain)
231+ * FLOW-ENTRY
232+ * SCALAR("item 3",plain)
233+ * FLOW-SEQUENCE-END
234+ * STREAM-END
235+ *
236+ * 2. A flow mapping:
237+ *
238+ * {
239+ * a simple key: a value, # Note that the KEY token is produced.
240+ * ? a complex key: another value,
241+ * }
242+ *
243+ * Tokens:
244+ *
245+ * STREAM-START(utf-8)
246+ * FLOW-MAPPING-START
247+ * KEY
248+ * SCALAR("a simple key",plain)
249+ * VALUE
250+ * SCALAR("a value",plain)
251+ * FLOW-ENTRY
252+ * KEY
253+ * SCALAR("a complex key",plain)
254+ * VALUE
255+ * SCALAR("another value",plain)
256+ * FLOW-ENTRY
257+ * FLOW-MAPPING-END
258+ * STREAM-END
259+ *
260+ * A simple key is a key which is not denoted by the '?' indicator. Note that
261+ * the Scanner still produce the KEY token whenever it encounters a simple key.
262+ *
263+ * For scanning block collections, the following tokens are used (note that we
264+ * repeat KEY and VALUE here):
265+ *
266+ * BLOCK-SEQUENCE-START
267+ * BLOCK-MAPPING-START
268+ * BLOCK-END
269+ * BLOCK-ENTRY
270+ * KEY
271+ * VALUE
272+ *
273+ * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
274+ * increase that precedes a block collection (cf. the INDENT token in Python).
275+ * The token BLOCK-END denote indentation decrease that ends a block collection
276+ * (cf. the DEDENT token in Python). However YAML has some syntax pecularities
277+ * that makes detections of these tokens more complex.
278+ *
279+ * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
280+ * '-', '?', and ':' correspondingly.
281+ *
282+ * The following examples show how the tokens BLOCK-SEQUENCE-START,
283+ * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
284+ *
285+ * 1. Block sequences:
286+ *
287+ * - item 1
288+ * - item 2
289+ * -
290+ * - item 3.1
291+ * - item 3.2
292+ * -
293+ * key 1: value 1
294+ * key 2: value 2
295+ *
296+ * Tokens:
297+ *
298+ * STREAM-START(utf-8)
299+ * BLOCK-SEQUENCE-START
300+ * BLOCK-ENTRY
301+ * SCALAR("item 1",plain)
302+ * BLOCK-ENTRY
303+ * SCALAR("item 2",plain)
304+ * BLOCK-ENTRY
305+ * BLOCK-SEQUENCE-START
306+ * BLOCK-ENTRY
307+ * SCALAR("item 3.1",plain)
308+ * BLOCK-ENTRY
309+ * SCALAR("item 3.2",plain)
310+ * BLOCK-END
311+ * BLOCK-ENTRY
312+ * BLOCK-MAPPING-START
313+ * KEY
314+ * SCALAR("key 1",plain)
315+ * VALUE
316+ * SCALAR("value 1",plain)
317+ * KEY
318+ * SCALAR("key 2",plain)
319+ * VALUE
320+ * SCALAR("value 2",plain)
321+ * BLOCK-END
322+ * BLOCK-END
323+ * STREAM-END
324+ *
325+ * 2. Block mappings:
326+ *
327+ * a simple key: a value # The KEY token is produced here.
328+ * ? a complex key
329+ * : another value
330+ * a mapping:
331+ * key 1: value 1
332+ * key 2: value 2
333+ * a sequence:
334+ * - item 1
335+ * - item 2
336+ *
337+ * Tokens:
338+ *
339+ * STREAM-START(utf-8)
340+ * BLOCK-MAPPING-START
341+ * KEY
342+ * SCALAR("a simple key",plain)
343+ * VALUE
344+ * SCALAR("a value",plain)
345+ * KEY
346+ * SCALAR("a complex key",plain)
347+ * VALUE
348+ * SCALAR("another value",plain)
349+ * KEY
350+ * SCALAR("a mapping",plain)
351+ * BLOCK-MAPPING-START
352+ * KEY
353+ * SCALAR("key 1",plain)
354+ * VALUE
355+ * SCALAR("value 1",plain)
356+ * KEY
357+ * SCALAR("key 2",plain)
358+ * VALUE
359+ * SCALAR("value 2",plain)
360+ * BLOCK-END
361+ * KEY
362+ * SCALAR("a sequence",plain)
363+ * VALUE
364+ * BLOCK-SEQUENCE-START
365+ * BLOCK-ENTRY
366+ * SCALAR("item 1",plain)
367+ * BLOCK-ENTRY
368+ * SCALAR("item 2",plain)
369+ * BLOCK-END
370+ * BLOCK-END
371+ * STREAM-END
372+ *
373+ * YAML does not always require to start a new block collection from a new
374+ * line. If the current line contains only '-', '?', and ':' indicators, a new
375+ * block collection may start at the current line. The following examples
376+ * illustrate this case:
377+ *
378+ * 1. Collections in a sequence:
379+ *
380+ * - - item 1
381+ * - item 2
382+ * - key 1: value 1
383+ * key 2: value 2
384+ * - ? complex key
385+ * : complex value
386+ *
387+ * Tokens:
388+ *
389+ * STREAM-START(utf-8)
390+ * BLOCK-SEQUENCE-START
391+ * BLOCK-ENTRY
392+ * BLOCK-SEQUENCE-START
393+ * BLOCK-ENTRY
394+ * SCALAR("item 1",plain)
395+ * BLOCK-ENTRY
396+ * SCALAR("item 2",plain)
397+ * BLOCK-END
398+ * BLOCK-ENTRY
399+ * BLOCK-MAPPING-START
400+ * KEY
401+ * SCALAR("key 1",plain)
402+ * VALUE
403+ * SCALAR("value 1",plain)
404+ * KEY
405+ * SCALAR("key 2",plain)
406+ * VALUE
407+ * SCALAR("value 2",plain)
408+ * BLOCK-END
409+ * BLOCK-ENTRY
410+ * BLOCK-MAPPING-START
411+ * KEY
412+ * SCALAR("complex key")
413+ * VALUE
414+ * SCALAR("complex value")
415+ * BLOCK-END
416+ * BLOCK-END
417+ * STREAM-END
418+ *
419+ * 2. Collections in a mapping:
420+ *
421+ * ? a sequence
422+ * : - item 1
423+ * - item 2
424+ * ? a mapping
425+ * : key 1: value 1
426+ * key 2: value 2
427+ *
428+ * Tokens:
429+ *
430+ * STREAM-START(utf-8)
431+ * BLOCK-MAPPING-START
432+ * KEY
433+ * SCALAR("a sequence",plain)
434+ * VALUE
435+ * BLOCK-SEQUENCE-START
436+ * BLOCK-ENTRY
437+ * SCALAR("item 1",plain)
438+ * BLOCK-ENTRY
439+ * SCALAR("item 2",plain)
440+ * BLOCK-END
441+ * KEY
442+ * SCALAR("a mapping",plain)
443+ * VALUE
444+ * BLOCK-MAPPING-START
445+ * KEY
446+ * SCALAR("key 1",plain)
447+ * VALUE
448+ * SCALAR("value 1",plain)
449+ * KEY
450+ * SCALAR("key 2",plain)
451+ * VALUE
452+ * SCALAR("value 2",plain)
453+ * BLOCK-END
454+ * BLOCK-END
455+ * STREAM-END
456+ *
457+ * YAML also permits non-indented sequences if they are included into a block
458+ * mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
459+ *
460+ * key:
461+ * - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
462+ * - item 2
463+ *
464+ * Tokens:
465+ *
466+ * STREAM-START(utf-8)
467+ * BLOCK-MAPPING-START
468+ * KEY
469+ * SCALAR("key",plain)
470+ * VALUE
471+ * BLOCK-ENTRY
472+ * SCALAR("item 1",plain)
473+ * BLOCK-ENTRY
474+ * SCALAR("item 2",plain)
475+ * BLOCK-END
476+ */
477+
478+#include "yaml_private.h"
479+
480+/*
481+ * Ensure that the buffer contains the required number of characters.
482+ * Return 1 on success, 0 on failure (reader error or memory error).
483+ */
484+
485+#define CACHE(parser,length) \
486+ (parser->unread >= (length) \
487+ ? 1 \
488+ : yaml_parser_update_buffer(parser, (length)))
489+
490+/*
491+ * Advance the buffer pointer.
492+ */
493+
494+#define SKIP(parser) \
495+ (parser->mark.index ++, \
496+ parser->mark.column ++, \
497+ parser->unread --, \
498+ parser->buffer.pointer += WIDTH(parser->buffer))
499+
500+#define SKIP_LINE(parser) \
501+ (IS_CRLF(parser->buffer) ? \
502+ (parser->mark.index += 2, \
503+ parser->mark.column = 0, \
504+ parser->mark.line ++, \
505+ parser->unread -= 2, \
506+ parser->buffer.pointer += 2) : \
507+ IS_BREAK(parser->buffer) ? \
508+ (parser->mark.index ++, \
509+ parser->mark.column = 0, \
510+ parser->mark.line ++, \
511+ parser->unread --, \
512+ parser->buffer.pointer += WIDTH(parser->buffer)) : 0)
513+
514+/*
515+ * Copy a character to a string buffer and advance pointers.
516+ */
517+
518+#define READ(parser,string) \
519+ (STRING_EXTEND(parser,string) ? \
520+ (COPY(string,parser->buffer), \
521+ parser->mark.index ++, \
522+ parser->mark.column ++, \
523+ parser->unread --, \
524+ 1) : 0)
525+
526+/*
527+ * Copy a line break character to a string buffer and advance pointers.
528+ */
529+
530+#define READ_LINE(parser,string) \
531+ (STRING_EXTEND(parser,string) ? \
532+ (((CHECK_AT(parser->buffer,'\r',0) \
533+ && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \
534+ (*((string).pointer++) = (yaml_char_t) '\n', \
535+ parser->buffer.pointer += 2, \
536+ parser->mark.index += 2, \
537+ parser->mark.column = 0, \
538+ parser->mark.line ++, \
539+ parser->unread -= 2) : \
540+ (CHECK_AT(parser->buffer,'\r',0) \
541+ || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \
542+ (*((string).pointer++) = (yaml_char_t) '\n', \
543+ parser->buffer.pointer ++, \
544+ parser->mark.index ++, \
545+ parser->mark.column = 0, \
546+ parser->mark.line ++, \
547+ parser->unread --) : \
548+ (CHECK_AT(parser->buffer,'\xC2',0) \
549+ && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \
550+ (*((string).pointer++) = (yaml_char_t) '\n', \
551+ parser->buffer.pointer += 2, \
552+ parser->mark.index ++, \
553+ parser->mark.column = 0, \
554+ parser->mark.line ++, \
555+ parser->unread --) : \
556+ (CHECK_AT(parser->buffer,'\xE2',0) && \
557+ CHECK_AT(parser->buffer,'\x80',1) && \
558+ (CHECK_AT(parser->buffer,'\xA8',2) || \
559+ CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \
560+ (*((string).pointer++) = *(parser->buffer.pointer++), \
561+ *((string).pointer++) = *(parser->buffer.pointer++), \
562+ *((string).pointer++) = *(parser->buffer.pointer++), \
563+ parser->mark.index ++, \
564+ parser->mark.column = 0, \
565+ parser->mark.line ++, \
566+ parser->unread --) : 0), \
567+ 1) : 0)
568+
569+/*
570+ * Public API declarations.
571+ */
572+
573+YAML_DECLARE(int)
574+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
575+
576+/*
577+ * Error handling.
578+ */
579+
580+static int
581+yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
582+ yaml_mark_t context_mark, const char *problem);
583+
584+/*
585+ * High-level token API.
586+ */
587+
588+YAML_DECLARE(int)
589+yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
590+
591+static int
592+yaml_parser_fetch_next_token(yaml_parser_t *parser);
593+
594+/*
595+ * Potential simple keys.
596+ */
597+
598+static int
599+yaml_parser_stale_simple_keys(yaml_parser_t *parser);
600+
601+static int
602+yaml_parser_save_simple_key(yaml_parser_t *parser);
603+
604+static int
605+yaml_parser_remove_simple_key(yaml_parser_t *parser);
606+
607+static int
608+yaml_parser_increase_flow_level(yaml_parser_t *parser);
609+
610+static int
611+yaml_parser_decrease_flow_level(yaml_parser_t *parser);
612+
613+/*
614+ * Indentation treatment.
615+ */
616+
617+static int
618+yaml_parser_roll_indent(yaml_parser_t *parser, int column,
619+ int number, yaml_token_type_t type, yaml_mark_t mark);
620+
621+static int
622+yaml_parser_unroll_indent(yaml_parser_t *parser, int column);
623+
624+/*
625+ * Token fetchers.
626+ */
627+
628+static int
629+yaml_parser_fetch_stream_start(yaml_parser_t *parser);
630+
631+static int
632+yaml_parser_fetch_stream_end(yaml_parser_t *parser);
633+
634+static int
635+yaml_parser_fetch_directive(yaml_parser_t *parser);
636+
637+static int
638+yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
639+ yaml_token_type_t type);
640+
641+static int
642+yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
643+ yaml_token_type_t type);
644+
645+static int
646+yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
647+ yaml_token_type_t type);
648+
649+static int
650+yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
651+
652+static int
653+yaml_parser_fetch_block_entry(yaml_parser_t *parser);
654+
655+static int
656+yaml_parser_fetch_key(yaml_parser_t *parser);
657+
658+static int
659+yaml_parser_fetch_value(yaml_parser_t *parser);
660+
661+static int
662+yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
663+
664+static int
665+yaml_parser_fetch_tag(yaml_parser_t *parser);
666+
667+static int
668+yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
669+
670+static int
671+yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
672+
673+static int
674+yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
675+
676+/*
677+ * Token scanners.
678+ */
679+
680+static int
681+yaml_parser_scan_to_next_token(yaml_parser_t *parser);
682+
683+static int
684+yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token);
685+
686+static int
687+yaml_parser_scan_directive_name(yaml_parser_t *parser,
688+ yaml_mark_t start_mark, yaml_char_t **name);
689+
690+static int
691+yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
692+ yaml_mark_t start_mark, int *major, int *minor);
693+
694+static int
695+yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
696+ yaml_mark_t start_mark, int *number);
697+
698+static int
699+yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
700+ yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
701+
702+static int
703+yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
704+ yaml_token_type_t type);
705+
706+static int
707+yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token);
708+
709+static int
710+yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
711+ yaml_mark_t start_mark, yaml_char_t **handle);
712+
713+static int
714+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
715+ yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
716+
717+static int
718+yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
719+ yaml_mark_t start_mark, yaml_string_t *string);
720+
721+static int
722+yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
723+ int literal);
724+
725+static int
726+yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
727+ int *indent, yaml_string_t *breaks,
728+ yaml_mark_t start_mark, yaml_mark_t *end_mark);
729+
730+static int
731+yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
732+ int single);
733+
734+static int
735+yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token);
736+
737+/*
738+ * Get the next token.
739+ */
740+
741+YAML_DECLARE(int)
742+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token)
743+{
744+ assert(parser); /* Non-NULL parser object is expected. */
745+ assert(token); /* Non-NULL token object is expected. */
746+
747+ /* Erase the token object. */
748+
749+ memset(token, 0, sizeof(yaml_token_t));
750+
751+ /* No tokens after STREAM-END or error. */
752+
753+ if (parser->stream_end_produced || parser->error) {
754+ return 1;
755+ }
756+
757+ /* Ensure that the tokens queue contains enough tokens. */
758+
759+ if (!parser->token_available) {
760+ if (!yaml_parser_fetch_more_tokens(parser))
761+ return 0;
762+ }
763+
764+ /* Fetch the next token from the queue. */
765+
766+ *token = DEQUEUE(parser, parser->tokens);
767+ parser->token_available = 0;
768+ parser->tokens_parsed ++;
769+
770+ if (token->type == YAML_STREAM_END_TOKEN) {
771+ parser->stream_end_produced = 1;
772+ }
773+
774+ return 1;
775+}
776+
777+/*
778+ * Set the scanner error and return 0.
779+ */
780+
781+static int
782+yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
783+ yaml_mark_t context_mark, const char *problem)
784+{
785+ parser->error = YAML_SCANNER_ERROR;
786+ parser->context = context;
787+ parser->context_mark = context_mark;
788+ parser->problem = problem;
789+ parser->problem_mark = parser->mark;
790+
791+ return 0;
792+}
793+
794+/*
795+ * Ensure that the tokens queue contains at least one token which can be
796+ * returned to the Parser.
797+ */
798+
799+YAML_DECLARE(int)
800+yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
801+{
802+ int need_more_tokens;
803+
804+ /* While we need more tokens to fetch, do it. */
805+
806+ while (1)
807+ {
808+ /*
809+ * Check if we really need to fetch more tokens.
810+ */
811+
812+ need_more_tokens = 0;
813+
814+ if (parser->tokens.head == parser->tokens.tail)
815+ {
816+ /* Queue is empty. */
817+
818+ need_more_tokens = 1;
819+ }
820+ else
821+ {
822+ yaml_simple_key_t *simple_key;
823+
824+ /* Check if any potential simple key may occupy the head position. */
825+
826+ if (!yaml_parser_stale_simple_keys(parser))
827+ return 0;
828+
829+ for (simple_key = parser->simple_keys.start;
830+ simple_key != parser->simple_keys.top; simple_key++) {
831+ if (simple_key->possible
832+ && simple_key->token_number == parser->tokens_parsed) {
833+ need_more_tokens = 1;
834+ break;
835+ }
836+ }
837+ }
838+
839+ /* We are finished. */
840+
841+ if (!need_more_tokens)
842+ break;
843+
844+ /* Fetch the next token. */
845+
846+ if (!yaml_parser_fetch_next_token(parser))
847+ return 0;
848+ }
849+
850+ parser->token_available = 1;
851+
852+ return 1;
853+}
854+
855+/*
856+ * The dispatcher for token fetchers.
857+ */
858+
859+static int
860+yaml_parser_fetch_next_token(yaml_parser_t *parser)
861+{
862+ /* Ensure that the buffer is initialized. */
863+
864+ if (!CACHE(parser, 1))
865+ return 0;
866+
867+ /* Check if we just started scanning. Fetch STREAM-START then. */
868+
869+ if (!parser->stream_start_produced)
870+ return yaml_parser_fetch_stream_start(parser);
871+
872+ /* Eat whitespaces and comments until we reach the next token. */
873+
874+ if (!yaml_parser_scan_to_next_token(parser))
875+ return 0;
876+
877+ /* Remove obsolete potential simple keys. */
878+
879+ if (!yaml_parser_stale_simple_keys(parser))
880+ return 0;
881+
882+ /* Check the indentation level against the current column. */
883+
884+ if (!yaml_parser_unroll_indent(parser, parser->mark.column))
885+ return 0;
886+
887+ /*
888+ * Ensure that the buffer contains at least 4 characters. 4 is the length
889+ * of the longest indicators ('--- ' and '... ').
890+ */
891+
892+ if (!CACHE(parser, 4))
893+ return 0;
894+
895+ /* Is it the end of the stream? */
896+
897+ if (IS_Z(parser->buffer))
898+ return yaml_parser_fetch_stream_end(parser);
899+
900+ /* Is it a directive? */
901+
902+ if (parser->mark.column == 0 && CHECK(parser->buffer, '%'))
903+ return yaml_parser_fetch_directive(parser);
904+
905+ /* Is it the document start indicator? */
906+
907+ if (parser->mark.column == 0
908+ && CHECK_AT(parser->buffer, '-', 0)
909+ && CHECK_AT(parser->buffer, '-', 1)
910+ && CHECK_AT(parser->buffer, '-', 2)
911+ && IS_BLANKZ_AT(parser->buffer, 3))
912+ return yaml_parser_fetch_document_indicator(parser,
913+ YAML_DOCUMENT_START_TOKEN);
914+
915+ /* Is it the document end indicator? */
916+
917+ if (parser->mark.column == 0
918+ && CHECK_AT(parser->buffer, '.', 0)
919+ && CHECK_AT(parser->buffer, '.', 1)
920+ && CHECK_AT(parser->buffer, '.', 2)
921+ && IS_BLANKZ_AT(parser->buffer, 3))
922+ return yaml_parser_fetch_document_indicator(parser,
923+ YAML_DOCUMENT_END_TOKEN);
924+
925+ /* Is it the flow sequence start indicator? */
926+
927+ if (CHECK(parser->buffer, '['))
928+ return yaml_parser_fetch_flow_collection_start(parser,
929+ YAML_FLOW_SEQUENCE_START_TOKEN);
930+
931+ /* Is it the flow mapping start indicator? */
932+
933+ if (CHECK(parser->buffer, '{'))
934+ return yaml_parser_fetch_flow_collection_start(parser,
935+ YAML_FLOW_MAPPING_START_TOKEN);
936+
937+ /* Is it the flow sequence end indicator? */
938+
939+ if (CHECK(parser->buffer, ']'))
940+ return yaml_parser_fetch_flow_collection_end(parser,
941+ YAML_FLOW_SEQUENCE_END_TOKEN);
942+
943+ /* Is it the flow mapping end indicator? */
944+
945+ if (CHECK(parser->buffer, '}'))
946+ return yaml_parser_fetch_flow_collection_end(parser,
947+ YAML_FLOW_MAPPING_END_TOKEN);
948+
949+ /* Is it the flow entry indicator? */
950+
951+ if (CHECK(parser->buffer, ','))
952+ return yaml_parser_fetch_flow_entry(parser);
953+
954+ /* Is it the block entry indicator? */
955+
956+ if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1))
957+ return yaml_parser_fetch_block_entry(parser);
958+
959+ /* Is it the key indicator? */
960+
961+ if (CHECK(parser->buffer, '?')
962+ && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
963+ return yaml_parser_fetch_key(parser);
964+
965+ /* Is it the value indicator? */
966+
967+ if (CHECK(parser->buffer, ':')
968+ && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1)))
969+ return yaml_parser_fetch_value(parser);
970+
971+ /* Is it an alias? */
972+
973+ if (CHECK(parser->buffer, '*'))
974+ return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
975+
976+ /* Is it an anchor? */
977+
978+ if (CHECK(parser->buffer, '&'))
979+ return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
980+
981+ /* Is it a tag? */
982+
983+ if (CHECK(parser->buffer, '!'))
984+ return yaml_parser_fetch_tag(parser);
985+
986+ /* Is it a literal scalar? */
987+
988+ if (CHECK(parser->buffer, '|') && !parser->flow_level)
989+ return yaml_parser_fetch_block_scalar(parser, 1);
990+
991+ /* Is it a folded scalar? */
992+
993+ if (CHECK(parser->buffer, '>') && !parser->flow_level)
994+ return yaml_parser_fetch_block_scalar(parser, 0);
995+
996+ /* Is it a single-quoted scalar? */
997+
998+ if (CHECK(parser->buffer, '\''))
999+ return yaml_parser_fetch_flow_scalar(parser, 1);
1000+
1001+ /* Is it a double-quoted scalar? */
1002+
1003+ if (CHECK(parser->buffer, '"'))
1004+ return yaml_parser_fetch_flow_scalar(parser, 0);
1005+
1006+ /*
1007+ * Is it a plain scalar?
1008+ *
1009+ * A plain scalar may start with any non-blank characters except
1010+ *
1011+ * '-', '?', ':', ',', '[', ']', '{', '}',
1012+ * '#', '&', '*', '!', '|', '>', '\'', '\"',
1013+ * '%', '@', '`'.
1014+ *
1015+ * In the block context (and, for the '-' indicator, in the flow context
1016+ * too), it may also start with the characters
1017+ *
1018+ * '-', '?', ':'
1019+ *
1020+ * if it is followed by a non-space character.
1021+ *
1022+ * The last rule is more restrictive than the specification requires.
1023+ */
1024+
1025+ if (!(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '-')
1026+ || CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':')
1027+ || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[')
1028+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
1029+ || CHECK(parser->buffer, '}') || CHECK(parser->buffer, '#')
1030+ || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '*')
1031+ || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '|')
1032+ || CHECK(parser->buffer, '>') || CHECK(parser->buffer, '\'')
1033+ || CHECK(parser->buffer, '"') || CHECK(parser->buffer, '%')
1034+ || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '`')) ||
1035+ (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) ||
1036+ (!parser->flow_level &&
1037+ (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':'))
1038+ && !IS_BLANKZ_AT(parser->buffer, 1)))
1039+ return yaml_parser_fetch_plain_scalar(parser);
1040+
1041+ /*
1042+ * If we don't determine the token type so far, it is an error.
1043+ */
1044+
1045+ return yaml_parser_set_scanner_error(parser,
1046+ "while scanning for the next token", parser->mark,
1047+ "found character that cannot start any token");
1048+}
1049+
1050+/*
1051+ * Check the list of potential simple keys and remove the positions that
1052+ * cannot contain simple keys anymore.
1053+ */
1054+
1055+static int
1056+yaml_parser_stale_simple_keys(yaml_parser_t *parser)
1057+{
1058+ yaml_simple_key_t *simple_key;
1059+
1060+ /* Check for a potential simple key for each flow level. */
1061+
1062+ for (simple_key = parser->simple_keys.start;
1063+ simple_key != parser->simple_keys.top; simple_key ++)
1064+ {
1065+ /*
1066+ * The specification requires that a simple key
1067+ *
1068+ * - is limited to a single line,
1069+ * - is shorter than 1024 characters.
1070+ */
1071+
1072+ if (simple_key->possible
1073+ && (simple_key->mark.line < parser->mark.line
1074+ || simple_key->mark.index+1024 < parser->mark.index)) {
1075+
1076+ /* Check if the potential simple key to be removed is required. */
1077+
1078+ if (simple_key->required) {
1079+ return yaml_parser_set_scanner_error(parser,
1080+ "while scanning a simple key", simple_key->mark,
1081+ "could not find expected ':'");
1082+ }
1083+
1084+ simple_key->possible = 0;
1085+ }
1086+ }
1087+
1088+ return 1;
1089+}
1090+
1091+/*
1092+ * Check if a simple key may start at the current position and add it if
1093+ * needed.
1094+ */
1095+
1096+static int
1097+yaml_parser_save_simple_key(yaml_parser_t *parser)
1098+{
1099+ /*
1100+ * A simple key is required at the current position if the scanner is in
1101+ * the block context and the current column coincides with the indentation
1102+ * level.
1103+ */
1104+
1105+ int required = (!parser->flow_level
1106+ && parser->indent == (int)parser->mark.column);
1107+
1108+ /*
1109+ * A simple key is required only when it is the first token in the current
1110+ * line. Therefore it is always allowed. But we add a check anyway.
1111+ */
1112+
1113+ assert(parser->simple_key_allowed || !required); /* Impossible. */
1114+
1115+ /*
1116+ * If the current position may start a simple key, save it.
1117+ */
1118+
1119+ if (parser->simple_key_allowed)
1120+ {
1121+ yaml_simple_key_t simple_key = { 1, required,
1122+ parser->tokens_parsed + parser->tokens.tail - parser->tokens.head,
1123+ { 0, 0, 0 } };
1124+ simple_key.mark = parser->mark;
1125+
1126+ if (!yaml_parser_remove_simple_key(parser)) return 0;
1127+
1128+ *(parser->simple_keys.top-1) = simple_key;
1129+ }
1130+
1131+ return 1;
1132+}
1133+
1134+/*
1135+ * Remove a potential simple key at the current flow level.
1136+ */
1137+
1138+static int
1139+yaml_parser_remove_simple_key(yaml_parser_t *parser)
1140+{
1141+ yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
1142+
1143+ if (simple_key->possible)
1144+ {
1145+ /* If the key is required, it is an error. */
1146+
1147+ if (simple_key->required) {
1148+ return yaml_parser_set_scanner_error(parser,
1149+ "while scanning a simple key", simple_key->mark,
1150+ "could not find expected ':'");
1151+ }
1152+ }
1153+
1154+ /* Remove the key from the stack. */
1155+
1156+ simple_key->possible = 0;
1157+
1158+ return 1;
1159+}
1160+
1161+/*
1162+ * Increase the flow level and resize the simple key list if needed.
1163+ */
1164+
1165+static int
1166+yaml_parser_increase_flow_level(yaml_parser_t *parser)
1167+{
1168+ yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } };
1169+
1170+ /* Reset the simple key on the next level. */
1171+
1172+ if (!PUSH(parser, parser->simple_keys, empty_simple_key))
1173+ return 0;
1174+
1175+ /* Increase the flow level. */
1176+
1177+ parser->flow_level++;
1178+
1179+ return 1;
1180+}
1181+
1182+/*
1183+ * Decrease the flow level.
1184+ */
1185+
1186+static int
1187+yaml_parser_decrease_flow_level(yaml_parser_t *parser)
1188+{
1189+ yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */
1190+
1191+ if (parser->flow_level) {
1192+ parser->flow_level --;
1193+ dummy_key = POP(parser, parser->simple_keys);
1194+ }
1195+
1196+ return 1;
1197+}
1198+
1199+/*
1200+ * Push the current indentation level to the stack and set the new level
1201+ * the current column is greater than the indentation level. In this case,
1202+ * append or insert the specified token into the token queue.
1203+ *
1204+ */
1205+
1206+static int
1207+yaml_parser_roll_indent(yaml_parser_t *parser, int column,
1208+ int number, yaml_token_type_t type, yaml_mark_t mark)
1209+{
1210+ yaml_token_t token;
1211+
1212+ /* In the flow context, do nothing. */
1213+
1214+ if (parser->flow_level)
1215+ return 1;
1216+
1217+ if (parser->indent < column)
1218+ {
1219+ /*
1220+ * Push the current indentation level to the stack and set the new
1221+ * indentation level.
1222+ */
1223+
1224+ if (!PUSH(parser, parser->indents, parser->indent))
1225+ return 0;
1226+
1227+ parser->indent = column;
1228+
1229+ /* Create a token and insert it into the queue. */
1230+
1231+ TOKEN_INIT(token, type, mark, mark);
1232+
1233+ if (number == -1) {
1234+ if (!ENQUEUE(parser, parser->tokens, token))
1235+ return 0;
1236+ }
1237+ else {
1238+ if (!QUEUE_INSERT(parser,
1239+ parser->tokens, number - parser->tokens_parsed, token))
1240+ return 0;
1241+ }
1242+ }
1243+
1244+ return 1;
1245+}
1246+
1247+/*
1248+ * Pop indentation levels from the indents stack until the current level
1249+ * becomes less or equal to the column. For each intendation level, append
1250+ * the BLOCK-END token.
1251+ */
1252+
1253+
1254+static int
1255+yaml_parser_unroll_indent(yaml_parser_t *parser, int column)
1256+{
1257+ yaml_token_t token;
1258+
1259+ /* In the flow context, do nothing. */
1260+
1261+ if (parser->flow_level)
1262+ return 1;
1263+
1264+ /* Loop through the intendation levels in the stack. */
1265+
1266+ while (parser->indent > column)
1267+ {
1268+ /* Create a token and append it to the queue. */
1269+
1270+ TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark);
1271+
1272+ if (!ENQUEUE(parser, parser->tokens, token))
1273+ return 0;
1274+
1275+ /* Pop the indentation level. */
1276+
1277+ parser->indent = POP(parser, parser->indents);
1278+ }
1279+
1280+ return 1;
1281+}
1282+
1283+/*
1284+ * Initialize the scanner and produce the STREAM-START token.
1285+ */
1286+
1287+static int
1288+yaml_parser_fetch_stream_start(yaml_parser_t *parser)
1289+{
1290+ yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } };
1291+ yaml_token_t token;
1292+
1293+ /* Set the initial indentation. */
1294+
1295+ parser->indent = -1;
1296+
1297+ /* Initialize the simple key stack. */
1298+
1299+ if (!PUSH(parser, parser->simple_keys, simple_key))
1300+ return 0;
1301+
1302+ /* A simple key is allowed at the beginning of the stream. */
1303+
1304+ parser->simple_key_allowed = 1;
1305+
1306+ /* We have started. */
1307+
1308+ parser->stream_start_produced = 1;
1309+
1310+ /* Create the STREAM-START token and append it to the queue. */
1311+
1312+ STREAM_START_TOKEN_INIT(token, parser->encoding,
1313+ parser->mark, parser->mark);
1314+
1315+ if (!ENQUEUE(parser, parser->tokens, token))
1316+ return 0;
1317+
1318+ return 1;
1319+}
1320+
1321+/*
1322+ * Produce the STREAM-END token and shut down the scanner.
1323+ */
1324+
1325+static int
1326+yaml_parser_fetch_stream_end(yaml_parser_t *parser)
1327+{
1328+ yaml_token_t token;
1329+
1330+ /* Force new line. */
1331+
1332+ if (parser->mark.column != 0) {
1333+ parser->mark.column = 0;
1334+ parser->mark.line ++;
1335+ }
1336+
1337+ /* Reset the indentation level. */
1338+
1339+ if (!yaml_parser_unroll_indent(parser, -1))
1340+ return 0;
1341+
1342+ /* Reset simple keys. */
1343+
1344+ if (!yaml_parser_remove_simple_key(parser))
1345+ return 0;
1346+
1347+ parser->simple_key_allowed = 0;
1348+
1349+ /* Create the STREAM-END token and append it to the queue. */
1350+
1351+ STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark);
1352+
1353+ if (!ENQUEUE(parser, parser->tokens, token))
1354+ return 0;
1355+
1356+ return 1;
1357+}
1358+
1359+/*
1360+ * Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
1361+ */
1362+
1363+static int
1364+yaml_parser_fetch_directive(yaml_parser_t *parser)
1365+{
1366+ yaml_token_t token;
1367+
1368+ /* Reset the indentation level. */
1369+
1370+ if (!yaml_parser_unroll_indent(parser, -1))
1371+ return 0;
1372+
1373+ /* Reset simple keys. */
1374+
1375+ if (!yaml_parser_remove_simple_key(parser))
1376+ return 0;
1377+
1378+ parser->simple_key_allowed = 0;
1379+
1380+ /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
1381+
1382+ if (!yaml_parser_scan_directive(parser, &token))
1383+ return 0;
1384+
1385+ /* Append the token to the queue. */
1386+
1387+ if (!ENQUEUE(parser, parser->tokens, token)) {
1388+ yaml_token_delete(&token);
1389+ return 0;
1390+ }
1391+
1392+ return 1;
1393+}
1394+
1395+/*
1396+ * Produce the DOCUMENT-START or DOCUMENT-END token.
1397+ */
1398+
1399+static int
1400+yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
1401+ yaml_token_type_t type)
1402+{
1403+ yaml_mark_t start_mark, end_mark;
1404+ yaml_token_t token;
1405+
1406+ /* Reset the indentation level. */
1407+
1408+ if (!yaml_parser_unroll_indent(parser, -1))
1409+ return 0;
1410+
1411+ /* Reset simple keys. */
1412+
1413+ if (!yaml_parser_remove_simple_key(parser))
1414+ return 0;
1415+
1416+ parser->simple_key_allowed = 0;
1417+
1418+ /* Consume the token. */
1419+
1420+ start_mark = parser->mark;
1421+
1422+ SKIP(parser);
1423+ SKIP(parser);
1424+ SKIP(parser);
1425+
1426+ end_mark = parser->mark;
1427+
1428+ /* Create the DOCUMENT-START or DOCUMENT-END token. */
1429+
1430+ TOKEN_INIT(token, type, start_mark, end_mark);
1431+
1432+ /* Append the token to the queue. */
1433+
1434+ if (!ENQUEUE(parser, parser->tokens, token))
1435+ return 0;
1436+
1437+ return 1;
1438+}
1439+
1440+/*
1441+ * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1442+ */
1443+
1444+static int
1445+yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
1446+ yaml_token_type_t type)
1447+{
1448+ yaml_mark_t start_mark, end_mark;
1449+ yaml_token_t token;
1450+
1451+ /* The indicators '[' and '{' may start a simple key. */
1452+
1453+ if (!yaml_parser_save_simple_key(parser))
1454+ return 0;
1455+
1456+ /* Increase the flow level. */
1457+
1458+ if (!yaml_parser_increase_flow_level(parser))
1459+ return 0;
1460+
1461+ /* A simple key may follow the indicators '[' and '{'. */
1462+
1463+ parser->simple_key_allowed = 1;
1464+
1465+ /* Consume the token. */
1466+
1467+ start_mark = parser->mark;
1468+ SKIP(parser);
1469+ end_mark = parser->mark;
1470+
1471+ /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
1472+
1473+ TOKEN_INIT(token, type, start_mark, end_mark);
1474+
1475+ /* Append the token to the queue. */
1476+
1477+ if (!ENQUEUE(parser, parser->tokens, token))
1478+ return 0;
1479+
1480+ return 1;
1481+}
1482+
1483+/*
1484+ * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1485+ */
1486+
1487+static int
1488+yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
1489+ yaml_token_type_t type)
1490+{
1491+ yaml_mark_t start_mark, end_mark;
1492+ yaml_token_t token;
1493+
1494+ /* Reset any potential simple key on the current flow level. */
1495+
1496+ if (!yaml_parser_remove_simple_key(parser))
1497+ return 0;
1498+
1499+ /* Decrease the flow level. */
1500+
1501+ if (!yaml_parser_decrease_flow_level(parser))
1502+ return 0;
1503+
1504+ /* No simple keys after the indicators ']' and '}'. */
1505+
1506+ parser->simple_key_allowed = 0;
1507+
1508+ /* Consume the token. */
1509+
1510+ start_mark = parser->mark;
1511+ SKIP(parser);
1512+ end_mark = parser->mark;
1513+
1514+ /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
1515+
1516+ TOKEN_INIT(token, type, start_mark, end_mark);
1517+
1518+ /* Append the token to the queue. */
1519+
1520+ if (!ENQUEUE(parser, parser->tokens, token))
1521+ return 0;
1522+
1523+ return 1;
1524+}
1525+
1526+/*
1527+ * Produce the FLOW-ENTRY token.
1528+ */
1529+
1530+static int
1531+yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
1532+{
1533+ yaml_mark_t start_mark, end_mark;
1534+ yaml_token_t token;
1535+
1536+ /* Reset any potential simple keys on the current flow level. */
1537+
1538+ if (!yaml_parser_remove_simple_key(parser))
1539+ return 0;
1540+
1541+ /* Simple keys are allowed after ','. */
1542+
1543+ parser->simple_key_allowed = 1;
1544+
1545+ /* Consume the token. */
1546+
1547+ start_mark = parser->mark;
1548+ SKIP(parser);
1549+ end_mark = parser->mark;
1550+
1551+ /* Create the FLOW-ENTRY token and append it to the queue. */
1552+
1553+ TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
1554+
1555+ if (!ENQUEUE(parser, parser->tokens, token))
1556+ return 0;
1557+
1558+ return 1;
1559+}
1560+
1561+/*
1562+ * Produce the BLOCK-ENTRY token.
1563+ */
1564+
1565+static int
1566+yaml_parser_fetch_block_entry(yaml_parser_t *parser)
1567+{
1568+ yaml_mark_t start_mark, end_mark;
1569+ yaml_token_t token;
1570+
1571+ /* Check if the scanner is in the block context. */
1572+
1573+ if (!parser->flow_level)
1574+ {
1575+ /* Check if we are allowed to start a new entry. */
1576+
1577+ if (!parser->simple_key_allowed) {
1578+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1579+ "block sequence entries are not allowed in this context");
1580+ }
1581+
1582+ /* Add the BLOCK-SEQUENCE-START token if needed. */
1583+
1584+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1585+ YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark))
1586+ return 0;
1587+ }
1588+ else
1589+ {
1590+ /*
1591+ * It is an error for the '-' indicator to occur in the flow context,
1592+ * but we let the Parser detect and report about it because the Parser
1593+ * is able to point to the context.
1594+ */
1595+ }
1596+
1597+ /* Reset any potential simple keys on the current flow level. */
1598+
1599+ if (!yaml_parser_remove_simple_key(parser))
1600+ return 0;
1601+
1602+ /* Simple keys are allowed after '-'. */
1603+
1604+ parser->simple_key_allowed = 1;
1605+
1606+ /* Consume the token. */
1607+
1608+ start_mark = parser->mark;
1609+ SKIP(parser);
1610+ end_mark = parser->mark;
1611+
1612+ /* Create the BLOCK-ENTRY token and append it to the queue. */
1613+
1614+ TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
1615+
1616+ if (!ENQUEUE(parser, parser->tokens, token))
1617+ return 0;
1618+
1619+ return 1;
1620+}
1621+
1622+/*
1623+ * Produce the KEY token.
1624+ */
1625+
1626+static int
1627+yaml_parser_fetch_key(yaml_parser_t *parser)
1628+{
1629+ yaml_mark_t start_mark, end_mark;
1630+ yaml_token_t token;
1631+
1632+ /* In the block context, additional checks are required. */
1633+
1634+ if (!parser->flow_level)
1635+ {
1636+ /* Check if we are allowed to start a new key (not nessesary simple). */
1637+
1638+ if (!parser->simple_key_allowed) {
1639+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1640+ "mapping keys are not allowed in this context");
1641+ }
1642+
1643+ /* Add the BLOCK-MAPPING-START token if needed. */
1644+
1645+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1646+ YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
1647+ return 0;
1648+ }
1649+
1650+ /* Reset any potential simple keys on the current flow level. */
1651+
1652+ if (!yaml_parser_remove_simple_key(parser))
1653+ return 0;
1654+
1655+ /* Simple keys are allowed after '?' in the block context. */
1656+
1657+ parser->simple_key_allowed = (!parser->flow_level);
1658+
1659+ /* Consume the token. */
1660+
1661+ start_mark = parser->mark;
1662+ SKIP(parser);
1663+ end_mark = parser->mark;
1664+
1665+ /* Create the KEY token and append it to the queue. */
1666+
1667+ TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark);
1668+
1669+ if (!ENQUEUE(parser, parser->tokens, token))
1670+ return 0;
1671+
1672+ return 1;
1673+}
1674+
1675+/*
1676+ * Produce the VALUE token.
1677+ */
1678+
1679+static int
1680+yaml_parser_fetch_value(yaml_parser_t *parser)
1681+{
1682+ yaml_mark_t start_mark, end_mark;
1683+ yaml_token_t token;
1684+ yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
1685+
1686+ /* Have we found a simple key? */
1687+
1688+ if (simple_key->possible)
1689+ {
1690+
1691+ /* Create the KEY token and insert it into the queue. */
1692+
1693+ TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
1694+
1695+ if (!QUEUE_INSERT(parser, parser->tokens,
1696+ simple_key->token_number - parser->tokens_parsed, token))
1697+ return 0;
1698+
1699+ /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
1700+
1701+ if (!yaml_parser_roll_indent(parser, simple_key->mark.column,
1702+ simple_key->token_number,
1703+ YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
1704+ return 0;
1705+
1706+ /* Remove the simple key. */
1707+
1708+ simple_key->possible = 0;
1709+
1710+ /* A simple key cannot follow another simple key. */
1711+
1712+ parser->simple_key_allowed = 0;
1713+ }
1714+ else
1715+ {
1716+ /* The ':' indicator follows a complex key. */
1717+
1718+ /* In the block context, extra checks are required. */
1719+
1720+ if (!parser->flow_level)
1721+ {
1722+ /* Check if we are allowed to start a complex value. */
1723+
1724+ if (!parser->simple_key_allowed) {
1725+ return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1726+ "mapping values are not allowed in this context");
1727+ }
1728+
1729+ /* Add the BLOCK-MAPPING-START token if needed. */
1730+
1731+ if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1732+ YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
1733+ return 0;
1734+ }
1735+
1736+ /* Simple keys after ':' are allowed in the block context. */
1737+
1738+ parser->simple_key_allowed = (!parser->flow_level);
1739+ }
1740+
1741+ /* Consume the token. */
1742+
1743+ start_mark = parser->mark;
1744+ SKIP(parser);
1745+ end_mark = parser->mark;
1746+
1747+ /* Create the VALUE token and append it to the queue. */
1748+
1749+ TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark);
1750+
1751+ if (!ENQUEUE(parser, parser->tokens, token))
1752+ return 0;
1753+
1754+ return 1;
1755+}
1756+
1757+/*
1758+ * Produce the ALIAS or ANCHOR token.
1759+ */
1760+
1761+static int
1762+yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
1763+{
1764+ yaml_token_t token;
1765+
1766+ /* An anchor or an alias could be a simple key. */
1767+
1768+ if (!yaml_parser_save_simple_key(parser))
1769+ return 0;
1770+
1771+ /* A simple key cannot follow an anchor or an alias. */
1772+
1773+ parser->simple_key_allowed = 0;
1774+
1775+ /* Create the ALIAS or ANCHOR token and append it to the queue. */
1776+
1777+ if (!yaml_parser_scan_anchor(parser, &token, type))
1778+ return 0;
1779+
1780+ if (!ENQUEUE(parser, parser->tokens, token)) {
1781+ yaml_token_delete(&token);
1782+ return 0;
1783+ }
1784+ return 1;
1785+}
1786+
1787+/*
1788+ * Produce the TAG token.
1789+ */
1790+
1791+static int
1792+yaml_parser_fetch_tag(yaml_parser_t *parser)
1793+{
1794+ yaml_token_t token;
1795+
1796+ /* A tag could be a simple key. */
1797+
1798+ if (!yaml_parser_save_simple_key(parser))
1799+ return 0;
1800+
1801+ /* A simple key cannot follow a tag. */
1802+
1803+ parser->simple_key_allowed = 0;
1804+
1805+ /* Create the TAG token and append it to the queue. */
1806+
1807+ if (!yaml_parser_scan_tag(parser, &token))
1808+ return 0;
1809+
1810+ if (!ENQUEUE(parser, parser->tokens, token)) {
1811+ yaml_token_delete(&token);
1812+ return 0;
1813+ }
1814+
1815+ return 1;
1816+}
1817+
1818+/*
1819+ * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
1820+ */
1821+
1822+static int
1823+yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
1824+{
1825+ yaml_token_t token;
1826+
1827+ /* Remove any potential simple keys. */
1828+
1829+ if (!yaml_parser_remove_simple_key(parser))
1830+ return 0;
1831+
1832+ /* A simple key may follow a block scalar. */
1833+
1834+ parser->simple_key_allowed = 1;
1835+
1836+ /* Create the SCALAR token and append it to the queue. */
1837+
1838+ if (!yaml_parser_scan_block_scalar(parser, &token, literal))
1839+ return 0;
1840+
1841+ if (!ENQUEUE(parser, parser->tokens, token)) {
1842+ yaml_token_delete(&token);
1843+ return 0;
1844+ }
1845+
1846+ return 1;
1847+}
1848+
1849+/*
1850+ * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
1851+ */
1852+
1853+static int
1854+yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
1855+{
1856+ yaml_token_t token;
1857+
1858+ /* A plain scalar could be a simple key. */
1859+
1860+ if (!yaml_parser_save_simple_key(parser))
1861+ return 0;
1862+
1863+ /* A simple key cannot follow a flow scalar. */
1864+
1865+ parser->simple_key_allowed = 0;
1866+
1867+ /* Create the SCALAR token and append it to the queue. */
1868+
1869+ if (!yaml_parser_scan_flow_scalar(parser, &token, single))
1870+ return 0;
1871+
1872+ if (!ENQUEUE(parser, parser->tokens, token)) {
1873+ yaml_token_delete(&token);
1874+ return 0;
1875+ }
1876+
1877+ return 1;
1878+}
1879+
1880+/*
1881+ * Produce the SCALAR(...,plain) token.
1882+ */
1883+
1884+static int
1885+yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
1886+{
1887+ yaml_token_t token;
1888+
1889+ /* A plain scalar could be a simple key. */
1890+
1891+ if (!yaml_parser_save_simple_key(parser))
1892+ return 0;
1893+
1894+ /* A simple key cannot follow a flow scalar. */
1895+
1896+ parser->simple_key_allowed = 0;
1897+
1898+ /* Create the SCALAR token and append it to the queue. */
1899+
1900+ if (!yaml_parser_scan_plain_scalar(parser, &token))
1901+ return 0;
1902+
1903+ if (!ENQUEUE(parser, parser->tokens, token)) {
1904+ yaml_token_delete(&token);
1905+ return 0;
1906+ }
1907+
1908+ return 1;
1909+}
1910+
1911+/*
1912+ * Eat whitespaces and comments until the next token is found.
1913+ */
1914+
1915+static int
1916+yaml_parser_scan_to_next_token(yaml_parser_t *parser)
1917+{
1918+ /* Until the next token is not found. */
1919+
1920+ while (1)
1921+ {
1922+ /* Allow the BOM mark to start a line. */
1923+
1924+ if (!CACHE(parser, 1)) return 0;
1925+
1926+ if (parser->mark.column == 0 && IS_BOM(parser->buffer))
1927+ SKIP(parser);
1928+
1929+ /*
1930+ * Eat whitespaces.
1931+ *
1932+ * Tabs are allowed:
1933+ *
1934+ * - in the flow context;
1935+ * - in the block context, but not at the beginning of the line or
1936+ * after '-', '?', or ':' (complex value).
1937+ */
1938+
1939+ if (!CACHE(parser, 1)) return 0;
1940+
1941+ while (CHECK(parser->buffer,' ') ||
1942+ ((parser->flow_level || !parser->simple_key_allowed) &&
1943+ CHECK(parser->buffer, '\t'))) {
1944+ SKIP(parser);
1945+ if (!CACHE(parser, 1)) return 0;
1946+ }
1947+
1948+ /* Eat a comment until a line break. */
1949+
1950+ if (CHECK(parser->buffer, '#')) {
1951+ while (!IS_BREAKZ(parser->buffer)) {
1952+ SKIP(parser);
1953+ if (!CACHE(parser, 1)) return 0;
1954+ }
1955+ }
1956+
1957+ /* If it is a line break, eat it. */
1958+
1959+ if (IS_BREAK(parser->buffer))
1960+ {
1961+ if (!CACHE(parser, 2)) return 0;
1962+ SKIP_LINE(parser);
1963+
1964+ /* In the block context, a new line may start a simple key. */
1965+
1966+ if (!parser->flow_level) {
1967+ parser->simple_key_allowed = 1;
1968+ }
1969+ }
1970+ else
1971+ {
1972+ /* We have found a token. */
1973+
1974+ break;
1975+ }
1976+ }
1977+
1978+ return 1;
1979+}
1980+
1981+/*
1982+ * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
1983+ *
1984+ * Scope:
1985+ * %YAML 1.1 # a comment \n
1986+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1987+ * %TAG !yaml! tag:yaml.org,2002: \n
1988+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1989+ */
1990+
1991+int
1992+yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token)
1993+{
1994+ yaml_mark_t start_mark, end_mark;
1995+ yaml_char_t *name = NULL;
1996+ int major, minor;
1997+ yaml_char_t *handle = NULL, *prefix = NULL;
1998+
1999+ /* Eat '%'. */
2000+
2001+ start_mark = parser->mark;
2002+
2003+ SKIP(parser);
2004+
2005+ /* Scan the directive name. */
2006+
2007+ if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
2008+ goto error;
2009+
2010+ /* Is it a YAML directive? */
2011+
2012+ if (strcmp((char *)name, "YAML") == 0)
2013+ {
2014+ /* Scan the VERSION directive value. */
2015+
2016+ if (!yaml_parser_scan_version_directive_value(parser, start_mark,
2017+ &major, &minor))
2018+ goto error;
2019+
2020+ end_mark = parser->mark;
2021+
2022+ /* Create a VERSION-DIRECTIVE token. */
2023+
2024+ VERSION_DIRECTIVE_TOKEN_INIT(*token, major, minor,
2025+ start_mark, end_mark);
2026+ }
2027+
2028+ /* Is it a TAG directive? */
2029+
2030+ else if (strcmp((char *)name, "TAG") == 0)
2031+ {
2032+ /* Scan the TAG directive value. */
2033+
2034+ if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
2035+ &handle, &prefix))
2036+ goto error;
2037+
2038+ end_mark = parser->mark;
2039+
2040+ /* Create a TAG-DIRECTIVE token. */
2041+
2042+ TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix,
2043+ start_mark, end_mark);
2044+ }
2045+
2046+ /* Unknown directive. */
2047+
2048+ else
2049+ {
2050+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
2051+ start_mark, "found uknown directive name");
2052+ goto error;
2053+ }
2054+
2055+ /* Eat the rest of the line including any comments. */
2056+
2057+ if (!CACHE(parser, 1)) goto error;
2058+
2059+ while (IS_BLANK(parser->buffer)) {
2060+ SKIP(parser);
2061+ if (!CACHE(parser, 1)) goto error;
2062+ }
2063+
2064+ if (CHECK(parser->buffer, '#')) {
2065+ while (!IS_BREAKZ(parser->buffer)) {
2066+ SKIP(parser);
2067+ if (!CACHE(parser, 1)) goto error;
2068+ }
2069+ }
2070+
2071+ /* Check if we are at the end of the line. */
2072+
2073+ if (!IS_BREAKZ(parser->buffer)) {
2074+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
2075+ start_mark, "did not find expected comment or line break");
2076+ goto error;
2077+ }
2078+
2079+ /* Eat a line break. */
2080+
2081+ if (IS_BREAK(parser->buffer)) {
2082+ if (!CACHE(parser, 2)) goto error;
2083+ SKIP_LINE(parser);
2084+ }
2085+
2086+ yaml_free(name);
2087+
2088+ return 1;
2089+
2090+error:
2091+ yaml_free(prefix);
2092+ yaml_free(handle);
2093+ yaml_free(name);
2094+ return 0;
2095+}
2096+
2097+/*
2098+ * Scan the directive name.
2099+ *
2100+ * Scope:
2101+ * %YAML 1.1 # a comment \n
2102+ * ^^^^
2103+ * %TAG !yaml! tag:yaml.org,2002: \n
2104+ * ^^^
2105+ */
2106+
2107+static int
2108+yaml_parser_scan_directive_name(yaml_parser_t *parser,
2109+ yaml_mark_t start_mark, yaml_char_t **name)
2110+{
2111+ yaml_string_t string = NULL_STRING;
2112+
2113+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2114+
2115+ /* Consume the directive name. */
2116+
2117+ if (!CACHE(parser, 1)) goto error;
2118+
2119+ while (IS_ALPHA(parser->buffer))
2120+ {
2121+ if (!READ(parser, string)) goto error;
2122+ if (!CACHE(parser, 1)) goto error;
2123+ }
2124+
2125+ /* Check if the name is empty. */
2126+
2127+ if (string.start == string.pointer) {
2128+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
2129+ start_mark, "could not find expected directive name");
2130+ goto error;
2131+ }
2132+
2133+ /* Check for an blank character after the name. */
2134+
2135+ if (!IS_BLANKZ(parser->buffer)) {
2136+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
2137+ start_mark, "found unexpected non-alphabetical character");
2138+ goto error;
2139+ }
2140+
2141+ *name = string.start;
2142+
2143+ return 1;
2144+
2145+error:
2146+ STRING_DEL(parser, string);
2147+ return 0;
2148+}
2149+
2150+/*
2151+ * Scan the value of VERSION-DIRECTIVE.
2152+ *
2153+ * Scope:
2154+ * %YAML 1.1 # a comment \n
2155+ * ^^^^^^
2156+ */
2157+
2158+static int
2159+yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
2160+ yaml_mark_t start_mark, int *major, int *minor)
2161+{
2162+ /* Eat whitespaces. */
2163+
2164+ if (!CACHE(parser, 1)) return 0;
2165+
2166+ while (IS_BLANK(parser->buffer)) {
2167+ SKIP(parser);
2168+ if (!CACHE(parser, 1)) return 0;
2169+ }
2170+
2171+ /* Consume the major version number. */
2172+
2173+ if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
2174+ return 0;
2175+
2176+ /* Eat '.'. */
2177+
2178+ if (!CHECK(parser->buffer, '.')) {
2179+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2180+ start_mark, "did not find expected digit or '.' character");
2181+ }
2182+
2183+ SKIP(parser);
2184+
2185+ /* Consume the minor version number. */
2186+
2187+ if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
2188+ return 0;
2189+
2190+ return 1;
2191+}
2192+
2193+#define MAX_NUMBER_LENGTH 9
2194+
2195+/*
2196+ * Scan the version number of VERSION-DIRECTIVE.
2197+ *
2198+ * Scope:
2199+ * %YAML 1.1 # a comment \n
2200+ * ^
2201+ * %YAML 1.1 # a comment \n
2202+ * ^
2203+ */
2204+
2205+static int
2206+yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
2207+ yaml_mark_t start_mark, int *number)
2208+{
2209+ int value = 0;
2210+ size_t length = 0;
2211+
2212+ /* Repeat while the next character is digit. */
2213+
2214+ if (!CACHE(parser, 1)) return 0;
2215+
2216+ while (IS_DIGIT(parser->buffer))
2217+ {
2218+ /* Check if the number is too long. */
2219+
2220+ if (++length > MAX_NUMBER_LENGTH) {
2221+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2222+ start_mark, "found extremely long version number");
2223+ }
2224+
2225+ value = value*10 + AS_DIGIT(parser->buffer);
2226+
2227+ SKIP(parser);
2228+
2229+ if (!CACHE(parser, 1)) return 0;
2230+ }
2231+
2232+ /* Check if the number was present. */
2233+
2234+ if (!length) {
2235+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2236+ start_mark, "did not find expected version number");
2237+ }
2238+
2239+ *number = value;
2240+
2241+ return 1;
2242+}
2243+
2244+/*
2245+ * Scan the value of a TAG-DIRECTIVE token.
2246+ *
2247+ * Scope:
2248+ * %TAG !yaml! tag:yaml.org,2002: \n
2249+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2250+ */
2251+
2252+static int
2253+yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
2254+ yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
2255+{
2256+ yaml_char_t *handle_value = NULL;
2257+ yaml_char_t *prefix_value = NULL;
2258+
2259+ /* Eat whitespaces. */
2260+
2261+ if (!CACHE(parser, 1)) goto error;
2262+
2263+ while (IS_BLANK(parser->buffer)) {
2264+ SKIP(parser);
2265+ if (!CACHE(parser, 1)) goto error;
2266+ }
2267+
2268+ /* Scan a handle. */
2269+
2270+ if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
2271+ goto error;
2272+
2273+ /* Expect a whitespace. */
2274+
2275+ if (!CACHE(parser, 1)) goto error;
2276+
2277+ if (!IS_BLANK(parser->buffer)) {
2278+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2279+ start_mark, "did not find expected whitespace");
2280+ goto error;
2281+ }
2282+
2283+ /* Eat whitespaces. */
2284+
2285+ while (IS_BLANK(parser->buffer)) {
2286+ SKIP(parser);
2287+ if (!CACHE(parser, 1)) goto error;
2288+ }
2289+
2290+ /* Scan a prefix. */
2291+
2292+ if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
2293+ goto error;
2294+
2295+ /* Expect a whitespace or line break. */
2296+
2297+ if (!CACHE(parser, 1)) goto error;
2298+
2299+ if (!IS_BLANKZ(parser->buffer)) {
2300+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2301+ start_mark, "did not find expected whitespace or line break");
2302+ goto error;
2303+ }
2304+
2305+ *handle = handle_value;
2306+ *prefix = prefix_value;
2307+
2308+ return 1;
2309+
2310+error:
2311+ yaml_free(handle_value);
2312+ yaml_free(prefix_value);
2313+ return 0;
2314+}
2315+
2316+static int
2317+yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
2318+ yaml_token_type_t type)
2319+{
2320+ int length = 0;
2321+ yaml_mark_t start_mark, end_mark;
2322+ yaml_string_t string = NULL_STRING;
2323+
2324+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2325+
2326+ /* Eat the indicator character. */
2327+
2328+ start_mark = parser->mark;
2329+
2330+ SKIP(parser);
2331+
2332+ /* Consume the value. */
2333+
2334+ if (!CACHE(parser, 1)) goto error;
2335+
2336+ while (IS_ALPHA(parser->buffer)) {
2337+ if (!READ(parser, string)) goto error;
2338+ if (!CACHE(parser, 1)) goto error;
2339+ length ++;
2340+ }
2341+
2342+ end_mark = parser->mark;
2343+
2344+ /*
2345+ * Check if length of the anchor is greater than 0 and it is followed by
2346+ * a whitespace character or one of the indicators:
2347+ *
2348+ * '?', ':', ',', ']', '}', '%', '@', '`'.
2349+ */
2350+
2351+ if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?')
2352+ || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',')
2353+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}')
2354+ || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@')
2355+ || CHECK(parser->buffer, '`'))) {
2356+ yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
2357+ "while scanning an anchor" : "while scanning an alias", start_mark,
2358+ "did not find expected alphabetic or numeric character");
2359+ goto error;
2360+ }
2361+
2362+ /* Create a token. */
2363+
2364+ if (type == YAML_ANCHOR_TOKEN) {
2365+ ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark);
2366+ }
2367+ else {
2368+ ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark);
2369+ }
2370+
2371+ return 1;
2372+
2373+error:
2374+ STRING_DEL(parser, string);
2375+ return 0;
2376+}
2377+
2378+/*
2379+ * Scan a TAG token.
2380+ */
2381+
2382+static int
2383+yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
2384+{
2385+ yaml_char_t *handle = NULL;
2386+ yaml_char_t *suffix = NULL;
2387+ yaml_mark_t start_mark, end_mark;
2388+
2389+ start_mark = parser->mark;
2390+
2391+ /* Check if the tag is in the canonical form. */
2392+
2393+ if (!CACHE(parser, 2)) goto error;
2394+
2395+ if (CHECK_AT(parser->buffer, '<', 1))
2396+ {
2397+ /* Set the handle to '' */
2398+
2399+ handle = yaml_malloc(1);
2400+ if (!handle) goto error;
2401+ handle[0] = '\0';
2402+
2403+ /* Eat '!<' */
2404+
2405+ SKIP(parser);
2406+ SKIP(parser);
2407+
2408+ /* Consume the tag value. */
2409+
2410+ if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2411+ goto error;
2412+
2413+ /* Check for '>' and eat it. */
2414+
2415+ if (!CHECK(parser->buffer, '>')) {
2416+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
2417+ start_mark, "did not find the expected '>'");
2418+ goto error;
2419+ }
2420+
2421+ SKIP(parser);
2422+ }
2423+ else
2424+ {
2425+ /* The tag has either the '!suffix' or the '!handle!suffix' form. */
2426+
2427+ /* First, try to scan a handle. */
2428+
2429+ if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
2430+ goto error;
2431+
2432+ /* Check if it is, indeed, handle. */
2433+
2434+ if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
2435+ {
2436+ /* Scan the suffix now. */
2437+
2438+ if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2439+ goto error;
2440+ }
2441+ else
2442+ {
2443+ /* It wasn't a handle after all. Scan the rest of the tag. */
2444+
2445+ if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
2446+ goto error;
2447+
2448+ /* Set the handle to '!'. */
2449+
2450+ yaml_free(handle);
2451+ handle = yaml_malloc(2);
2452+ if (!handle) goto error;
2453+ handle[0] = '!';
2454+ handle[1] = '\0';
2455+
2456+ /*
2457+ * A special case: the '!' tag. Set the handle to '' and the
2458+ * suffix to '!'.
2459+ */
2460+
2461+ if (suffix[0] == '\0') {
2462+ yaml_char_t *tmp = handle;
2463+ handle = suffix;
2464+ suffix = tmp;
2465+ }
2466+ }
2467+ }
2468+
2469+ /* Check the character which ends the tag. */
2470+
2471+ if (!CACHE(parser, 1)) goto error;
2472+
2473+ if (!IS_BLANKZ(parser->buffer)) {
2474+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
2475+ start_mark, "did not find expected whitespace or line break");
2476+ goto error;
2477+ }
2478+
2479+ end_mark = parser->mark;
2480+
2481+ /* Create a token. */
2482+
2483+ TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark);
2484+
2485+ return 1;
2486+
2487+error:
2488+ yaml_free(handle);
2489+ yaml_free(suffix);
2490+ return 0;
2491+}
2492+
2493+/*
2494+ * Scan a tag handle.
2495+ */
2496+
2497+static int
2498+yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
2499+ yaml_mark_t start_mark, yaml_char_t **handle)
2500+{
2501+ yaml_string_t string = NULL_STRING;
2502+
2503+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2504+
2505+ /* Check the initial '!' character. */
2506+
2507+ if (!CACHE(parser, 1)) goto error;
2508+
2509+ if (!CHECK(parser->buffer, '!')) {
2510+ yaml_parser_set_scanner_error(parser, directive ?
2511+ "while scanning a tag directive" : "while scanning a tag",
2512+ start_mark, "did not find expected '!'");
2513+ goto error;
2514+ }
2515+
2516+ /* Copy the '!' character. */
2517+
2518+ if (!READ(parser, string)) goto error;
2519+
2520+ /* Copy all subsequent alphabetical and numerical characters. */
2521+
2522+ if (!CACHE(parser, 1)) goto error;
2523+
2524+ while (IS_ALPHA(parser->buffer))
2525+ {
2526+ if (!READ(parser, string)) goto error;
2527+ if (!CACHE(parser, 1)) goto error;
2528+ }
2529+
2530+ /* Check if the trailing character is '!' and copy it. */
2531+
2532+ if (CHECK(parser->buffer, '!'))
2533+ {
2534+ if (!READ(parser, string)) goto error;
2535+ }
2536+ else
2537+ {
2538+ /*
2539+ * It's either the '!' tag or not really a tag handle. If it's a %TAG
2540+ * directive, it's an error. If it's a tag token, it must be a part of
2541+ * URI.
2542+ */
2543+
2544+ if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) {
2545+ yaml_parser_set_scanner_error(parser, "while parsing a tag directive",
2546+ start_mark, "did not find expected '!'");
2547+ goto error;
2548+ }
2549+ }
2550+
2551+ *handle = string.start;
2552+
2553+ return 1;
2554+
2555+error:
2556+ STRING_DEL(parser, string);
2557+ return 0;
2558+}
2559+
2560+/*
2561+ * Scan a tag.
2562+ */
2563+
2564+static int
2565+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
2566+ yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
2567+{
2568+ size_t length = head ? strlen((char *)head) : 0;
2569+ yaml_string_t string = NULL_STRING;
2570+
2571+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2572+
2573+ /* Resize the string to include the head. */
2574+
2575+ while (string.end - string.start <= (int)length) {
2576+ if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) {
2577+ parser->error = YAML_MEMORY_ERROR;
2578+ goto error;
2579+ }
2580+ }
2581+
2582+ /*
2583+ * Copy the head if needed.
2584+ *
2585+ * Note that we don't copy the leading '!' character.
2586+ */
2587+
2588+ if (length > 1) {
2589+ memcpy(string.start, head+1, length-1);
2590+ string.pointer += length-1;
2591+ }
2592+
2593+ /* Scan the tag. */
2594+
2595+ if (!CACHE(parser, 1)) goto error;
2596+
2597+ /*
2598+ * The set of characters that may appear in URI is as follows:
2599+ *
2600+ * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
2601+ * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
2602+ * '%'.
2603+ */
2604+
2605+ while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';')
2606+ || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?')
2607+ || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@')
2608+ || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=')
2609+ || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$')
2610+ || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.')
2611+ || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~')
2612+ || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'')
2613+ || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')')
2614+ || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']')
2615+ || CHECK(parser->buffer, '%'))
2616+ {
2617+ /* Check if it is a URI-escape sequence. */
2618+
2619+ if (CHECK(parser->buffer, '%')) {
2620+ if (!yaml_parser_scan_uri_escapes(parser,
2621+ directive, start_mark, &string)) goto error;
2622+ }
2623+ else {
2624+ if (!READ(parser, string)) goto error;
2625+ }
2626+
2627+ length ++;
2628+ if (!CACHE(parser, 1)) goto error;
2629+ }
2630+
2631+ /* Check if the tag is non-empty. */
2632+
2633+ if (!length) {
2634+ if (!STRING_EXTEND(parser, string))
2635+ goto error;
2636+
2637+ yaml_parser_set_scanner_error(parser, directive ?
2638+ "while parsing a %TAG directive" : "while parsing a tag",
2639+ start_mark, "did not find expected tag URI");
2640+ goto error;
2641+ }
2642+
2643+ *uri = string.start;
2644+
2645+ return 1;
2646+
2647+error:
2648+ STRING_DEL(parser, string);
2649+ return 0;
2650+}
2651+
2652+/*
2653+ * Decode an URI-escape sequence corresponding to a single UTF-8 character.
2654+ */
2655+
2656+static int
2657+yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
2658+ yaml_mark_t start_mark, yaml_string_t *string)
2659+{
2660+ int width = 0;
2661+
2662+ /* Decode the required number of characters. */
2663+
2664+ do {
2665+
2666+ unsigned char octet = 0;
2667+
2668+ /* Check for a URI-escaped octet. */
2669+
2670+ if (!CACHE(parser, 3)) return 0;
2671+
2672+ if (!(CHECK(parser->buffer, '%')
2673+ && IS_HEX_AT(parser->buffer, 1)
2674+ && IS_HEX_AT(parser->buffer, 2))) {
2675+ return yaml_parser_set_scanner_error(parser, directive ?
2676+ "while parsing a %TAG directive" : "while parsing a tag",
2677+ start_mark, "did not find URI escaped octet");
2678+ }
2679+
2680+ /* Get the octet. */
2681+
2682+ octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2);
2683+
2684+ /* If it is the leading octet, determine the length of the UTF-8 sequence. */
2685+
2686+ if (!width)
2687+ {
2688+ width = (octet & 0x80) == 0x00 ? 1 :
2689+ (octet & 0xE0) == 0xC0 ? 2 :
2690+ (octet & 0xF0) == 0xE0 ? 3 :
2691+ (octet & 0xF8) == 0xF0 ? 4 : 0;
2692+ if (!width) {
2693+ return yaml_parser_set_scanner_error(parser, directive ?
2694+ "while parsing a %TAG directive" : "while parsing a tag",
2695+ start_mark, "found an incorrect leading UTF-8 octet");
2696+ }
2697+ }
2698+ else
2699+ {
2700+ /* Check if the trailing octet is correct. */
2701+
2702+ if ((octet & 0xC0) != 0x80) {
2703+ return yaml_parser_set_scanner_error(parser, directive ?
2704+ "while parsing a %TAG directive" : "while parsing a tag",
2705+ start_mark, "found an incorrect trailing UTF-8 octet");
2706+ }
2707+ }
2708+
2709+ /* Copy the octet and move the pointers. */
2710+
2711+ *(string->pointer++) = octet;
2712+ SKIP(parser);
2713+ SKIP(parser);
2714+ SKIP(parser);
2715+
2716+ } while (--width);
2717+
2718+ return 1;
2719+}
2720+
2721+/*
2722+ * Scan a block scalar.
2723+ */
2724+
2725+static int
2726+yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
2727+ int literal)
2728+{
2729+ yaml_mark_t start_mark;
2730+ yaml_mark_t end_mark;
2731+ yaml_string_t string = NULL_STRING;
2732+ yaml_string_t leading_break = NULL_STRING;
2733+ yaml_string_t trailing_breaks = NULL_STRING;
2734+ int chomping = 0;
2735+ int increment = 0;
2736+ int indent = 0;
2737+ int leading_blank = 0;
2738+ int trailing_blank = 0;
2739+
2740+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2741+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
2742+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
2743+
2744+ /* Eat the indicator '|' or '>'. */
2745+
2746+ start_mark = parser->mark;
2747+
2748+ SKIP(parser);
2749+
2750+ /* Scan the additional block scalar indicators. */
2751+
2752+ if (!CACHE(parser, 1)) goto error;
2753+
2754+ /* Check for a chomping indicator. */
2755+
2756+ if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-'))
2757+ {
2758+ /* Set the chomping method and eat the indicator. */
2759+
2760+ chomping = CHECK(parser->buffer, '+') ? +1 : -1;
2761+
2762+ SKIP(parser);
2763+
2764+ /* Check for an indentation indicator. */
2765+
2766+ if (!CACHE(parser, 1)) goto error;
2767+
2768+ if (IS_DIGIT(parser->buffer))
2769+ {
2770+ /* Check that the intendation is greater than 0. */
2771+
2772+ if (CHECK(parser->buffer, '0')) {
2773+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2774+ start_mark, "found an intendation indicator equal to 0");
2775+ goto error;
2776+ }
2777+
2778+ /* Get the intendation level and eat the indicator. */
2779+
2780+ increment = AS_DIGIT(parser->buffer);
2781+
2782+ SKIP(parser);
2783+ }
2784+ }
2785+
2786+ /* Do the same as above, but in the opposite order. */
2787+
2788+ else if (IS_DIGIT(parser->buffer))
2789+ {
2790+ if (CHECK(parser->buffer, '0')) {
2791+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2792+ start_mark, "found an intendation indicator equal to 0");
2793+ goto error;
2794+ }
2795+
2796+ increment = AS_DIGIT(parser->buffer);
2797+
2798+ SKIP(parser);
2799+
2800+ if (!CACHE(parser, 1)) goto error;
2801+
2802+ if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) {
2803+ chomping = CHECK(parser->buffer, '+') ? +1 : -1;
2804+
2805+ SKIP(parser);
2806+ }
2807+ }
2808+
2809+ /* Eat whitespaces and comments to the end of the line. */
2810+
2811+ if (!CACHE(parser, 1)) goto error;
2812+
2813+ while (IS_BLANK(parser->buffer)) {
2814+ SKIP(parser);
2815+ if (!CACHE(parser, 1)) goto error;
2816+ }
2817+
2818+ if (CHECK(parser->buffer, '#')) {
2819+ while (!IS_BREAKZ(parser->buffer)) {
2820+ SKIP(parser);
2821+ if (!CACHE(parser, 1)) goto error;
2822+ }
2823+ }
2824+
2825+ /* Check if we are at the end of the line. */
2826+
2827+ if (!IS_BREAKZ(parser->buffer)) {
2828+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2829+ start_mark, "did not find expected comment or line break");
2830+ goto error;
2831+ }
2832+
2833+ /* Eat a line break. */
2834+
2835+ if (IS_BREAK(parser->buffer)) {
2836+ if (!CACHE(parser, 2)) goto error;
2837+ SKIP_LINE(parser);
2838+ }
2839+
2840+ end_mark = parser->mark;
2841+
2842+ /* Set the intendation level if it was specified. */
2843+
2844+ if (increment) {
2845+ indent = parser->indent >= 0 ? parser->indent+increment : increment;
2846+ }
2847+
2848+ /* Scan the leading line breaks and determine the indentation level if needed. */
2849+
2850+ if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks,
2851+ start_mark, &end_mark)) goto error;
2852+
2853+ /* Scan the block scalar content. */
2854+
2855+ if (!CACHE(parser, 1)) goto error;
2856+
2857+ while ((int)parser->mark.column == indent && !IS_Z(parser->buffer))
2858+ {
2859+ /*
2860+ * We are at the beginning of a non-empty line.
2861+ */
2862+
2863+ /* Is it a trailing whitespace? */
2864+
2865+ trailing_blank = IS_BLANK(parser->buffer);
2866+
2867+ /* Check if we need to fold the leading line break. */
2868+
2869+ if (!literal && (*leading_break.start == '\n')
2870+ && !leading_blank && !trailing_blank)
2871+ {
2872+ /* Do we need to join the lines by space? */
2873+
2874+ if (*trailing_breaks.start == '\0') {
2875+ if (!STRING_EXTEND(parser, string)) goto error;
2876+ *(string.pointer ++) = ' ';
2877+ }
2878+
2879+ CLEAR(parser, leading_break);
2880+ }
2881+ else {
2882+ if (!JOIN(parser, string, leading_break)) goto error;
2883+ CLEAR(parser, leading_break);
2884+ }
2885+
2886+ /* Append the remaining line breaks. */
2887+
2888+ if (!JOIN(parser, string, trailing_breaks)) goto error;
2889+ CLEAR(parser, trailing_breaks);
2890+
2891+ /* Is it a leading whitespace? */
2892+
2893+ leading_blank = IS_BLANK(parser->buffer);
2894+
2895+ /* Consume the current line. */
2896+
2897+ while (!IS_BREAKZ(parser->buffer)) {
2898+ if (!READ(parser, string)) goto error;
2899+ if (!CACHE(parser, 1)) goto error;
2900+ }
2901+
2902+ /* Consume the line break. */
2903+
2904+ if (!CACHE(parser, 2)) goto error;
2905+
2906+ if (!READ_LINE(parser, leading_break)) goto error;
2907+
2908+ /* Eat the following intendation spaces and line breaks. */
2909+
2910+ if (!yaml_parser_scan_block_scalar_breaks(parser,
2911+ &indent, &trailing_breaks, start_mark, &end_mark)) goto error;
2912+ }
2913+
2914+ /* Chomp the tail. */
2915+
2916+ if (chomping != -1) {
2917+ if (!JOIN(parser, string, leading_break)) goto error;
2918+ }
2919+ if (chomping == 1) {
2920+ if (!JOIN(parser, string, trailing_breaks)) goto error;
2921+ }
2922+
2923+ /* Create a token. */
2924+
2925+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
2926+ literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE,
2927+ start_mark, end_mark);
2928+
2929+ STRING_DEL(parser, leading_break);
2930+ STRING_DEL(parser, trailing_breaks);
2931+
2932+ return 1;
2933+
2934+error:
2935+ STRING_DEL(parser, string);
2936+ STRING_DEL(parser, leading_break);
2937+ STRING_DEL(parser, trailing_breaks);
2938+
2939+ return 0;
2940+}
2941+
2942+/*
2943+ * Scan intendation spaces and line breaks for a block scalar. Determine the
2944+ * intendation level if needed.
2945+ */
2946+
2947+static int
2948+yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
2949+ int *indent, yaml_string_t *breaks,
2950+ yaml_mark_t start_mark, yaml_mark_t *end_mark)
2951+{
2952+ int max_indent = 0;
2953+
2954+ *end_mark = parser->mark;
2955+
2956+ /* Eat the intendation spaces and line breaks. */
2957+
2958+ while (1)
2959+ {
2960+ /* Eat the intendation spaces. */
2961+
2962+ if (!CACHE(parser, 1)) return 0;
2963+
2964+ while ((!*indent || (int)parser->mark.column < *indent)
2965+ && IS_SPACE(parser->buffer)) {
2966+ SKIP(parser);
2967+ if (!CACHE(parser, 1)) return 0;
2968+ }
2969+
2970+ if ((int)parser->mark.column > max_indent)
2971+ max_indent = (int)parser->mark.column;
2972+
2973+ /* Check for a tab character messing the intendation. */
2974+
2975+ if ((!*indent || (int)parser->mark.column < *indent)
2976+ && IS_TAB(parser->buffer)) {
2977+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2978+ start_mark, "found a tab character where an intendation space is expected");
2979+ }
2980+
2981+ /* Have we found a non-empty line? */
2982+
2983+ if (!IS_BREAK(parser->buffer)) break;
2984+
2985+ /* Consume the line break. */
2986+
2987+ if (!CACHE(parser, 2)) return 0;
2988+ if (!READ_LINE(parser, *breaks)) return 0;
2989+ *end_mark = parser->mark;
2990+ }
2991+
2992+ /* Determine the indentation level if needed. */
2993+
2994+ if (!*indent) {
2995+ *indent = max_indent;
2996+ if (*indent < parser->indent + 1)
2997+ *indent = parser->indent + 1;
2998+ if (*indent < 1)
2999+ *indent = 1;
3000+ }
3001+
3002+ return 1;
3003+}
3004+
3005+/*
3006+ * Scan a quoted scalar.
3007+ */
3008+
3009+static int
3010+yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
3011+ int single)
3012+{
3013+ yaml_mark_t start_mark;
3014+ yaml_mark_t end_mark;
3015+ yaml_string_t string = NULL_STRING;
3016+ yaml_string_t leading_break = NULL_STRING;
3017+ yaml_string_t trailing_breaks = NULL_STRING;
3018+ yaml_string_t whitespaces = NULL_STRING;
3019+ int leading_blanks;
3020+
3021+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
3022+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
3023+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
3024+ if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
3025+
3026+ /* Eat the left quote. */
3027+
3028+ start_mark = parser->mark;
3029+
3030+ SKIP(parser);
3031+
3032+ /* Consume the content of the quoted scalar. */
3033+
3034+ while (1)
3035+ {
3036+ /* Check that there are no document indicators at the beginning of the line. */
3037+
3038+ if (!CACHE(parser, 4)) goto error;
3039+
3040+ if (parser->mark.column == 0 &&
3041+ ((CHECK_AT(parser->buffer, '-', 0) &&
3042+ CHECK_AT(parser->buffer, '-', 1) &&
3043+ CHECK_AT(parser->buffer, '-', 2)) ||
3044+ (CHECK_AT(parser->buffer, '.', 0) &&
3045+ CHECK_AT(parser->buffer, '.', 1) &&
3046+ CHECK_AT(parser->buffer, '.', 2))) &&
3047+ IS_BLANKZ_AT(parser->buffer, 3))
3048+ {
3049+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3050+ start_mark, "found unexpected document indicator");
3051+ goto error;
3052+ }
3053+
3054+ /* Check for EOF. */
3055+
3056+ if (IS_Z(parser->buffer)) {
3057+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3058+ start_mark, "found unexpected end of stream");
3059+ goto error;
3060+ }
3061+
3062+ /* Consume non-blank characters. */
3063+
3064+ if (!CACHE(parser, 2)) goto error;
3065+
3066+ leading_blanks = 0;
3067+
3068+ while (!IS_BLANKZ(parser->buffer))
3069+ {
3070+ /* Check for an escaped single quote. */
3071+
3072+ if (single && CHECK_AT(parser->buffer, '\'', 0)
3073+ && CHECK_AT(parser->buffer, '\'', 1))
3074+ {
3075+ if (!STRING_EXTEND(parser, string)) goto error;
3076+ *(string.pointer++) = '\'';
3077+ SKIP(parser);
3078+ SKIP(parser);
3079+ }
3080+
3081+ /* Check for the right quote. */
3082+
3083+ else if (CHECK(parser->buffer, single ? '\'' : '"'))
3084+ {
3085+ break;
3086+ }
3087+
3088+ /* Check for an escaped line break. */
3089+
3090+ else if (!single && CHECK(parser->buffer, '\\')
3091+ && IS_BREAK_AT(parser->buffer, 1))
3092+ {
3093+ if (!CACHE(parser, 3)) goto error;
3094+ SKIP(parser);
3095+ SKIP_LINE(parser);
3096+ leading_blanks = 1;
3097+ break;
3098+ }
3099+
3100+ /* Check for an escape sequence. */
3101+
3102+ else if (!single && CHECK(parser->buffer, '\\'))
3103+ {
3104+ size_t code_length = 0;
3105+
3106+ if (!STRING_EXTEND(parser, string)) goto error;
3107+
3108+ /* Check the escape character. */
3109+
3110+ switch (parser->buffer.pointer[1])
3111+ {
3112+ case '0':
3113+ *(string.pointer++) = '\0';
3114+ break;
3115+
3116+ case 'a':
3117+ *(string.pointer++) = '\x07';
3118+ break;
3119+
3120+ case 'b':
3121+ *(string.pointer++) = '\x08';
3122+ break;
3123+
3124+ case 't':
3125+ case '\t':
3126+ *(string.pointer++) = '\x09';
3127+ break;
3128+
3129+ case 'n':
3130+ *(string.pointer++) = '\x0A';
3131+ break;
3132+
3133+ case 'v':
3134+ *(string.pointer++) = '\x0B';
3135+ break;
3136+
3137+ case 'f':
3138+ *(string.pointer++) = '\x0C';
3139+ break;
3140+
3141+ case 'r':
3142+ *(string.pointer++) = '\x0D';
3143+ break;
3144+
3145+ case 'e':
3146+ *(string.pointer++) = '\x1B';
3147+ break;
3148+
3149+ case ' ':
3150+ *(string.pointer++) = '\x20';
3151+ break;
3152+
3153+ case '"':
3154+ *(string.pointer++) = '"';
3155+ break;
3156+
3157+ case '\'':
3158+ *(string.pointer++) = '\'';
3159+ break;
3160+
3161+ case '\\':
3162+ *(string.pointer++) = '\\';
3163+ break;
3164+
3165+ case 'N': /* NEL (#x85) */
3166+ *(string.pointer++) = '\xC2';
3167+ *(string.pointer++) = '\x85';
3168+ break;
3169+
3170+ case '_': /* #xA0 */
3171+ *(string.pointer++) = '\xC2';
3172+ *(string.pointer++) = '\xA0';
3173+ break;
3174+
3175+ case 'L': /* LS (#x2028) */
3176+ *(string.pointer++) = '\xE2';
3177+ *(string.pointer++) = '\x80';
3178+ *(string.pointer++) = '\xA8';
3179+ break;
3180+
3181+ case 'P': /* PS (#x2029) */
3182+ *(string.pointer++) = '\xE2';
3183+ *(string.pointer++) = '\x80';
3184+ *(string.pointer++) = '\xA9';
3185+ break;
3186+
3187+ case 'x':
3188+ code_length = 2;
3189+ break;
3190+
3191+ case 'u':
3192+ code_length = 4;
3193+ break;
3194+
3195+ case 'U':
3196+ code_length = 8;
3197+ break;
3198+
3199+ default:
3200+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3201+ start_mark, "found unknown escape character");
3202+ goto error;
3203+ }
3204+
3205+ SKIP(parser);
3206+ SKIP(parser);
3207+
3208+ /* Consume an arbitrary escape code. */
3209+
3210+ if (code_length)
3211+ {
3212+ unsigned int value = 0;
3213+ size_t k;
3214+
3215+ /* Scan the character value. */
3216+
3217+ if (!CACHE(parser, code_length)) goto error;
3218+
3219+ for (k = 0; k < code_length; k ++) {
3220+ if (!IS_HEX_AT(parser->buffer, k)) {
3221+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3222+ start_mark, "did not find expected hexdecimal number");
3223+ goto error;
3224+ }
3225+ value = (value << 4) + AS_HEX_AT(parser->buffer, k);
3226+ }
3227+
3228+ /* Check the value and write the character. */
3229+
3230+ if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
3231+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3232+ start_mark, "found invalid Unicode character escape code");
3233+ goto error;
3234+ }
3235+
3236+ if (value <= 0x7F) {
3237+ *(string.pointer++) = value;
3238+ }
3239+ else if (value <= 0x7FF) {
3240+ *(string.pointer++) = 0xC0 + (value >> 6);
3241+ *(string.pointer++) = 0x80 + (value & 0x3F);
3242+ }
3243+ else if (value <= 0xFFFF) {
3244+ *(string.pointer++) = 0xE0 + (value >> 12);
3245+ *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3246+ *(string.pointer++) = 0x80 + (value & 0x3F);
3247+ }
3248+ else {
3249+ *(string.pointer++) = 0xF0 + (value >> 18);
3250+ *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F);
3251+ *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3252+ *(string.pointer++) = 0x80 + (value & 0x3F);
3253+ }
3254+
3255+ /* Advance the pointer. */
3256+
3257+ for (k = 0; k < code_length; k ++) {
3258+ SKIP(parser);
3259+ }
3260+ }
3261+ }
3262+
3263+ else
3264+ {
3265+ /* It is a non-escaped non-blank character. */
3266+
3267+ if (!READ(parser, string)) goto error;
3268+ }
3269+
3270+ if (!CACHE(parser, 2)) goto error;
3271+ }
3272+
3273+ /* Check if we are at the end of the scalar. */
3274+
3275+ if (CHECK(parser->buffer, single ? '\'' : '"'))
3276+ break;
3277+
3278+ /* Consume blank characters. */
3279+
3280+ if (!CACHE(parser, 1)) goto error;
3281+
3282+ while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
3283+ {
3284+ if (IS_BLANK(parser->buffer))
3285+ {
3286+ /* Consume a space or a tab character. */
3287+
3288+ if (!leading_blanks) {
3289+ if (!READ(parser, whitespaces)) goto error;
3290+ }
3291+ else {
3292+ SKIP(parser);
3293+ }
3294+ }
3295+ else
3296+ {
3297+ if (!CACHE(parser, 2)) goto error;
3298+
3299+ /* Check if it is a first line break. */
3300+
3301+ if (!leading_blanks)
3302+ {
3303+ CLEAR(parser, whitespaces);
3304+ if (!READ_LINE(parser, leading_break)) goto error;
3305+ leading_blanks = 1;
3306+ }
3307+ else
3308+ {
3309+ if (!READ_LINE(parser, trailing_breaks)) goto error;
3310+ }
3311+ }
3312+ if (!CACHE(parser, 1)) goto error;
3313+ }
3314+
3315+ /* Join the whitespaces or fold line breaks. */
3316+
3317+ if (leading_blanks)
3318+ {
3319+ /* Do we need to fold line breaks? */
3320+
3321+ if (leading_break.start[0] == '\n') {
3322+ if (trailing_breaks.start[0] == '\0') {
3323+ if (!STRING_EXTEND(parser, string)) goto error;
3324+ *(string.pointer++) = ' ';
3325+ }
3326+ else {
3327+ if (!JOIN(parser, string, trailing_breaks)) goto error;
3328+ CLEAR(parser, trailing_breaks);
3329+ }
3330+ CLEAR(parser, leading_break);
3331+ }
3332+ else {
3333+ if (!JOIN(parser, string, leading_break)) goto error;
3334+ if (!JOIN(parser, string, trailing_breaks)) goto error;
3335+ CLEAR(parser, leading_break);
3336+ CLEAR(parser, trailing_breaks);
3337+ }
3338+ }
3339+ else
3340+ {
3341+ if (!JOIN(parser, string, whitespaces)) goto error;
3342+ CLEAR(parser, whitespaces);
3343+ }
3344+ }
3345+
3346+ /* Eat the right quote. */
3347+
3348+ SKIP(parser);
3349+
3350+ end_mark = parser->mark;
3351+
3352+ /* Create a token. */
3353+
3354+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
3355+ single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE,
3356+ start_mark, end_mark);
3357+
3358+ STRING_DEL(parser, leading_break);
3359+ STRING_DEL(parser, trailing_breaks);
3360+ STRING_DEL(parser, whitespaces);
3361+
3362+ return 1;
3363+
3364+error:
3365+ STRING_DEL(parser, string);
3366+ STRING_DEL(parser, leading_break);
3367+ STRING_DEL(parser, trailing_breaks);
3368+ STRING_DEL(parser, whitespaces);
3369+
3370+ return 0;
3371+}
3372+
3373+/*
3374+ * Scan a plain scalar.
3375+ */
3376+
3377+static int
3378+yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
3379+{
3380+ yaml_mark_t start_mark;
3381+ yaml_mark_t end_mark;
3382+ yaml_string_t string = NULL_STRING;
3383+ yaml_string_t leading_break = NULL_STRING;
3384+ yaml_string_t trailing_breaks = NULL_STRING;
3385+ yaml_string_t whitespaces = NULL_STRING;
3386+ int leading_blanks = 0;
3387+ int indent = parser->indent+1;
3388+
3389+ if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
3390+ if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
3391+ if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
3392+ if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
3393+
3394+ start_mark = end_mark = parser->mark;
3395+
3396+ /* Consume the content of the plain scalar. */
3397+
3398+ while (1)
3399+ {
3400+ /* Check for a document indicator. */
3401+
3402+ if (!CACHE(parser, 4)) goto error;
3403+
3404+ if (parser->mark.column == 0 &&
3405+ ((CHECK_AT(parser->buffer, '-', 0) &&
3406+ CHECK_AT(parser->buffer, '-', 1) &&
3407+ CHECK_AT(parser->buffer, '-', 2)) ||
3408+ (CHECK_AT(parser->buffer, '.', 0) &&
3409+ CHECK_AT(parser->buffer, '.', 1) &&
3410+ CHECK_AT(parser->buffer, '.', 2))) &&
3411+ IS_BLANKZ_AT(parser->buffer, 3)) break;
3412+
3413+ /* Check for a comment. */
3414+
3415+ if (CHECK(parser->buffer, '#'))
3416+ break;
3417+
3418+ /* Consume non-blank characters. */
3419+
3420+ while (!IS_BLANKZ(parser->buffer))
3421+ {
3422+ /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */
3423+
3424+ if (parser->flow_level
3425+ && CHECK(parser->buffer, ':')
3426+ && !IS_BLANKZ_AT(parser->buffer, 1)) {
3427+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
3428+ start_mark, "found unexpected ':'");
3429+ goto error;
3430+ }
3431+
3432+ /* Check for indicators that may end a plain scalar. */
3433+
3434+ if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1))
3435+ || (parser->flow_level &&
3436+ (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':')
3437+ || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[')
3438+ || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
3439+ || CHECK(parser->buffer, '}'))))
3440+ break;
3441+
3442+ /* Check if we need to join whitespaces and breaks. */
3443+
3444+ if (leading_blanks || whitespaces.start != whitespaces.pointer)
3445+ {
3446+ if (leading_blanks)
3447+ {
3448+ /* Do we need to fold line breaks? */
3449+
3450+ if (leading_break.start[0] == '\n') {
3451+ if (trailing_breaks.start[0] == '\0') {
3452+ if (!STRING_EXTEND(parser, string)) goto error;
3453+ *(string.pointer++) = ' ';
3454+ }
3455+ else {
3456+ if (!JOIN(parser, string, trailing_breaks)) goto error;
3457+ CLEAR(parser, trailing_breaks);
3458+ }
3459+ CLEAR(parser, leading_break);
3460+ }
3461+ else {
3462+ if (!JOIN(parser, string, leading_break)) goto error;
3463+ if (!JOIN(parser, string, trailing_breaks)) goto error;
3464+ CLEAR(parser, leading_break);
3465+ CLEAR(parser, trailing_breaks);
3466+ }
3467+
3468+ leading_blanks = 0;
3469+ }
3470+ else
3471+ {
3472+ if (!JOIN(parser, string, whitespaces)) goto error;
3473+ CLEAR(parser, whitespaces);
3474+ }
3475+ }
3476+
3477+ /* Copy the character. */
3478+
3479+ if (!READ(parser, string)) goto error;
3480+
3481+ end_mark = parser->mark;
3482+
3483+ if (!CACHE(parser, 2)) goto error;
3484+ }
3485+
3486+ /* Is it the end? */
3487+
3488+ if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)))
3489+ break;
3490+
3491+ /* Consume blank characters. */
3492+
3493+ if (!CACHE(parser, 1)) goto error;
3494+
3495+ while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
3496+ {
3497+ if (IS_BLANK(parser->buffer))
3498+ {
3499+ /* Check for tab character that abuse intendation. */
3500+
3501+ if (leading_blanks && (int)parser->mark.column < indent
3502+ && IS_TAB(parser->buffer)) {
3503+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
3504+ start_mark, "found a tab character that violate intendation");
3505+ goto error;
3506+ }
3507+
3508+ /* Consume a space or a tab character. */
3509+
3510+ if (!leading_blanks) {
3511+ if (!READ(parser, whitespaces)) goto error;
3512+ }
3513+ else {
3514+ SKIP(parser);
3515+ }
3516+ }
3517+ else
3518+ {
3519+ if (!CACHE(parser, 2)) goto error;
3520+
3521+ /* Check if it is a first line break. */
3522+
3523+ if (!leading_blanks)
3524+ {
3525+ CLEAR(parser, whitespaces);
3526+ if (!READ_LINE(parser, leading_break)) goto error;
3527+ leading_blanks = 1;
3528+ }
3529+ else
3530+ {
3531+ if (!READ_LINE(parser, trailing_breaks)) goto error;
3532+ }
3533+ }
3534+ if (!CACHE(parser, 1)) goto error;
3535+ }
3536+
3537+ /* Check intendation level. */
3538+
3539+ if (!parser->flow_level && (int)parser->mark.column < indent)
3540+ break;
3541+ }
3542+
3543+ /* Create a token. */
3544+
3545+ SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
3546+ YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark);
3547+
3548+ /* Note that we change the 'simple_key_allowed' flag. */
3549+
3550+ if (leading_blanks) {
3551+ parser->simple_key_allowed = 1;
3552+ }
3553+
3554+ STRING_DEL(parser, leading_break);
3555+ STRING_DEL(parser, trailing_breaks);
3556+ STRING_DEL(parser, whitespaces);
3557+
3558+ return 1;
3559+
3560+error:
3561+ STRING_DEL(parser, string);
3562+ STRING_DEL(parser, leading_break);
3563+ STRING_DEL(parser, trailing_breaks);
3564+ STRING_DEL(parser, whitespaces);
3565+
3566+ return 0;
3567+}
3568+
c/writer.cnew file+141
@@ -0,0 +1,141 @@
1+
2+#include "yaml_private.h"
3+
4+/*
5+ * Declarations.
6+ */
7+
8+static int
9+yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
10+
11+YAML_DECLARE(int)
12+yaml_emitter_flush(yaml_emitter_t *emitter);
13+
14+/*
15+ * Set the writer error and return 0.
16+ */
17+
18+static int
19+yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
20+{
21+ emitter->error = YAML_WRITER_ERROR;
22+ emitter->problem = problem;
23+
24+ return 0;
25+}
26+
27+/*
28+ * Flush the output buffer.
29+ */
30+
31+YAML_DECLARE(int)
32+yaml_emitter_flush(yaml_emitter_t *emitter)
33+{
34+ int low, high;
35+
36+ assert(emitter); /* Non-NULL emitter object is expected. */
37+ assert(emitter->write_handler); /* Write handler must be set. */
38+ assert(emitter->encoding); /* Output encoding must be set. */
39+
40+ emitter->buffer.last = emitter->buffer.pointer;
41+ emitter->buffer.pointer = emitter->buffer.start;
42+
43+ /* Check if the buffer is empty. */
44+
45+ if (emitter->buffer.start == emitter->buffer.last) {
46+ return 1;
47+ }
48+
49+ /* If the output encoding is UTF-8, we don't need to recode the buffer. */
50+
51+ if (emitter->encoding == YAML_UTF8_ENCODING)
52+ {
53+ if (emitter->write_handler(emitter->write_handler_data,
54+ emitter->buffer.start,
55+ emitter->buffer.last - emitter->buffer.start)) {
56+ emitter->buffer.last = emitter->buffer.start;
57+ emitter->buffer.pointer = emitter->buffer.start;
58+ return 1;
59+ }
60+ else {
61+ return yaml_emitter_set_writer_error(emitter, "Write error");
62+ }
63+ }
64+
65+ /* Recode the buffer into the raw buffer. */
66+
67+ low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
68+ high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
69+
70+ while (emitter->buffer.pointer != emitter->buffer.last)
71+ {
72+ unsigned char octet;
73+ unsigned int width;
74+ unsigned int value;
75+ size_t k;
76+
77+ /*
78+ * See the "reader.c" code for more details on UTF-8 encoding. Note
79+ * that we assume that the buffer contains a valid UTF-8 sequence.
80+ */
81+
82+ /* Read the next UTF-8 character. */
83+
84+ octet = emitter->buffer.pointer[0];
85+
86+ width = (octet & 0x80) == 0x00 ? 1 :
87+ (octet & 0xE0) == 0xC0 ? 2 :
88+ (octet & 0xF0) == 0xE0 ? 3 :
89+ (octet & 0xF8) == 0xF0 ? 4 : 0;
90+
91+ value = (octet & 0x80) == 0x00 ? octet & 0x7F :
92+ (octet & 0xE0) == 0xC0 ? octet & 0x1F :
93+ (octet & 0xF0) == 0xE0 ? octet & 0x0F :
94+ (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
95+
96+ for (k = 1; k < width; k ++) {
97+ octet = emitter->buffer.pointer[k];
98+ value = (value << 6) + (octet & 0x3F);
99+ }
100+
101+ emitter->buffer.pointer += width;
102+
103+ /* Write the character. */
104+
105+ if (value < 0x10000)
106+ {
107+ emitter->raw_buffer.last[high] = value >> 8;
108+ emitter->raw_buffer.last[low] = value & 0xFF;
109+
110+ emitter->raw_buffer.last += 2;
111+ }
112+ else
113+ {
114+ /* Write the character using a surrogate pair (check "reader.c"). */
115+
116+ value -= 0x10000;
117+ emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
118+ emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
119+ emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
120+ emitter->raw_buffer.last[low+2] = value & 0xFF;
121+
122+ emitter->raw_buffer.last += 4;
123+ }
124+ }
125+
126+ /* Write the raw buffer. */
127+
128+ if (emitter->write_handler(emitter->write_handler_data,
129+ emitter->raw_buffer.start,
130+ emitter->raw_buffer.last - emitter->raw_buffer.start)) {
131+ emitter->buffer.last = emitter->buffer.start;
132+ emitter->buffer.pointer = emitter->buffer.start;
133+ emitter->raw_buffer.last = emitter->raw_buffer.start;
134+ emitter->raw_buffer.pointer = emitter->raw_buffer.start;
135+ return 1;
136+ }
137+ else {
138+ return yaml_emitter_set_writer_error(emitter, "Write error");
139+ }
140+}
141+
c/yaml.hnew file+1973
@@ -0,0 +1,1973 @@
1+/**
2+ * @file yaml.h
3+ * @brief Public interface for libyaml.
4+ *
5+ * Include the header file with the code:
6+ * @code
7+ * #include <yaml.h>
8+ * @endcode
9+ */
10+
11+#ifndef YAML_H
12+#define YAML_H
13+
14+#ifdef __cplusplus
15+extern "C" {
16+#endif
17+
18+#include <stdlib.h>
19+#include <stdio.h>
20+#include <string.h>
21+
22+/**
23+ * @defgroup export Export Definitions
24+ * @{
25+ */
26+
27+/** The public API declaration. */
28+
29+#define YAML_DECLARE_STATIC
30+
31+#ifdef WIN32
32+# if defined(YAML_DECLARE_STATIC)
33+# define YAML_DECLARE(type) type
34+# elif defined(YAML_DECLARE_EXPORT)
35+# define YAML_DECLARE(type) __declspec(dllexport) type
36+# else
37+# define YAML_DECLARE(type) __declspec(dllimport) type
38+# endif
39+#else
40+# define YAML_DECLARE(type) type
41+#endif
42+
43+/** @} */
44+
45+/**
46+ * @defgroup version Version Information
47+ * @{
48+ */
49+
50+/**
51+ * Get the library version as a string.
52+ *
53+ * @returns The function returns the pointer to a static string of the form
54+ * @c "X.Y.Z", where @c X is the major version number, @c Y is a minor version
55+ * number, and @c Z is the patch version number.
56+ */
57+
58+YAML_DECLARE(const char *)
59+yaml_get_version_string(void);
60+
61+/**
62+ * Get the library version numbers.
63+ *
64+ * @param[out] major Major version number.
65+ * @param[out] minor Minor version number.
66+ * @param[out] patch Patch version number.
67+ */
68+
69+YAML_DECLARE(void)
70+yaml_get_version(int *major, int *minor, int *patch);
71+
72+/** @} */
73+
74+/**
75+ * @defgroup basic Basic Types
76+ * @{
77+ */
78+
79+/** The character type (UTF-8 octet). */
80+typedef unsigned char yaml_char_t;
81+
82+/** The version directive data. */
83+typedef struct yaml_version_directive_s {
84+ /** The major version number. */
85+ int major;
86+ /** The minor version number. */
87+ int minor;
88+} yaml_version_directive_t;
89+
90+/** The tag directive data. */
91+typedef struct yaml_tag_directive_s {
92+ /** The tag handle. */
93+ yaml_char_t *handle;
94+ /** The tag prefix. */
95+ yaml_char_t *prefix;
96+} yaml_tag_directive_t;
97+
98+/** The stream encoding. */
99+typedef enum yaml_encoding_e {
100+ /** Let the parser choose the encoding. */
101+ YAML_ANY_ENCODING,
102+ /** The default UTF-8 encoding. */
103+ YAML_UTF8_ENCODING,
104+ /** The UTF-16-LE encoding with BOM. */
105+ YAML_UTF16LE_ENCODING,
106+ /** The UTF-16-BE encoding with BOM. */
107+ YAML_UTF16BE_ENCODING
108+} yaml_encoding_t;
109+
110+/** Line break types. */
111+
112+typedef enum yaml_break_e {
113+ /** Let the parser choose the break type. */
114+ YAML_ANY_BREAK,
115+ /** Use CR for line breaks (Mac style). */
116+ YAML_CR_BREAK,
117+ /** Use LN for line breaks (Unix style). */
118+ YAML_LN_BREAK,
119+ /** Use CR LN for line breaks (DOS style). */
120+ YAML_CRLN_BREAK
121+} yaml_break_t;
122+
123+/** Many bad things could happen with the parser and emitter. */
124+typedef enum yaml_error_type_e {
125+ /** No error is produced. */
126+ YAML_NO_ERROR,
127+
128+ /** Cannot allocate or reallocate a block of memory. */
129+ YAML_MEMORY_ERROR,
130+
131+ /** Cannot read or decode the input stream. */
132+ YAML_READER_ERROR,
133+ /** Cannot scan the input stream. */
134+ YAML_SCANNER_ERROR,
135+ /** Cannot parse the input stream. */
136+ YAML_PARSER_ERROR,
137+ /** Cannot compose a YAML document. */
138+ YAML_COMPOSER_ERROR,
139+
140+ /** Cannot write to the output stream. */
141+ YAML_WRITER_ERROR,
142+ /** Cannot emit a YAML stream. */
143+ YAML_EMITTER_ERROR
144+} yaml_error_type_t;
145+
146+/** The pointer position. */
147+typedef struct yaml_mark_s {
148+ /** The position index. */
149+ size_t index;
150+
151+ /** The position line. */
152+ size_t line;
153+
154+ /** The position column. */
155+ size_t column;
156+} yaml_mark_t;
157+
158+/** @} */
159+
160+/**
161+ * @defgroup styles Node Styles
162+ * @{
163+ */
164+
165+/** Scalar styles. */
166+typedef enum yaml_scalar_style_e {
167+ /** Let the emitter choose the style. */
168+ YAML_ANY_SCALAR_STYLE,
169+
170+ /** The plain scalar style. */
171+ YAML_PLAIN_SCALAR_STYLE,
172+
173+ /** The single-quoted scalar style. */
174+ YAML_SINGLE_QUOTED_SCALAR_STYLE,
175+ /** The double-quoted scalar style. */
176+ YAML_DOUBLE_QUOTED_SCALAR_STYLE,
177+
178+ /** The literal scalar style. */
179+ YAML_LITERAL_SCALAR_STYLE,
180+ /** The folded scalar style. */
181+ YAML_FOLDED_SCALAR_STYLE
182+} yaml_scalar_style_t;
183+
184+/** Sequence styles. */
185+typedef enum yaml_sequence_style_e {
186+ /** Let the emitter choose the style. */
187+ YAML_ANY_SEQUENCE_STYLE,
188+
189+ /** The block sequence style. */
190+ YAML_BLOCK_SEQUENCE_STYLE,
191+ /** The flow sequence style. */
192+ YAML_FLOW_SEQUENCE_STYLE
193+} yaml_sequence_style_t;
194+
195+/** Mapping styles. */
196+typedef enum yaml_mapping_style_e {
197+ /** Let the emitter choose the style. */
198+ YAML_ANY_MAPPING_STYLE,
199+
200+ /** The block mapping style. */
201+ YAML_BLOCK_MAPPING_STYLE,
202+ /** The flow mapping style. */
203+ YAML_FLOW_MAPPING_STYLE
204+/* YAML_FLOW_SET_MAPPING_STYLE */
205+} yaml_mapping_style_t;
206+
207+/** @} */
208+
209+/**
210+ * @defgroup tokens Tokens
211+ * @{
212+ */
213+
214+/** Token types. */
215+typedef enum yaml_token_type_e {
216+ /** An empty token. */
217+ YAML_NO_TOKEN,
218+
219+ /** A STREAM-START token. */
220+ YAML_STREAM_START_TOKEN,
221+ /** A STREAM-END token. */
222+ YAML_STREAM_END_TOKEN,
223+
224+ /** A VERSION-DIRECTIVE token. */
225+ YAML_VERSION_DIRECTIVE_TOKEN,
226+ /** A TAG-DIRECTIVE token. */
227+ YAML_TAG_DIRECTIVE_TOKEN,
228+ /** A DOCUMENT-START token. */
229+ YAML_DOCUMENT_START_TOKEN,
230+ /** A DOCUMENT-END token. */
231+ YAML_DOCUMENT_END_TOKEN,
232+
233+ /** A BLOCK-SEQUENCE-START token. */
234+ YAML_BLOCK_SEQUENCE_START_TOKEN,
235+ /** A BLOCK-SEQUENCE-END token. */
236+ YAML_BLOCK_MAPPING_START_TOKEN,
237+ /** A BLOCK-END token. */
238+ YAML_BLOCK_END_TOKEN,
239+
240+ /** A FLOW-SEQUENCE-START token. */
241+ YAML_FLOW_SEQUENCE_START_TOKEN,
242+ /** A FLOW-SEQUENCE-END token. */
243+ YAML_FLOW_SEQUENCE_END_TOKEN,
244+ /** A FLOW-MAPPING-START token. */
245+ YAML_FLOW_MAPPING_START_TOKEN,
246+ /** A FLOW-MAPPING-END token. */
247+ YAML_FLOW_MAPPING_END_TOKEN,
248+
249+ /** A BLOCK-ENTRY token. */
250+ YAML_BLOCK_ENTRY_TOKEN,
251+ /** A FLOW-ENTRY token. */
252+ YAML_FLOW_ENTRY_TOKEN,
253+ /** A KEY token. */
254+ YAML_KEY_TOKEN,
255+ /** A VALUE token. */
256+ YAML_VALUE_TOKEN,
257+
258+ /** An ALIAS token. */
259+ YAML_ALIAS_TOKEN,
260+ /** An ANCHOR token. */
261+ YAML_ANCHOR_TOKEN,
262+ /** A TAG token. */
263+ YAML_TAG_TOKEN,
264+ /** A SCALAR token. */
265+ YAML_SCALAR_TOKEN
266+} yaml_token_type_t;
267+
268+/** The token structure. */
269+typedef struct yaml_token_s {
270+
271+ /** The token type. */
272+ yaml_token_type_t type;
273+
274+ /** The token data. */
275+ union {
276+
277+ /** The stream start (for @c YAML_STREAM_START_TOKEN). */
278+ struct {
279+ /** The stream encoding. */
280+ yaml_encoding_t encoding;
281+ } stream_start;
282+
283+ /** The alias (for @c YAML_ALIAS_TOKEN). */
284+ struct {
285+ /** The alias value. */
286+ yaml_char_t *value;
287+ } alias;
288+
289+ /** The anchor (for @c YAML_ANCHOR_TOKEN). */
290+ struct {
291+ /** The anchor value. */
292+ yaml_char_t *value;
293+ } anchor;
294+
295+ /** The tag (for @c YAML_TAG_TOKEN). */
296+ struct {
297+ /** The tag handle. */
298+ yaml_char_t *handle;
299+ /** The tag suffix. */
300+ yaml_char_t *suffix;
301+ } tag;
302+
303+ /** The scalar value (for @c YAML_SCALAR_TOKEN). */
304+ struct {
305+ /** The scalar value. */
306+ yaml_char_t *value;
307+ /** The length of the scalar value. */
308+ size_t length;
309+ /** The scalar style. */
310+ yaml_scalar_style_t style;
311+ } scalar;
312+
313+ /** The version directive (for @c YAML_VERSION_DIRECTIVE_TOKEN). */
314+ struct {
315+ /** The major version number. */
316+ int major;
317+ /** The minor version number. */
318+ int minor;
319+ } version_directive;
320+
321+ /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */
322+ struct {
323+ /** The tag handle. */
324+ yaml_char_t *handle;
325+ /** The tag prefix. */
326+ yaml_char_t *prefix;
327+ } tag_directive;
328+
329+ } data;
330+
331+ /** The beginning of the token. */
332+ yaml_mark_t start_mark;
333+ /** The end of the token. */
334+ yaml_mark_t end_mark;
335+
336+} yaml_token_t;
337+
338+/**
339+ * Free any memory allocated for a token object.
340+ *
341+ * @param[in,out] token A token object.
342+ */
343+
344+YAML_DECLARE(void)
345+yaml_token_delete(yaml_token_t *token);
346+
347+/** @} */
348+
349+/**
350+ * @defgroup events Events
351+ * @{
352+ */
353+
354+/** Event types. */
355+typedef enum yaml_event_type_e {
356+ /** An empty event. */
357+ YAML_NO_EVENT,
358+
359+ /** A STREAM-START event. */
360+ YAML_STREAM_START_EVENT,
361+ /** A STREAM-END event. */
362+ YAML_STREAM_END_EVENT,
363+
364+ /** A DOCUMENT-START event. */
365+ YAML_DOCUMENT_START_EVENT,
366+ /** A DOCUMENT-END event. */
367+ YAML_DOCUMENT_END_EVENT,
368+
369+ /** An ALIAS event. */
370+ YAML_ALIAS_EVENT,
371+ /** A SCALAR event. */
372+ YAML_SCALAR_EVENT,
373+
374+ /** A SEQUENCE-START event. */
375+ YAML_SEQUENCE_START_EVENT,
376+ /** A SEQUENCE-END event. */
377+ YAML_SEQUENCE_END_EVENT,
378+
379+ /** A MAPPING-START event. */
380+ YAML_MAPPING_START_EVENT,
381+ /** A MAPPING-END event. */
382+ YAML_MAPPING_END_EVENT
383+} yaml_event_type_t;
384+
385+/** The event structure. */
386+typedef struct yaml_event_s {
387+
388+ /** The event type. */
389+ yaml_event_type_t type;
390+
391+ /** The event data. */
392+ union {
393+
394+ /** The stream parameters (for @c YAML_STREAM_START_EVENT). */
395+ struct {
396+ /** The document encoding. */
397+ yaml_encoding_t encoding;
398+ } stream_start;
399+
400+ /** The document parameters (for @c YAML_DOCUMENT_START_EVENT). */
401+ struct {
402+ /** The version directive. */
403+ yaml_version_directive_t *version_directive;
404+
405+ /** The list of tag directives. */
406+ struct {
407+ /** The beginning of the tag directives list. */
408+ yaml_tag_directive_t *start;
409+ /** The end of the tag directives list. */
410+ yaml_tag_directive_t *end;
411+ } tag_directives;
412+
413+ /** Is the document indicator implicit? */
414+ int implicit;
415+ } document_start;
416+
417+ /** The document end parameters (for @c YAML_DOCUMENT_END_EVENT). */
418+ struct {
419+ /** Is the document end indicator implicit? */
420+ int implicit;
421+ } document_end;
422+
423+ /** The alias parameters (for @c YAML_ALIAS_EVENT). */
424+ struct {
425+ /** The anchor. */
426+ yaml_char_t *anchor;
427+ } alias;
428+
429+ /** The scalar parameters (for @c YAML_SCALAR_EVENT). */
430+ struct {
431+ /** The anchor. */
432+ yaml_char_t *anchor;
433+ /** The tag. */
434+ yaml_char_t *tag;
435+ /** The scalar value. */
436+ yaml_char_t *value;
437+ /** The length of the scalar value. */
438+ size_t length;
439+ /** Is the tag optional for the plain style? */
440+ int plain_implicit;
441+ /** Is the tag optional for any non-plain style? */
442+ int quoted_implicit;
443+ /** The scalar style. */
444+ yaml_scalar_style_t style;
445+ } scalar;
446+
447+ /** The sequence parameters (for @c YAML_SEQUENCE_START_EVENT). */
448+ struct {
449+ /** The anchor. */
450+ yaml_char_t *anchor;
451+ /** The tag. */
452+ yaml_char_t *tag;
453+ /** Is the tag optional? */
454+ int implicit;
455+ /** The sequence style. */
456+ yaml_sequence_style_t style;
457+ } sequence_start;
458+
459+ /** The mapping parameters (for @c YAML_MAPPING_START_EVENT). */
460+ struct {
461+ /** The anchor. */
462+ yaml_char_t *anchor;
463+ /** The tag. */
464+ yaml_char_t *tag;
465+ /** Is the tag optional? */
466+ int implicit;
467+ /** The mapping style. */
468+ yaml_mapping_style_t style;
469+ } mapping_start;
470+
471+ } data;
472+
473+ /** The beginning of the event. */
474+ yaml_mark_t start_mark;
475+ /** The end of the event. */
476+ yaml_mark_t end_mark;
477+
478+} yaml_event_t;
479+
480+/**
481+ * Create the STREAM-START event.
482+ *
483+ * @param[out] event An empty event object.
484+ * @param[in] encoding The stream encoding.
485+ *
486+ * @returns @c 1 if the function succeeded, @c 0 on error.
487+ */
488+
489+YAML_DECLARE(int)
490+yaml_stream_start_event_initialize(yaml_event_t *event,
491+ yaml_encoding_t encoding);
492+
493+/**
494+ * Create the STREAM-END event.
495+ *
496+ * @param[out] event An empty event object.
497+ *
498+ * @returns @c 1 if the function succeeded, @c 0 on error.
499+ */
500+
501+YAML_DECLARE(int)
502+yaml_stream_end_event_initialize(yaml_event_t *event);
503+
504+/**
505+ * Create the DOCUMENT-START event.
506+ *
507+ * The @a implicit argument is considered as a stylistic parameter and may be
508+ * ignored by the emitter.
509+ *
510+ * @param[out] event An empty event object.
511+ * @param[in] version_directive The %YAML directive value or
512+ * @c NULL.
513+ * @param[in] tag_directives_start The beginning of the %TAG
514+ * directives list.
515+ * @param[in] tag_directives_end The end of the %TAG directives
516+ * list.
517+ * @param[in] implicit If the document start indicator is
518+ * implicit.
519+ *
520+ * @returns @c 1 if the function succeeded, @c 0 on error.
521+ */
522+
523+YAML_DECLARE(int)
524+yaml_document_start_event_initialize(yaml_event_t *event,
525+ yaml_version_directive_t *version_directive,
526+ yaml_tag_directive_t *tag_directives_start,
527+ yaml_tag_directive_t *tag_directives_end,
528+ int implicit);
529+
530+/**
531+ * Create the DOCUMENT-END event.
532+ *
533+ * The @a implicit argument is considered as a stylistic parameter and may be
534+ * ignored by the emitter.
535+ *
536+ * @param[out] event An empty event object.
537+ * @param[in] implicit If the document end indicator is implicit.
538+ *
539+ * @returns @c 1 if the function succeeded, @c 0 on error.
540+ */
541+
542+YAML_DECLARE(int)
543+yaml_document_end_event_initialize(yaml_event_t *event, int implicit);
544+
545+/**
546+ * Create an ALIAS event.
547+ *
548+ * @param[out] event An empty event object.
549+ * @param[in] anchor The anchor value.
550+ *
551+ * @returns @c 1 if the function succeeded, @c 0 on error.
552+ */
553+
554+YAML_DECLARE(int)
555+yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
556+
557+/**
558+ * Create a SCALAR event.
559+ *
560+ * The @a style argument may be ignored by the emitter.
561+ *
562+ * Either the @a tag attribute or one of the @a plain_implicit and
563+ * @a quoted_implicit flags must be set.
564+ *
565+ * @param[out] event An empty event object.
566+ * @param[in] anchor The scalar anchor or @c NULL.
567+ * @param[in] tag The scalar tag or @c NULL.
568+ * @param[in] value The scalar value.
569+ * @param[in] length The length of the scalar value.
570+ * @param[in] plain_implicit If the tag may be omitted for the plain
571+ * style.
572+ * @param[in] quoted_implicit If the tag may be omitted for any
573+ * non-plain style.
574+ * @param[in] style The scalar style.
575+ *
576+ * @returns @c 1 if the function succeeded, @c 0 on error.
577+ */
578+
579+YAML_DECLARE(int)
580+yaml_scalar_event_initialize(yaml_event_t *event,
581+ yaml_char_t *anchor, yaml_char_t *tag,
582+ yaml_char_t *value, int length,
583+ int plain_implicit, int quoted_implicit,
584+ yaml_scalar_style_t style);
585+
586+/**
587+ * Create a SEQUENCE-START event.
588+ *
589+ * The @a style argument may be ignored by the emitter.
590+ *
591+ * Either the @a tag attribute or the @a implicit flag must be set.
592+ *
593+ * @param[out] event An empty event object.
594+ * @param[in] anchor The sequence anchor or @c NULL.
595+ * @param[in] tag The sequence tag or @c NULL.
596+ * @param[in] implicit If the tag may be omitted.
597+ * @param[in] style The sequence style.
598+ *
599+ * @returns @c 1 if the function succeeded, @c 0 on error.
600+ */
601+
602+YAML_DECLARE(int)
603+yaml_sequence_start_event_initialize(yaml_event_t *event,
604+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
605+ yaml_sequence_style_t style);
606+
607+/**
608+ * Create a SEQUENCE-END event.
609+ *
610+ * @param[out] event An empty event object.
611+ *
612+ * @returns @c 1 if the function succeeded, @c 0 on error.
613+ */
614+
615+YAML_DECLARE(int)
616+yaml_sequence_end_event_initialize(yaml_event_t *event);
617+
618+/**
619+ * Create a MAPPING-START event.
620+ *
621+ * The @a style argument may be ignored by the emitter.
622+ *
623+ * Either the @a tag attribute or the @a implicit flag must be set.
624+ *
625+ * @param[out] event An empty event object.
626+ * @param[in] anchor The mapping anchor or @c NULL.
627+ * @param[in] tag The mapping tag or @c NULL.
628+ * @param[in] implicit If the tag may be omitted.
629+ * @param[in] style The mapping style.
630+ *
631+ * @returns @c 1 if the function succeeded, @c 0 on error.
632+ */
633+
634+YAML_DECLARE(int)
635+yaml_mapping_start_event_initialize(yaml_event_t *event,
636+ yaml_char_t *anchor, yaml_char_t *tag, int implicit,
637+ yaml_mapping_style_t style);
638+
639+/**
640+ * Create a MAPPING-END event.
641+ *
642+ * @param[out] event An empty event object.
643+ *
644+ * @returns @c 1 if the function succeeded, @c 0 on error.
645+ */
646+
647+YAML_DECLARE(int)
648+yaml_mapping_end_event_initialize(yaml_event_t *event);
649+
650+/**
651+ * Free any memory allocated for an event object.
652+ *
653+ * @param[in,out] event An event object.
654+ */
655+
656+YAML_DECLARE(void)
657+yaml_event_delete(yaml_event_t *event);
658+
659+/** @} */
660+
661+/**
662+ * @defgroup nodes Nodes
663+ * @{
664+ */
665+
666+/** The tag @c !!null with the only possible value: @c null. */
667+#define YAML_NULL_TAG "tag:yaml.org,2002:null"
668+/** The tag @c !!bool with the values: @c true and @c falce. */
669+#define YAML_BOOL_TAG "tag:yaml.org,2002:bool"
670+/** The tag @c !!str for string values. */
671+#define YAML_STR_TAG "tag:yaml.org,2002:str"
672+/** The tag @c !!int for integer values. */
673+#define YAML_INT_TAG "tag:yaml.org,2002:int"
674+/** The tag @c !!float for float values. */
675+#define YAML_FLOAT_TAG "tag:yaml.org,2002:float"
676+/** The tag @c !!timestamp for date and time values. */
677+#define YAML_TIMESTAMP_TAG "tag:yaml.org,2002:timestamp"
678+
679+/** The tag @c !!seq is used to denote sequences. */
680+#define YAML_SEQ_TAG "tag:yaml.org,2002:seq"
681+/** The tag @c !!map is used to denote mapping. */
682+#define YAML_MAP_TAG "tag:yaml.org,2002:map"
683+
684+/** The default scalar tag is @c !!str. */
685+#define YAML_DEFAULT_SCALAR_TAG YAML_STR_TAG
686+/** The default sequence tag is @c !!seq. */
687+#define YAML_DEFAULT_SEQUENCE_TAG YAML_SEQ_TAG
688+/** The default mapping tag is @c !!map. */
689+#define YAML_DEFAULT_MAPPING_TAG YAML_MAP_TAG
690+
691+/** Node types. */
692+typedef enum yaml_node_type_e {
693+ /** An empty node. */
694+ YAML_NO_NODE,
695+
696+ /** A scalar node. */
697+ YAML_SCALAR_NODE,
698+ /** A sequence node. */
699+ YAML_SEQUENCE_NODE,
700+ /** A mapping node. */
701+ YAML_MAPPING_NODE
702+} yaml_node_type_t;
703+
704+/** The forward definition of a document node structure. */
705+typedef struct yaml_node_s yaml_node_t;
706+
707+/** An element of a sequence node. */
708+typedef int yaml_node_item_t;
709+
710+/** An element of a mapping node. */
711+typedef struct yaml_node_pair_s {
712+ /** The key of the element. */
713+ int key;
714+ /** The value of the element. */
715+ int value;
716+} yaml_node_pair_t;
717+
718+/** The node structure. */
719+struct yaml_node_s {
720+
721+ /** The node type. */
722+ yaml_node_type_t type;
723+
724+ /** The node tag. */
725+ yaml_char_t *tag;
726+
727+ /** The node data. */
728+ union {
729+
730+ /** The scalar parameters (for @c YAML_SCALAR_NODE). */
731+ struct {
732+ /** The scalar value. */
733+ yaml_char_t *value;
734+ /** The length of the scalar value. */
735+ size_t length;
736+ /** The scalar style. */
737+ yaml_scalar_style_t style;
738+ } scalar;
739+
740+ /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */
741+ struct {
742+ /** The stack of sequence items. */
743+ struct {
744+ /** The beginning of the stack. */
745+ yaml_node_item_t *start;
746+ /** The end of the stack. */
747+ yaml_node_item_t *end;
748+ /** The top of the stack. */
749+ yaml_node_item_t *top;
750+ } items;
751+ /** The sequence style. */
752+ yaml_sequence_style_t style;
753+ } sequence;
754+
755+ /** The mapping parameters (for @c YAML_MAPPING_NODE). */
756+ struct {
757+ /** The stack of mapping pairs (key, value). */
758+ struct {
759+ /** The beginning of the stack. */
760+ yaml_node_pair_t *start;
761+ /** The end of the stack. */
762+ yaml_node_pair_t *end;
763+ /** The top of the stack. */
764+ yaml_node_pair_t *top;
765+ } pairs;
766+ /** The mapping style. */
767+ yaml_mapping_style_t style;
768+ } mapping;
769+
770+ } data;
771+
772+ /** The beginning of the node. */
773+ yaml_mark_t start_mark;
774+ /** The end of the node. */
775+ yaml_mark_t end_mark;
776+
777+};
778+
779+/** The document structure. */
780+typedef struct yaml_document_s {
781+
782+ /** The document nodes. */
783+ struct {
784+ /** The beginning of the stack. */
785+ yaml_node_t *start;
786+ /** The end of the stack. */
787+ yaml_node_t *end;
788+ /** The top of the stack. */
789+ yaml_node_t *top;
790+ } nodes;
791+
792+ /** The version directive. */
793+ yaml_version_directive_t *version_directive;
794+
795+ /** The list of tag directives. */
796+ struct {
797+ /** The beginning of the tag directives list. */
798+ yaml_tag_directive_t *start;
799+ /** The end of the tag directives list. */
800+ yaml_tag_directive_t *end;
801+ } tag_directives;
802+
803+ /** Is the document start indicator implicit? */
804+ int start_implicit;
805+ /** Is the document end indicator implicit? */
806+ int end_implicit;
807+
808+ /** The beginning of the document. */
809+ yaml_mark_t start_mark;
810+ /** The end of the document. */
811+ yaml_mark_t end_mark;
812+
813+} yaml_document_t;
814+
815+/**
816+ * Create a YAML document.
817+ *
818+ * @param[out] document An empty document object.
819+ * @param[in] version_directive The %YAML directive value or
820+ * @c NULL.
821+ * @param[in] tag_directives_start The beginning of the %TAG
822+ * directives list.
823+ * @param[in] tag_directives_end The end of the %TAG directives
824+ * list.
825+ * @param[in] start_implicit If the document start indicator is
826+ * implicit.
827+ * @param[in] end_implicit If the document end indicator is
828+ * implicit.
829+ *
830+ * @returns @c 1 if the function succeeded, @c 0 on error.
831+ */
832+
833+YAML_DECLARE(int)
834+yaml_document_initialize(yaml_document_t *document,
835+ yaml_version_directive_t *version_directive,
836+ yaml_tag_directive_t *tag_directives_start,
837+ yaml_tag_directive_t *tag_directives_end,
838+ int start_implicit, int end_implicit);
839+
840+/**
841+ * Delete a YAML document and all its nodes.
842+ *
843+ * @param[in,out] document A document object.
844+ */
845+
846+YAML_DECLARE(void)
847+yaml_document_delete(yaml_document_t *document);
848+
849+/**
850+ * Get a node of a YAML document.
851+ *
852+ * The pointer returned by this function is valid until any of the functions
853+ * modifying the documents are called.
854+ *
855+ * @param[in] document A document object.
856+ * @param[in] index The node id.
857+ *
858+ * @returns the node objct or @c NULL if @c node_id is out of range.
859+ */
860+
861+YAML_DECLARE(yaml_node_t *)
862+yaml_document_get_node(yaml_document_t *document, int index);
863+
864+/**
865+ * Get the root of a YAML document node.
866+ *
867+ * The root object is the first object added to the document.
868+ *
869+ * The pointer returned by this function is valid until any of the functions
870+ * modifying the documents are called.
871+ *
872+ * An empty document produced by the parser signifies the end of a YAML
873+ * stream.
874+ *
875+ * @param[in] document A document object.
876+ *
877+ * @returns the node object or @c NULL if the document is empty.
878+ */
879+
880+YAML_DECLARE(yaml_node_t *)
881+yaml_document_get_root_node(yaml_document_t *document);
882+
883+/**
884+ * Create a SCALAR node and attach it to the document.
885+ *
886+ * The @a style argument may be ignored by the emitter.
887+ *
888+ * @param[in,out] document A document object.
889+ * @param[in] tag The scalar tag.
890+ * @param[in] value The scalar value.
891+ * @param[in] length The length of the scalar value.
892+ * @param[in] style The scalar style.
893+ *
894+ * @returns the node id or @c 0 on error.
895+ */
896+
897+YAML_DECLARE(int)
898+yaml_document_add_scalar(yaml_document_t *document,
899+ yaml_char_t *tag, yaml_char_t *value, int length,
900+ yaml_scalar_style_t style);
901+
902+/**
903+ * Create a SEQUENCE node and attach it to the document.
904+ *
905+ * The @a style argument may be ignored by the emitter.
906+ *
907+ * @param[in,out] document A document object.
908+ * @param[in] tag The sequence tag.
909+ * @param[in] style The sequence style.
910+ *
911+ * @returns the node id or @c 0 on error.
912+ */
913+
914+YAML_DECLARE(int)
915+yaml_document_add_sequence(yaml_document_t *document,
916+ yaml_char_t *tag, yaml_sequence_style_t style);
917+
918+/**
919+ * Create a MAPPING node and attach it to the document.
920+ *
921+ * The @a style argument may be ignored by the emitter.
922+ *
923+ * @param[in,out] document A document object.
924+ * @param[in] tag The sequence tag.
925+ * @param[in] style The sequence style.
926+ *
927+ * @returns the node id or @c 0 on error.
928+ */
929+
930+YAML_DECLARE(int)
931+yaml_document_add_mapping(yaml_document_t *document,
932+ yaml_char_t *tag, yaml_mapping_style_t style);
933+
934+/**
935+ * Add an item to a SEQUENCE node.
936+ *
937+ * @param[in,out] document A document object.
938+ * @param[in] sequence The sequence node id.
939+ * @param[in] item The item node id.
940+*
941+ * @returns @c 1 if the function succeeded, @c 0 on error.
942+ */
943+
944+YAML_DECLARE(int)
945+yaml_document_append_sequence_item(yaml_document_t *document,
946+ int sequence, int item);
947+
948+/**
949+ * Add a pair of a key and a value to a MAPPING node.
950+ *
951+ * @param[in,out] document A document object.
952+ * @param[in] mapping The mapping node id.
953+ * @param[in] key The key node id.
954+ * @param[in] value The value node id.
955+*
956+ * @returns @c 1 if the function succeeded, @c 0 on error.
957+ */
958+
959+YAML_DECLARE(int)
960+yaml_document_append_mapping_pair(yaml_document_t *document,
961+ int mapping, int key, int value);
962+
963+/** @} */
964+
965+/**
966+ * @defgroup parser Parser Definitions
967+ * @{
968+ */
969+
970+/**
971+ * The prototype of a read handler.
972+ *
973+ * The read handler is called when the parser needs to read more bytes from the
974+ * source. The handler should write not more than @a size bytes to the @a
975+ * buffer. The number of written bytes should be set to the @a length variable.
976+ *
977+ * @param[in,out] data A pointer to an application data specified by
978+ * yaml_parser_set_input().
979+ * @param[out] buffer The buffer to write the data from the source.
980+ * @param[in] size The size of the buffer.
981+ * @param[out] size_read The actual number of bytes read from the source.
982+ *
983+ * @returns On success, the handler should return @c 1. If the handler failed,
984+ * the returned value should be @c 0. On EOF, the handler should set the
985+ * @a size_read to @c 0 and return @c 1.
986+ */
987+
988+typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size,
989+ size_t *size_read);
990+
991+/**
992+ * This structure holds information about a potential simple key.
993+ */
994+
995+typedef struct yaml_simple_key_s {
996+ /** Is a simple key possible? */
997+ int possible;
998+
999+ /** Is a simple key required? */
1000+ int required;
1001+
1002+ /** The number of the token. */
1003+ size_t token_number;
1004+
1005+ /** The position mark. */
1006+ yaml_mark_t mark;
1007+} yaml_simple_key_t;
1008+
1009+/**
1010+ * The states of the parser.
1011+ */
1012+typedef enum yaml_parser_state_e {
1013+ /** Expect STREAM-START. */
1014+ YAML_PARSE_STREAM_START_STATE,
1015+ /** Expect the beginning of an implicit document. */
1016+ YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE,
1017+ /** Expect DOCUMENT-START. */
1018+ YAML_PARSE_DOCUMENT_START_STATE,
1019+ /** Expect the content of a document. */
1020+ YAML_PARSE_DOCUMENT_CONTENT_STATE,
1021+ /** Expect DOCUMENT-END. */
1022+ YAML_PARSE_DOCUMENT_END_STATE,
1023+ /** Expect a block node. */
1024+ YAML_PARSE_BLOCK_NODE_STATE,
1025+ /** Expect a block node or indentless sequence. */
1026+ YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE,
1027+ /** Expect a flow node. */
1028+ YAML_PARSE_FLOW_NODE_STATE,
1029+ /** Expect the first entry of a block sequence. */
1030+ YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE,
1031+ /** Expect an entry of a block sequence. */
1032+ YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE,
1033+ /** Expect an entry of an indentless sequence. */
1034+ YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE,
1035+ /** Expect the first key of a block mapping. */
1036+ YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE,
1037+ /** Expect a block mapping key. */
1038+ YAML_PARSE_BLOCK_MAPPING_KEY_STATE,
1039+ /** Expect a block mapping value. */
1040+ YAML_PARSE_BLOCK_MAPPING_VALUE_STATE,
1041+ /** Expect the first entry of a flow sequence. */
1042+ YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE,
1043+ /** Expect an entry of a flow sequence. */
1044+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE,
1045+ /** Expect a key of an ordered mapping. */
1046+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE,
1047+ /** Expect a value of an ordered mapping. */
1048+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE,
1049+ /** Expect the and of an ordered mapping entry. */
1050+ YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE,
1051+ /** Expect the first key of a flow mapping. */
1052+ YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE,
1053+ /** Expect a key of a flow mapping. */
1054+ YAML_PARSE_FLOW_MAPPING_KEY_STATE,
1055+ /** Expect a value of a flow mapping. */
1056+ YAML_PARSE_FLOW_MAPPING_VALUE_STATE,
1057+ /** Expect an empty value of a flow mapping. */
1058+ YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE,
1059+ /** Expect nothing. */
1060+ YAML_PARSE_END_STATE
1061+} yaml_parser_state_t;
1062+
1063+/**
1064+ * This structure holds aliases data.
1065+ */
1066+
1067+typedef struct yaml_alias_data_s {
1068+ /** The anchor. */
1069+ yaml_char_t *anchor;
1070+ /** The node id. */
1071+ int index;
1072+ /** The anchor mark. */
1073+ yaml_mark_t mark;
1074+} yaml_alias_data_t;
1075+
1076+/**
1077+ * The parser structure.
1078+ *
1079+ * All members are internal. Manage the structure using the @c yaml_parser_
1080+ * family of functions.
1081+ */
1082+
1083+typedef struct yaml_parser_s {
1084+
1085+ /**
1086+ * @name Error handling
1087+ * @{
1088+ */
1089+
1090+ /** Error type. */
1091+ yaml_error_type_t error;
1092+ /** Error description. */
1093+ const char *problem;
1094+ /** The byte about which the problem occured. */
1095+ size_t problem_offset;
1096+ /** The problematic value (@c -1 is none). */
1097+ int problem_value;
1098+ /** The problem position. */
1099+ yaml_mark_t problem_mark;
1100+ /** The error context. */
1101+ const char *context;
1102+ /** The context position. */
1103+ yaml_mark_t context_mark;
1104+
1105+ /**
1106+ * @}
1107+ */
1108+
1109+ /**
1110+ * @name Reader stuff
1111+ * @{
1112+ */
1113+
1114+ /** Read handler. */
1115+ yaml_read_handler_t *read_handler;
1116+
1117+ /** A pointer for passing to the read handler. */
1118+ void *read_handler_data;
1119+
1120+ /** Standard (string or file) input data. */
1121+ union {
1122+ /** String input data. */
1123+ struct {
1124+ /** The string start pointer. */
1125+ const unsigned char *start;
1126+ /** The string end pointer. */
1127+ const unsigned char *end;
1128+ /** The string current position. */
1129+ const unsigned char *current;
1130+ } string;
1131+
1132+ /** File input data. */
1133+ FILE *file;
1134+ } input;
1135+
1136+ /** EOF flag */
1137+ int eof;
1138+
1139+ /** The working buffer. */
1140+ struct {
1141+ /** The beginning of the buffer. */
1142+ yaml_char_t *start;
1143+ /** The end of the buffer. */
1144+ yaml_char_t *end;
1145+ /** The current position of the buffer. */
1146+ yaml_char_t *pointer;
1147+ /** The last filled position of the buffer. */
1148+ yaml_char_t *last;
1149+ } buffer;
1150+
1151+ /* The number of unread characters in the buffer. */
1152+ size_t unread;
1153+
1154+ /** The raw buffer. */
1155+ struct {
1156+ /** The beginning of the buffer. */
1157+ unsigned char *start;
1158+ /** The end of the buffer. */
1159+ unsigned char *end;
1160+ /** The current position of the buffer. */
1161+ unsigned char *pointer;
1162+ /** The last filled position of the buffer. */
1163+ unsigned char *last;
1164+ } raw_buffer;
1165+
1166+ /** The input encoding. */
1167+ yaml_encoding_t encoding;
1168+
1169+ /** The offset of the current position (in bytes). */
1170+ size_t offset;
1171+
1172+ /** The mark of the current position. */
1173+ yaml_mark_t mark;
1174+
1175+ /**
1176+ * @}
1177+ */
1178+
1179+ /**
1180+ * @name Scanner stuff
1181+ * @{
1182+ */
1183+
1184+ /** Have we started to scan the input stream? */
1185+ int stream_start_produced;
1186+
1187+ /** Have we reached the end of the input stream? */
1188+ int stream_end_produced;
1189+
1190+ /** The number of unclosed '[' and '{' indicators. */
1191+ int flow_level;
1192+
1193+ /** The tokens queue. */
1194+ struct {
1195+ /** The beginning of the tokens queue. */
1196+ yaml_token_t *start;
1197+ /** The end of the tokens queue. */
1198+ yaml_token_t *end;
1199+ /** The head of the tokens queue. */
1200+ yaml_token_t *head;
1201+ /** The tail of the tokens queue. */
1202+ yaml_token_t *tail;
1203+ } tokens;
1204+
1205+ /** The number of tokens fetched from the queue. */
1206+ size_t tokens_parsed;
1207+
1208+ /* Does the tokens queue contain a token ready for dequeueing. */
1209+ int token_available;
1210+
1211+ /** The indentation levels stack. */
1212+ struct {
1213+ /** The beginning of the stack. */
1214+ int *start;
1215+ /** The end of the stack. */
1216+ int *end;
1217+ /** The top of the stack. */
1218+ int *top;
1219+ } indents;
1220+
1221+ /** The current indentation level. */
1222+ int indent;
1223+
1224+ /** May a simple key occur at the current position? */
1225+ int simple_key_allowed;
1226+
1227+ /** The stack of simple keys. */
1228+ struct {
1229+ /** The beginning of the stack. */
1230+ yaml_simple_key_t *start;
1231+ /** The end of the stack. */
1232+ yaml_simple_key_t *end;
1233+ /** The top of the stack. */
1234+ yaml_simple_key_t *top;
1235+ } simple_keys;
1236+
1237+ /**
1238+ * @}
1239+ */
1240+
1241+ /**
1242+ * @name Parser stuff
1243+ * @{
1244+ */
1245+
1246+ /** The parser states stack. */
1247+ struct {
1248+ /** The beginning of the stack. */
1249+ yaml_parser_state_t *start;
1250+ /** The end of the stack. */
1251+ yaml_parser_state_t *end;
1252+ /** The top of the stack. */
1253+ yaml_parser_state_t *top;
1254+ } states;
1255+
1256+ /** The current parser state. */
1257+ yaml_parser_state_t state;
1258+
1259+ /** The stack of marks. */
1260+ struct {
1261+ /** The beginning of the stack. */
1262+ yaml_mark_t *start;
1263+ /** The end of the stack. */
1264+ yaml_mark_t *end;
1265+ /** The top of the stack. */
1266+ yaml_mark_t *top;
1267+ } marks;
1268+
1269+ /** The list of TAG directives. */
1270+ struct {
1271+ /** The beginning of the list. */
1272+ yaml_tag_directive_t *start;
1273+ /** The end of the list. */
1274+ yaml_tag_directive_t *end;
1275+ /** The top of the list. */
1276+ yaml_tag_directive_t *top;
1277+ } tag_directives;
1278+
1279+ /**
1280+ * @}
1281+ */
1282+
1283+ /**
1284+ * @name Dumper stuff
1285+ * @{
1286+ */
1287+
1288+ /** The alias data. */
1289+ struct {
1290+ /** The beginning of the list. */
1291+ yaml_alias_data_t *start;
1292+ /** The end of the list. */
1293+ yaml_alias_data_t *end;
1294+ /** The top of the list. */
1295+ yaml_alias_data_t *top;
1296+ } aliases;
1297+
1298+ /** The currently parsed document. */
1299+ yaml_document_t *document;
1300+
1301+ /**
1302+ * @}
1303+ */
1304+
1305+} yaml_parser_t;
1306+
1307+/**
1308+ * Initialize a parser.
1309+ *
1310+ * This function creates a new parser object. An application is responsible
1311+ * for destroying the object using the yaml_parser_delete() function.
1312+ *
1313+ * @param[out] parser An empty parser object.
1314+ *
1315+ * @returns @c 1 if the function succeeded, @c 0 on error.
1316+ */
1317+
1318+YAML_DECLARE(int)
1319+yaml_parser_initialize(yaml_parser_t *parser);
1320+
1321+/**
1322+ * Destroy a parser.
1323+ *
1324+ * @param[in,out] parser A parser object.
1325+ */
1326+
1327+YAML_DECLARE(void)
1328+yaml_parser_delete(yaml_parser_t *parser);
1329+
1330+/**
1331+ * Set a string input.
1332+ *
1333+ * Note that the @a input pointer must be valid while the @a parser object
1334+ * exists. The application is responsible for destroing @a input after
1335+ * destroying the @a parser.
1336+ *
1337+ * @param[in,out] parser A parser object.
1338+ * @param[in] input A source data.
1339+ * @param[in] size The length of the source data in bytes.
1340+ */
1341+
1342+YAML_DECLARE(void)
1343+yaml_parser_set_input_string(yaml_parser_t *parser,
1344+ const unsigned char *input, size_t size);
1345+
1346+/**
1347+ * Set a file input.
1348+ *
1349+ * @a file should be a file object open for reading. The application is
1350+ * responsible for closing the @a file.
1351+ *
1352+ * @param[in,out] parser A parser object.
1353+ * @param[in] file An open file.
1354+ */
1355+
1356+YAML_DECLARE(void)
1357+yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file);
1358+
1359+/**
1360+ * Set a generic input handler.
1361+ *
1362+ * @param[in,out] parser A parser object.
1363+ * @param[in] handler A read handler.
1364+ * @param[in] data Any application data for passing to the read
1365+ * handler.
1366+ */
1367+
1368+YAML_DECLARE(void)
1369+yaml_parser_set_input(yaml_parser_t *parser,
1370+ yaml_read_handler_t *handler, void *data);
1371+
1372+/**
1373+ * Set the source encoding.
1374+ *
1375+ * @param[in,out] parser A parser object.
1376+ * @param[in] encoding The source encoding.
1377+ */
1378+
1379+YAML_DECLARE(void)
1380+yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding);
1381+
1382+/**
1383+ * Scan the input stream and produce the next token.
1384+ *
1385+ * Call the function subsequently to produce a sequence of tokens corresponding
1386+ * to the input stream. The initial token has the type
1387+ * @c YAML_STREAM_START_TOKEN while the ending token has the type
1388+ * @c YAML_STREAM_END_TOKEN.
1389+ *
1390+ * An application is responsible for freeing any buffers associated with the
1391+ * produced token object using the @c yaml_token_delete function.
1392+ *
1393+ * An application must not alternate the calls of yaml_parser_scan() with the
1394+ * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
1395+ * the parser.
1396+ *
1397+ * @param[in,out] parser A parser object.
1398+ * @param[out] token An empty token object.
1399+ *
1400+ * @returns @c 1 if the function succeeded, @c 0 on error.
1401+ */
1402+
1403+YAML_DECLARE(int)
1404+yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token);
1405+
1406+/**
1407+ * Parse the input stream and produce the next parsing event.
1408+ *
1409+ * Call the function subsequently to produce a sequence of events corresponding
1410+ * to the input stream. The initial event has the type
1411+ * @c YAML_STREAM_START_EVENT while the ending event has the type
1412+ * @c YAML_STREAM_END_EVENT.
1413+ *
1414+ * An application is responsible for freeing any buffers associated with the
1415+ * produced event object using the yaml_event_delete() function.
1416+ *
1417+ * An application must not alternate the calls of yaml_parser_parse() with the
1418+ * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the
1419+ * parser.
1420+ *
1421+ * @param[in,out] parser A parser object.
1422+ * @param[out] event An empty event object.
1423+ *
1424+ * @returns @c 1 if the function succeeded, @c 0 on error.
1425+ */
1426+
1427+YAML_DECLARE(int)
1428+yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
1429+
1430+/**
1431+ * Parse the input stream and produce the next YAML document.
1432+ *
1433+ * Call this function subsequently to produce a sequence of documents
1434+ * constituting the input stream.
1435+ *
1436+ * If the produced document has no root node, it means that the document
1437+ * end has been reached.
1438+ *
1439+ * An application is responsible for freeing any data associated with the
1440+ * produced document object using the yaml_document_delete() function.
1441+ *
1442+ * An application must not alternate the calls of yaml_parser_load() with the
1443+ * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
1444+ * the parser.
1445+ *
1446+ * @param[in,out] parser A parser object.
1447+ * @param[out] document An empty document object.
1448+ *
1449+ * @return @c 1 if the function succeeded, @c 0 on error.
1450+ */
1451+
1452+YAML_DECLARE(int)
1453+yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document);
1454+
1455+/** @} */
1456+
1457+/**
1458+ * @defgroup emitter Emitter Definitions
1459+ * @{
1460+ */
1461+
1462+/**
1463+ * The prototype of a write handler.
1464+ *
1465+ * The write handler is called when the emitter needs to flush the accumulated
1466+ * characters to the output. The handler should write @a size bytes of the
1467+ * @a buffer to the output.
1468+ *
1469+ * @param[in,out] data A pointer to an application data specified by
1470+ * yaml_emitter_set_output().
1471+ * @param[in] buffer The buffer with bytes to be written.
1472+ * @param[in] size The size of the buffer.
1473+ *
1474+ * @returns On success, the handler should return @c 1. If the handler failed,
1475+ * the returned value should be @c 0.
1476+ */
1477+
1478+typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size);
1479+
1480+/** The emitter states. */
1481+typedef enum yaml_emitter_state_e {
1482+ /** Expect STREAM-START. */
1483+ YAML_EMIT_STREAM_START_STATE,
1484+ /** Expect the first DOCUMENT-START or STREAM-END. */
1485+ YAML_EMIT_FIRST_DOCUMENT_START_STATE,
1486+ /** Expect DOCUMENT-START or STREAM-END. */
1487+ YAML_EMIT_DOCUMENT_START_STATE,
1488+ /** Expect the content of a document. */
1489+ YAML_EMIT_DOCUMENT_CONTENT_STATE,
1490+ /** Expect DOCUMENT-END. */
1491+ YAML_EMIT_DOCUMENT_END_STATE,
1492+ /** Expect the first item of a flow sequence. */
1493+ YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE,
1494+ /** Expect an item of a flow sequence. */
1495+ YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE,
1496+ /** Expect the first key of a flow mapping. */
1497+ YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE,
1498+ /** Expect a key of a flow mapping. */
1499+ YAML_EMIT_FLOW_MAPPING_KEY_STATE,
1500+ /** Expect a value for a simple key of a flow mapping. */
1501+ YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE,
1502+ /** Expect a value of a flow mapping. */
1503+ YAML_EMIT_FLOW_MAPPING_VALUE_STATE,
1504+ /** Expect the first item of a block sequence. */
1505+ YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE,
1506+ /** Expect an item of a block sequence. */
1507+ YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE,
1508+ /** Expect the first key of a block mapping. */
1509+ YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE,
1510+ /** Expect the key of a block mapping. */
1511+ YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
1512+ /** Expect a value for a simple key of a block mapping. */
1513+ YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE,
1514+ /** Expect a value of a block mapping. */
1515+ YAML_EMIT_BLOCK_MAPPING_VALUE_STATE,
1516+ /** Expect nothing. */
1517+ YAML_EMIT_END_STATE
1518+} yaml_emitter_state_t;
1519+
1520+/**
1521+ * The emitter structure.
1522+ *
1523+ * All members are internal. Manage the structure using the @c yaml_emitter_
1524+ * family of functions.
1525+ */
1526+
1527+typedef struct yaml_emitter_s {
1528+
1529+ /**
1530+ * @name Error handling
1531+ * @{
1532+ */
1533+
1534+ /** Error type. */
1535+ yaml_error_type_t error;
1536+ /** Error description. */
1537+ const char *problem;
1538+
1539+ /**
1540+ * @}
1541+ */
1542+
1543+ /**
1544+ * @name Writer stuff
1545+ * @{
1546+ */
1547+
1548+ /** Write handler. */
1549+ yaml_write_handler_t *write_handler;
1550+
1551+ /** A pointer for passing to the white handler. */
1552+ void *write_handler_data;
1553+
1554+ /** Standard (string or file) output data. */
1555+ union {
1556+ /** String output data. */
1557+ struct {
1558+ /** The buffer pointer. */
1559+ unsigned char *buffer;
1560+ /** The buffer size. */
1561+ size_t size;
1562+ /** The number of written bytes. */
1563+ size_t *size_written;
1564+ } string;
1565+
1566+ /** File output data. */
1567+ FILE *file;
1568+ } output;
1569+
1570+ /** The working buffer. */
1571+ struct {
1572+ /** The beginning of the buffer. */
1573+ yaml_char_t *start;
1574+ /** The end of the buffer. */
1575+ yaml_char_t *end;
1576+ /** The current position of the buffer. */
1577+ yaml_char_t *pointer;
1578+ /** The last filled position of the buffer. */
1579+ yaml_char_t *last;
1580+ } buffer;
1581+
1582+ /** The raw buffer. */
1583+ struct {
1584+ /** The beginning of the buffer. */
1585+ unsigned char *start;
1586+ /** The end of the buffer. */
1587+ unsigned char *end;
1588+ /** The current position of the buffer. */
1589+ unsigned char *pointer;
1590+ /** The last filled position of the buffer. */
1591+ unsigned char *last;
1592+ } raw_buffer;
1593+
1594+ /** The stream encoding. */
1595+ yaml_encoding_t encoding;
1596+
1597+ /**
1598+ * @}
1599+ */
1600+
1601+ /**
1602+ * @name Emitter stuff
1603+ * @{
1604+ */
1605+
1606+ /** If the output is in the canonical style? */
1607+ int canonical;
1608+ /** The number of indentation spaces. */
1609+ int best_indent;
1610+ /** The preferred width of the output lines. */
1611+ int best_width;
1612+ /** Allow unescaped non-ASCII characters? */
1613+ int unicode;
1614+ /** The preferred line break. */
1615+ yaml_break_t line_break;
1616+
1617+ /** The stack of states. */
1618+ struct {
1619+ /** The beginning of the stack. */
1620+ yaml_emitter_state_t *start;
1621+ /** The end of the stack. */
1622+ yaml_emitter_state_t *end;
1623+ /** The top of the stack. */
1624+ yaml_emitter_state_t *top;
1625+ } states;
1626+
1627+ /** The current emitter state. */
1628+ yaml_emitter_state_t state;
1629+
1630+ /** The event queue. */
1631+ struct {
1632+ /** The beginning of the event queue. */
1633+ yaml_event_t *start;
1634+ /** The end of the event queue. */
1635+ yaml_event_t *end;
1636+ /** The head of the event queue. */
1637+ yaml_event_t *head;
1638+ /** The tail of the event queue. */
1639+ yaml_event_t *tail;
1640+ } events;
1641+
1642+ /** The stack of indentation levels. */
1643+ struct {
1644+ /** The beginning of the stack. */
1645+ int *start;
1646+ /** The end of the stack. */
1647+ int *end;
1648+ /** The top of the stack. */
1649+ int *top;
1650+ } indents;
1651+
1652+ /** The list of tag directives. */
1653+ struct {
1654+ /** The beginning of the list. */
1655+ yaml_tag_directive_t *start;
1656+ /** The end of the list. */
1657+ yaml_tag_directive_t *end;
1658+ /** The top of the list. */
1659+ yaml_tag_directive_t *top;
1660+ } tag_directives;
1661+
1662+ /** The current indentation level. */
1663+ int indent;
1664+
1665+ /** The current flow level. */
1666+ int flow_level;
1667+
1668+ /** Is it the document root context? */
1669+ int root_context;
1670+ /** Is it a sequence context? */
1671+ int sequence_context;
1672+ /** Is it a mapping context? */
1673+ int mapping_context;
1674+ /** Is it a simple mapping key context? */
1675+ int simple_key_context;
1676+
1677+ /** The current line. */
1678+ int line;
1679+ /** The current column. */
1680+ int column;
1681+ /** If the last character was a whitespace? */
1682+ int whitespace;
1683+ /** If the last character was an indentation character (' ', '-', '?', ':')? */
1684+ int indention;
1685+ /** If an explicit document end is required? */
1686+ int open_ended;
1687+
1688+ /** Anchor analysis. */
1689+ struct {
1690+ /** The anchor value. */
1691+ yaml_char_t *anchor;
1692+ /** The anchor length. */
1693+ size_t anchor_length;
1694+ /** Is it an alias? */
1695+ int alias;
1696+ } anchor_data;
1697+
1698+ /** Tag analysis. */
1699+ struct {
1700+ /** The tag handle. */
1701+ yaml_char_t *handle;
1702+ /** The tag handle length. */
1703+ size_t handle_length;
1704+ /** The tag suffix. */
1705+ yaml_char_t *suffix;
1706+ /** The tag suffix length. */
1707+ size_t suffix_length;
1708+ } tag_data;
1709+
1710+ /** Scalar analysis. */
1711+ struct {
1712+ /** The scalar value. */
1713+ yaml_char_t *value;
1714+ /** The scalar length. */
1715+ size_t length;
1716+ /** Does the scalar contain line breaks? */
1717+ int multiline;
1718+ /** Can the scalar be expessed in the flow plain style? */
1719+ int flow_plain_allowed;
1720+ /** Can the scalar be expressed in the block plain style? */
1721+ int block_plain_allowed;
1722+ /** Can the scalar be expressed in the single quoted style? */
1723+ int single_quoted_allowed;
1724+ /** Can the scalar be expressed in the literal or folded styles? */
1725+ int block_allowed;
1726+ /** The output style. */
1727+ yaml_scalar_style_t style;
1728+ } scalar_data;
1729+
1730+ /**
1731+ * @}
1732+ */
1733+
1734+ /**
1735+ * @name Dumper stuff
1736+ * @{
1737+ */
1738+
1739+ /** If the stream was already opened? */
1740+ int opened;
1741+ /** If the stream was already closed? */
1742+ int closed;
1743+
1744+ /** The information associated with the document nodes. */
1745+ struct {
1746+ /** The number of references. */
1747+ int references;
1748+ /** The anchor id. */
1749+ int anchor;
1750+ /** If the node has been emitted? */
1751+ int serialized;
1752+ } *anchors;
1753+
1754+ /** The last assigned anchor id. */
1755+ int last_anchor_id;
1756+
1757+ /** The currently emitted document. */
1758+ yaml_document_t *document;
1759+
1760+ /**
1761+ * @}
1762+ */
1763+
1764+} yaml_emitter_t;
1765+
1766+/**
1767+ * Initialize an emitter.
1768+ *
1769+ * This function creates a new emitter object. An application is responsible
1770+ * for destroying the object using the yaml_emitter_delete() function.
1771+ *
1772+ * @param[out] emitter An empty parser object.
1773+ *
1774+ * @returns @c 1 if the function succeeded, @c 0 on error.
1775+ */
1776+
1777+YAML_DECLARE(int)
1778+yaml_emitter_initialize(yaml_emitter_t *emitter);
1779+
1780+/**
1781+ * Destroy an emitter.
1782+ *
1783+ * @param[in,out] emitter An emitter object.
1784+ */
1785+
1786+YAML_DECLARE(void)
1787+yaml_emitter_delete(yaml_emitter_t *emitter);
1788+
1789+/**
1790+ * Set a string output.
1791+ *
1792+ * The emitter will write the output characters to the @a output buffer of the
1793+ * size @a size. The emitter will set @a size_written to the number of written
1794+ * bytes. If the buffer is smaller than required, the emitter produces the
1795+ * YAML_WRITE_ERROR error.
1796+ *
1797+ * @param[in,out] emitter An emitter object.
1798+ * @param[in] output An output buffer.
1799+ * @param[in] size The buffer size.
1800+ * @param[in] size_written The pointer to save the number of written
1801+ * bytes.
1802+ */
1803+
1804+YAML_DECLARE(void)
1805+yaml_emitter_set_output_string(yaml_emitter_t *emitter,
1806+ unsigned char *output, size_t size, size_t *size_written);
1807+
1808+/**
1809+ * Set a file output.
1810+ *
1811+ * @a file should be a file object open for writing. The application is
1812+ * responsible for closing the @a file.
1813+ *
1814+ * @param[in,out] emitter An emitter object.
1815+ * @param[in] file An open file.
1816+ */
1817+
1818+YAML_DECLARE(void)
1819+yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file);
1820+
1821+/**
1822+ * Set a generic output handler.
1823+ *
1824+ * @param[in,out] emitter An emitter object.
1825+ * @param[in] handler A write handler.
1826+ * @param[in] data Any application data for passing to the write
1827+ * handler.
1828+ */
1829+
1830+YAML_DECLARE(void)
1831+yaml_emitter_set_output(yaml_emitter_t *emitter,
1832+ yaml_write_handler_t *handler, void *data);
1833+
1834+/**
1835+ * Set the output encoding.
1836+ *
1837+ * @param[in,out] emitter An emitter object.
1838+ * @param[in] encoding The output encoding.
1839+ */
1840+
1841+YAML_DECLARE(void)
1842+yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding);
1843+
1844+/**
1845+ * Set if the output should be in the "canonical" format as in the YAML
1846+ * specification.
1847+ *
1848+ * @param[in,out] emitter An emitter object.
1849+ * @param[in] canonical If the output is canonical.
1850+ */
1851+
1852+YAML_DECLARE(void)
1853+yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical);
1854+
1855+/**
1856+ * Set the intendation increment.
1857+ *
1858+ * @param[in,out] emitter An emitter object.
1859+ * @param[in] indent The indentation increment (1 < . < 10).
1860+ */
1861+
1862+YAML_DECLARE(void)
1863+yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent);
1864+
1865+/**
1866+ * Set the preferred line width. @c -1 means unlimited.
1867+ *
1868+ * @param[in,out] emitter An emitter object.
1869+ * @param[in] width The preferred line width.
1870+ */
1871+
1872+YAML_DECLARE(void)
1873+yaml_emitter_set_width(yaml_emitter_t *emitter, int width);
1874+
1875+/**
1876+ * Set if unescaped non-ASCII characters are allowed.
1877+ *
1878+ * @param[in,out] emitter An emitter object.
1879+ * @param[in] unicode If unescaped Unicode characters are allowed.
1880+ */
1881+
1882+YAML_DECLARE(void)
1883+yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode);
1884+
1885+/**
1886+ * Set the preferred line break.
1887+ *
1888+ * @param[in,out] emitter An emitter object.
1889+ * @param[in] line_break The preferred line break.
1890+ */
1891+
1892+YAML_DECLARE(void)
1893+yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break);
1894+
1895+/**
1896+ * Emit an event.
1897+ *
1898+ * The event object may be generated using the yaml_parser_parse() function.
1899+ * The emitter takes the responsibility for the event object and destroys its
1900+ * content after it is emitted. The event object is destroyed even if the
1901+ * function fails.
1902+ *
1903+ * @param[in,out] emitter An emitter object.
1904+ * @param[in,out] event An event object.
1905+ *
1906+ * @returns @c 1 if the function succeeded, @c 0 on error.
1907+ */
1908+
1909+YAML_DECLARE(int)
1910+yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event);
1911+
1912+/**
1913+ * Start a YAML stream.
1914+ *
1915+ * This function should be used before yaml_emitter_dump() is called.
1916+ *
1917+ * @param[in,out] emitter An emitter object.
1918+ *
1919+ * @returns @c 1 if the function succeeded, @c 0 on error.
1920+ */
1921+
1922+YAML_DECLARE(int)
1923+yaml_emitter_open(yaml_emitter_t *emitter);
1924+
1925+/**
1926+ * Finish a YAML stream.
1927+ *
1928+ * This function should be used after yaml_emitter_dump() is called.
1929+ *
1930+ * @param[in,out] emitter An emitter object.
1931+ *
1932+ * @returns @c 1 if the function succeeded, @c 0 on error.
1933+ */
1934+
1935+YAML_DECLARE(int)
1936+yaml_emitter_close(yaml_emitter_t *emitter);
1937+
1938+/**
1939+ * Emit a YAML document.
1940+ *
1941+ * The documen object may be generated using the yaml_parser_load() function
1942+ * or the yaml_document_initialize() function. The emitter takes the
1943+ * responsibility for the document object and destoys its content after
1944+ * it is emitted. The document object is destroyedeven if the function fails.
1945+ *
1946+ * @param[in,out] emitter An emitter object.
1947+ * @param[in,out] document A document object.
1948+ *
1949+ * @returns @c 1 if the function succeeded, @c 0 on error.
1950+ */
1951+
1952+YAML_DECLARE(int)
1953+yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document);
1954+
1955+/**
1956+ * Flush the accumulated characters to the output.
1957+ *
1958+ * @param[in,out] emitter An emitter object.
1959+ *
1960+ * @returns @c 1 if the function succeeded, @c 0 on error.
1961+ */
1962+
1963+YAML_DECLARE(int)
1964+yaml_emitter_flush(yaml_emitter_t *emitter);
1965+
1966+/** @} */
1967+
1968+#ifdef __cplusplus
1969+}
1970+#endif
1971+
1972+#endif /* #ifndef YAML_H */
1973+
c/yaml_private.hnew file+639
@@ -0,0 +1,639 @@
1+
2+#if HAVE_CONFIG_H
3+#include <config.h>
4+#endif
5+
6+#include <yaml.h>
7+
8+#include <assert.h>
9+#include <limits.h>
10+
11+/*
12+ * Memory management.
13+ */
14+
15+YAML_DECLARE(void *)
16+yaml_malloc(size_t size);
17+
18+YAML_DECLARE(void *)
19+yaml_realloc(void *ptr, size_t size);
20+
21+YAML_DECLARE(void)
22+yaml_free(void *ptr);
23+
24+YAML_DECLARE(yaml_char_t *)
25+yaml_strdup(const yaml_char_t *);
26+
27+/*
28+ * Reader: Ensure that the buffer contains at least `length` characters.
29+ */
30+
31+YAML_DECLARE(int)
32+yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
33+
34+/*
35+ * Scanner: Ensure that the token stack contains at least one token ready.
36+ */
37+
38+YAML_DECLARE(int)
39+yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
40+
41+/*
42+ * The size of the input raw buffer.
43+ */
44+
45+#define INPUT_RAW_BUFFER_SIZE 16384
46+
47+/*
48+ * The size of the input buffer.
49+ *
50+ * It should be possible to decode the whole raw buffer.
51+ */
52+
53+#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
54+
55+/*
56+ * The size of the output buffer.
57+ */
58+
59+#define OUTPUT_BUFFER_SIZE 16384
60+
61+/*
62+ * The size of the output raw buffer.
63+ *
64+ * It should be possible to encode the whole output buffer.
65+ */
66+
67+#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
68+
69+/*
70+ * The size of other stacks and queues.
71+ */
72+
73+#define INITIAL_STACK_SIZE 16
74+#define INITIAL_QUEUE_SIZE 16
75+#define INITIAL_STRING_SIZE 16
76+
77+/*
78+ * Buffer management.
79+ */
80+
81+#define BUFFER_INIT(context,buffer,size) \
82+ (((buffer).start = yaml_malloc(size)) ? \
83+ ((buffer).last = (buffer).pointer = (buffer).start, \
84+ (buffer).end = (buffer).start+(size), \
85+ 1) : \
86+ ((context)->error = YAML_MEMORY_ERROR, \
87+ 0))
88+
89+#define BUFFER_DEL(context,buffer) \
90+ (yaml_free((buffer).start), \
91+ (buffer).start = (buffer).pointer = (buffer).end = 0)
92+
93+/*
94+ * String management.
95+ */
96+
97+typedef struct {
98+ yaml_char_t *start;
99+ yaml_char_t *end;
100+ yaml_char_t *pointer;
101+} yaml_string_t;
102+
103+YAML_DECLARE(int)
104+yaml_string_extend(yaml_char_t **start,
105+ yaml_char_t **pointer, yaml_char_t **end);
106+
107+YAML_DECLARE(int)
108+yaml_string_join(
109+ yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
110+ yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
111+
112+#define NULL_STRING { NULL, NULL, NULL }
113+
114+#define STRING(string,length) { (string), (string)+(length), (string) }
115+
116+#define STRING_INIT(context,string,size) \
117+ (((string).start = yaml_malloc(size)) ? \
118+ ((string).pointer = (string).start, \
119+ (string).end = (string).start+(size), \
120+ memset((string).start, 0, (size)), \
121+ 1) : \
122+ ((context)->error = YAML_MEMORY_ERROR, \
123+ 0))
124+
125+#define STRING_DEL(context,string) \
126+ (yaml_free((string).start), \
127+ (string).start = (string).pointer = (string).end = 0)
128+
129+#define STRING_EXTEND(context,string) \
130+ (((string).pointer+5 < (string).end) \
131+ || yaml_string_extend(&(string).start, \
132+ &(string).pointer, &(string).end))
133+
134+#define CLEAR(context,string) \
135+ ((string).pointer = (string).start, \
136+ memset((string).start, 0, (string).end-(string).start))
137+
138+#define JOIN(context,string_a,string_b) \
139+ ((yaml_string_join(&(string_a).start, &(string_a).pointer, \
140+ &(string_a).end, &(string_b).start, \
141+ &(string_b).pointer, &(string_b).end)) ? \
142+ ((string_b).pointer = (string_b).start, \
143+ 1) : \
144+ ((context)->error = YAML_MEMORY_ERROR, \
145+ 0))
146+
147+/*
148+ * String check operations.
149+ */
150+
151+/*
152+ * Check the octet at the specified position.
153+ */
154+
155+#define CHECK_AT(string,octet,offset) \
156+ ((string).pointer[offset] == (yaml_char_t)(octet))
157+
158+/*
159+ * Check the current octet in the buffer.
160+ */
161+
162+#define CHECK(string,octet) CHECK_AT((string),(octet),0)
163+
164+/*
165+ * Check if the character at the specified position is an alphabetical
166+ * character, a digit, '_', or '-'.
167+ */
168+
169+#define IS_ALPHA_AT(string,offset) \
170+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
171+ (string).pointer[offset] <= (yaml_char_t) '9') || \
172+ ((string).pointer[offset] >= (yaml_char_t) 'A' && \
173+ (string).pointer[offset] <= (yaml_char_t) 'Z') || \
174+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
175+ (string).pointer[offset] <= (yaml_char_t) 'z') || \
176+ (string).pointer[offset] == '_' || \
177+ (string).pointer[offset] == '-')
178+
179+#define IS_ALPHA(string) IS_ALPHA_AT((string),0)
180+
181+/*
182+ * Check if the character at the specified position is a digit.
183+ */
184+
185+#define IS_DIGIT_AT(string,offset) \
186+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
187+ (string).pointer[offset] <= (yaml_char_t) '9'))
188+
189+#define IS_DIGIT(string) IS_DIGIT_AT((string),0)
190+
191+/*
192+ * Get the value of a digit.
193+ */
194+
195+#define AS_DIGIT_AT(string,offset) \
196+ ((string).pointer[offset] - (yaml_char_t) '0')
197+
198+#define AS_DIGIT(string) AS_DIGIT_AT((string),0)
199+
200+/*
201+ * Check if the character at the specified position is a hex-digit.
202+ */
203+
204+#define IS_HEX_AT(string,offset) \
205+ (((string).pointer[offset] >= (yaml_char_t) '0' && \
206+ (string).pointer[offset] <= (yaml_char_t) '9') || \
207+ ((string).pointer[offset] >= (yaml_char_t) 'A' && \
208+ (string).pointer[offset] <= (yaml_char_t) 'F') || \
209+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
210+ (string).pointer[offset] <= (yaml_char_t) 'f'))
211+
212+#define IS_HEX(string) IS_HEX_AT((string),0)
213+
214+/*
215+ * Get the value of a hex-digit.
216+ */
217+
218+#define AS_HEX_AT(string,offset) \
219+ (((string).pointer[offset] >= (yaml_char_t) 'A' && \
220+ (string).pointer[offset] <= (yaml_char_t) 'F') ? \
221+ ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
222+ ((string).pointer[offset] >= (yaml_char_t) 'a' && \
223+ (string).pointer[offset] <= (yaml_char_t) 'f') ? \
224+ ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
225+ ((string).pointer[offset] - (yaml_char_t) '0'))
226+
227+#define AS_HEX(string) AS_HEX_AT((string),0)
228+
229+/*
230+ * Check if the character is ASCII.
231+ */
232+
233+#define IS_ASCII_AT(string,offset) \
234+ ((string).pointer[offset] <= (yaml_char_t) '\x7F')
235+
236+#define IS_ASCII(string) IS_ASCII_AT((string),0)
237+
238+/*
239+ * Check if the character can be printed unescaped.
240+ */
241+
242+#define IS_PRINTABLE_AT(string,offset) \
243+ (((string).pointer[offset] == 0x0A) /* . == #x0A */ \
244+ || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
245+ && (string).pointer[offset] <= 0x7E) \
246+ || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
247+ && (string).pointer[offset+1] >= 0xA0) \
248+ || ((string).pointer[offset] > 0xC2 \
249+ && (string).pointer[offset] < 0xED) \
250+ || ((string).pointer[offset] == 0xED \
251+ && (string).pointer[offset+1] < 0xA0) \
252+ || ((string).pointer[offset] == 0xEE) \
253+ || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
254+ && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
255+ && (string).pointer[offset+2] == 0xBF) \
256+ && !((string).pointer[offset+1] == 0xBF \
257+ && ((string).pointer[offset+2] == 0xBE \
258+ || (string).pointer[offset+2] == 0xBF))))
259+
260+#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
261+
262+/*
263+ * Check if the character at the specified position is NUL.
264+ */
265+
266+#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
267+
268+#define IS_Z(string) IS_Z_AT((string),0)
269+
270+/*
271+ * Check if the character at the specified position is BOM.
272+ */
273+
274+#define IS_BOM_AT(string,offset) \
275+ (CHECK_AT((string),'\xEF',(offset)) \
276+ && CHECK_AT((string),'\xBB',(offset)+1) \
277+ && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
278+
279+#define IS_BOM(string) IS_BOM_AT(string,0)
280+
281+/*
282+ * Check if the character at the specified position is space.
283+ */
284+
285+#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
286+
287+#define IS_SPACE(string) IS_SPACE_AT((string),0)
288+
289+/*
290+ * Check if the character at the specified position is tab.
291+ */
292+
293+#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
294+
295+#define IS_TAB(string) IS_TAB_AT((string),0)
296+
297+/*
298+ * Check if the character at the specified position is blank (space or tab).
299+ */
300+
301+#define IS_BLANK_AT(string,offset) \
302+ (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
303+
304+#define IS_BLANK(string) IS_BLANK_AT((string),0)
305+
306+/*
307+ * Check if the character at the specified position is a line break.
308+ */
309+
310+#define IS_BREAK_AT(string,offset) \
311+ (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
312+ || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
313+ || (CHECK_AT((string),'\xC2',(offset)) \
314+ && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
315+ || (CHECK_AT((string),'\xE2',(offset)) \
316+ && CHECK_AT((string),'\x80',(offset)+1) \
317+ && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
318+ || (CHECK_AT((string),'\xE2',(offset)) \
319+ && CHECK_AT((string),'\x80',(offset)+1) \
320+ && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
321+
322+#define IS_BREAK(string) IS_BREAK_AT((string),0)
323+
324+#define IS_CRLF_AT(string,offset) \
325+ (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
326+
327+#define IS_CRLF(string) IS_CRLF_AT((string),0)
328+
329+/*
330+ * Check if the character is a line break or NUL.
331+ */
332+
333+#define IS_BREAKZ_AT(string,offset) \
334+ (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
335+
336+#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
337+
338+/*
339+ * Check if the character is a line break, space, or NUL.
340+ */
341+
342+#define IS_SPACEZ_AT(string,offset) \
343+ (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
344+
345+#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
346+
347+/*
348+ * Check if the character is a line break, space, tab, or NUL.
349+ */
350+
351+#define IS_BLANKZ_AT(string,offset) \
352+ (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
353+
354+#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
355+
356+/*
357+ * Determine the width of the character.
358+ */
359+
360+#define WIDTH_AT(string,offset) \
361+ (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
362+ ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
363+ ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
364+ ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
365+
366+#define WIDTH(string) WIDTH_AT((string),0)
367+
368+/*
369+ * Move the string pointer to the next character.
370+ */
371+
372+#define MOVE(string) ((string).pointer += WIDTH((string)))
373+
374+/*
375+ * Copy a character and move the pointers of both strings.
376+ */
377+
378+#define COPY(string_a,string_b) \
379+ ((*(string_b).pointer & 0x80) == 0x00 ? \
380+ (*((string_a).pointer++) = *((string_b).pointer++)) : \
381+ (*(string_b).pointer & 0xE0) == 0xC0 ? \
382+ (*((string_a).pointer++) = *((string_b).pointer++), \
383+ *((string_a).pointer++) = *((string_b).pointer++)) : \
384+ (*(string_b).pointer & 0xF0) == 0xE0 ? \
385+ (*((string_a).pointer++) = *((string_b).pointer++), \
386+ *((string_a).pointer++) = *((string_b).pointer++), \
387+ *((string_a).pointer++) = *((string_b).pointer++)) : \
388+ (*(string_b).pointer & 0xF8) == 0xF0 ? \
389+ (*((string_a).pointer++) = *((string_b).pointer++), \
390+ *((string_a).pointer++) = *((string_b).pointer++), \
391+ *((string_a).pointer++) = *((string_b).pointer++), \
392+ *((string_a).pointer++) = *((string_b).pointer++)) : 0)
393+
394+/*
395+ * Stack and queue management.
396+ */
397+
398+YAML_DECLARE(int)
399+yaml_stack_extend(void **start, void **top, void **end);
400+
401+YAML_DECLARE(int)
402+yaml_queue_extend(void **start, void **head, void **tail, void **end);
403+
404+#define STACK_INIT(context,stack,size) \
405+ (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
406+ ((stack).top = (stack).start, \
407+ (stack).end = (stack).start+(size), \
408+ 1) : \
409+ ((context)->error = YAML_MEMORY_ERROR, \
410+ 0))
411+
412+#define STACK_DEL(context,stack) \
413+ (yaml_free((stack).start), \
414+ (stack).start = (stack).top = (stack).end = 0)
415+
416+#define STACK_EMPTY(context,stack) \
417+ ((stack).start == (stack).top)
418+
419+#define PUSH(context,stack,value) \
420+ (((stack).top != (stack).end \
421+ || yaml_stack_extend((void **)&(stack).start, \
422+ (void **)&(stack).top, (void **)&(stack).end)) ? \
423+ (*((stack).top++) = value, \
424+ 1) : \
425+ ((context)->error = YAML_MEMORY_ERROR, \
426+ 0))
427+
428+#define POP(context,stack) \
429+ (*(--(stack).top))
430+
431+#define QUEUE_INIT(context,queue,size) \
432+ (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
433+ ((queue).head = (queue).tail = (queue).start, \
434+ (queue).end = (queue).start+(size), \
435+ 1) : \
436+ ((context)->error = YAML_MEMORY_ERROR, \
437+ 0))
438+
439+#define QUEUE_DEL(context,queue) \
440+ (yaml_free((queue).start), \
441+ (queue).start = (queue).head = (queue).tail = (queue).end = 0)
442+
443+#define QUEUE_EMPTY(context,queue) \
444+ ((queue).head == (queue).tail)
445+
446+#define ENQUEUE(context,queue,value) \
447+ (((queue).tail != (queue).end \
448+ || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
449+ (void **)&(queue).tail, (void **)&(queue).end)) ? \
450+ (*((queue).tail++) = value, \
451+ 1) : \
452+ ((context)->error = YAML_MEMORY_ERROR, \
453+ 0))
454+
455+#define DEQUEUE(context,queue) \
456+ (*((queue).head++))
457+
458+#define QUEUE_INSERT(context,queue,index,value) \
459+ (((queue).tail != (queue).end \
460+ || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
461+ (void **)&(queue).tail, (void **)&(queue).end)) ? \
462+ (memmove((queue).head+(index)+1,(queue).head+(index), \
463+ ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
464+ *((queue).head+(index)) = value, \
465+ (queue).tail++, \
466+ 1) : \
467+ ((context)->error = YAML_MEMORY_ERROR, \
468+ 0))
469+
470+/*
471+ * Token initializers.
472+ */
473+
474+#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
475+ (memset(&(token), 0, sizeof(yaml_token_t)), \
476+ (token).type = (token_type), \
477+ (token).start_mark = (token_start_mark), \
478+ (token).end_mark = (token_end_mark))
479+
480+#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
481+ (TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \
482+ (token).data.stream_start.encoding = (token_encoding))
483+
484+#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
485+ (TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark)))
486+
487+#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
488+ (TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \
489+ (token).data.alias.value = (token_value))
490+
491+#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
492+ (TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \
493+ (token).data.anchor.value = (token_value))
494+
495+#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
496+ (TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \
497+ (token).data.tag.handle = (token_handle), \
498+ (token).data.tag.suffix = (token_suffix))
499+
500+#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
501+ (TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \
502+ (token).data.scalar.value = (token_value), \
503+ (token).data.scalar.length = (token_length), \
504+ (token).data.scalar.style = (token_style))
505+
506+#define VERSION_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
507+ (TOKEN_INIT((token),YAML_VERSION_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
508+ (token).data.version_directive.major = (token_major), \
509+ (token).data.version_directive.minor = (token_minor))
510+
511+#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
512+ (TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
513+ (token).data.tag_directive.handle = (token_handle), \
514+ (token).data.tag_directive.prefix = (token_prefix))
515+
516+/*
517+ * Event initializers.
518+ */
519+
520+#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
521+ (memset(&(event), 0, sizeof(yaml_event_t)), \
522+ (event).type = (event_type), \
523+ (event).start_mark = (event_start_mark), \
524+ (event).end_mark = (event_end_mark))
525+
526+#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
527+ (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \
528+ (event).data.stream_start.encoding = (event_encoding))
529+
530+#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
531+ (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
532+
533+#define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \
534+ event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
535+ (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
536+ (event).data.document_start.version_directive = (event_version_directive), \
537+ (event).data.document_start.tag_directives.start = (event_tag_directives_start), \
538+ (event).data.document_start.tag_directives.end = (event_tag_directives_end), \
539+ (event).data.document_start.implicit = (event_implicit))
540+
541+#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
542+ (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
543+ (event).data.document_end.implicit = (event_implicit))
544+
545+#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
546+ (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \
547+ (event).data.alias.anchor = (event_anchor))
548+
549+#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
550+ event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
551+ (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \
552+ (event).data.scalar.anchor = (event_anchor), \
553+ (event).data.scalar.tag = (event_tag), \
554+ (event).data.scalar.value = (event_value), \
555+ (event).data.scalar.length = (event_length), \
556+ (event).data.scalar.plain_implicit = (event_plain_implicit), \
557+ (event).data.scalar.quoted_implicit = (event_quoted_implicit), \
558+ (event).data.scalar.style = (event_style))
559+
560+#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
561+ event_implicit,event_style,start_mark,end_mark) \
562+ (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
563+ (event).data.sequence_start.anchor = (event_anchor), \
564+ (event).data.sequence_start.tag = (event_tag), \
565+ (event).data.sequence_start.implicit = (event_implicit), \
566+ (event).data.sequence_start.style = (event_style))
567+
568+#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
569+ (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
570+
571+#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
572+ event_implicit,event_style,start_mark,end_mark) \
573+ (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \
574+ (event).data.mapping_start.anchor = (event_anchor), \
575+ (event).data.mapping_start.tag = (event_tag), \
576+ (event).data.mapping_start.implicit = (event_implicit), \
577+ (event).data.mapping_start.style = (event_style))
578+
579+#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
580+ (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
581+
582+/*
583+ * Document initializer.
584+ */
585+
586+#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
587+ document_version_directive,document_tag_directives_start, \
588+ document_tag_directives_end,document_start_implicit, \
589+ document_end_implicit,document_start_mark,document_end_mark) \
590+ (memset(&(document), 0, sizeof(yaml_document_t)), \
591+ (document).nodes.start = (document_nodes_start), \
592+ (document).nodes.end = (document_nodes_end), \
593+ (document).nodes.top = (document_nodes_start), \
594+ (document).version_directive = (document_version_directive), \
595+ (document).tag_directives.start = (document_tag_directives_start), \
596+ (document).tag_directives.end = (document_tag_directives_end), \
597+ (document).start_implicit = (document_start_implicit), \
598+ (document).end_implicit = (document_end_implicit), \
599+ (document).start_mark = (document_start_mark), \
600+ (document).end_mark = (document_end_mark))
601+
602+/*
603+ * Node initializers.
604+ */
605+
606+#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
607+ (memset(&(node), 0, sizeof(yaml_node_t)), \
608+ (node).type = (node_type), \
609+ (node).tag = (node_tag), \
610+ (node).start_mark = (node_start_mark), \
611+ (node).end_mark = (node_end_mark))
612+
613+#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
614+ node_style,start_mark,end_mark) \
615+ (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
616+ (node).data.scalar.value = (node_value), \
617+ (node).data.scalar.length = (node_length), \
618+ (node).data.scalar.style = (node_style))
619+
620+#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
621+ node_style,start_mark,end_mark) \
622+ (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
623+ (node).data.sequence.items.start = (node_items_start), \
624+ (node).data.sequence.items.end = (node_items_end), \
625+ (node).data.sequence.items.top = (node_items_start), \
626+ (node).data.sequence.style = (node_style))
627+
628+#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
629+ node_style,start_mark,end_mark) \
630+ (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
631+ (node).data.mapping.pairs.start = (node_pairs_start), \
632+ (node).data.mapping.pairs.end = (node_pairs_end), \
633+ (node).data.mapping.pairs.top = (node_pairs_start), \
634+ (node).data.mapping.style = (node_style))
635+
636+#define YAML_VERSION_STRING "0.1.2"
637+#define YAML_VERSION_MAJOR 0
638+#define YAML_VERSION_MINOR 1
639+#define YAML_VERSION_PATCH 2
libyaml/ChangeLog.mddeleted−27
@@ -1,27 +0,0 @@
1−# Changelog for libyaml
2−
3−## 0.1.4
4−
5−* Use libyaml-clib for the cbits
6−* Use pkg-config to link to system yaml
7−
8−## 0.1.3
9−
10−* Correct signature for `fclose`
11−
12−## 0.1.2
13−
14−* Upgrade `libyaml` to 0.2.2
15−
16−## 0.1.1.1
17−
18−* Work around GHC 8.6.5 issue on Windows preventing truncated files. [#178](https://github.com/snoyberg/yaml/issues/178)
19−
20−## 0.1.1.0
21−
22−* Add options to `FormatOptions` to govern when tags rendered explicitly and when they are left implicit. [#165](https://github.com/snoyberg/yaml/issues/165)
23−
24−## 0.1.0.0
25−
26−* Split `libyaml` into a separate package from `yaml`. This split occurred at
27− `yaml` version 0.10.4.0.
libyaml/Makefiledeleted−4
@@ -1,4 +0,0 @@
1−libhelper.so : helper.o
2− gcc -shared -Wl,-soname,libhelper.so -o libhelper.so helper.o
3−helper.o : c/helper.c
4− gcc -c -fPIC c/helper.c -o helper.o
libyaml/README.mddeleted−3
@@ -1,3 +0,0 @@
1−# libyaml
2−
3−This package provides a haskell wrapper over the [libyaml C library version 0.2.2 by Kirill Simonov](https://github.com/yaml/libyaml). It contains the C source so you don't need to worry about any non-Haskell dependencies.
libyaml/Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
libyaml/libyaml.cabaldeleted−68
@@ -1,68 +0,0 @@
1−cabal-version: 1.12
2−
3−-- This file has been generated from package.yaml by hpack version 0.36.0.
4−--
5−-- see: https://github.com/sol/hpack
6−
7−name: libyaml
8−version: 0.1.4
9−synopsis: Low-level, streaming YAML interface.
10−description: README and API documentation are available at <https://www.stackage.org/package/libyaml>
11−category: Text
12−stability: stable
13−homepage: https://github.com/snoyberg/yaml#readme
14−bug-reports: https://github.com/snoyberg/yaml/issues
15−author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
16−maintainer: Michael Snoyman <michael@snoyman.com>
17−license: BSD3
18−license-file: LICENSE
19−build-type: Simple
20−extra-source-files:
21− include/helper.h
22− README.md
23− ChangeLog.md
24−
25−source-repository head
26− type: git
27− location: https://github.com/snoyberg/yaml
28−
29−flag no-unicode
30− description: Don't enable unicode output. Instead, unicode characters will be escaped.
31− manual: False
32− default: False
33−
34−flag system-libyaml
35− description: Use the system-wide libyaml instead of the bundled copy
36− manual: False
37− default: False
38−
39−library
40− exposed-modules:
41− Text.Libyaml
42− other-modules:
43− Paths_libyaml
44− hs-source-dirs:
45− src
46− ghc-options: -Wall
47− include-dirs:
48− include
49− c-sources:
50− c/helper.c
51− build-depends:
52− base >=4.9.1 && <5
53− , bytestring >=0.9.1.4
54− , conduit >=1.2.8 && <1.4
55− , resourcet >=0.3 && <1.4
56− default-language: Haskell2010
57− if flag(no-unicode)
58− cpp-options: -D__NO_UNICODE__
59− if !(flag(system-libyaml))
60− build-depends:
61− libyaml-clib
62− else
63− pkgconfig-depends:
64− yaml-0.1
65− if os(windows)
66− cpp-options: -DWINDOWS
67− build-depends:
68− directory
libyaml/package.yamldeleted−53
@@ -1,53 +0,0 @@
1−name: libyaml
2−version: 0.1.4
3−synopsis: Low-level, streaming YAML interface.
4−description: README and API documentation are available at <https://www.stackage.org/package/libyaml>
5−category: Text
6−author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
7−maintainer: Michael Snoyman <michael@snoyman.com>
8−license: BSD3
9−github: snoyberg/yaml
10−stability: stable
11−
12−extra-source-files:
13−- include/helper.h
14−- README.md
15−- ChangeLog.md
16−
17−flags:
18− system-libyaml:
19− description: Use the system-wide libyaml instead of the bundled copy
20− manual: false
21− default: false
22− no-unicode:
23− description: Don't enable unicode output. Instead, unicode characters will be escaped.
24− manual: false
25− default: false
26−
27−dependencies:
28−- base >=4.14 && <5 # GHC 8.10.1 and later
29−- bytestring >=0.9.1.4
30−- conduit >=1.2.8 && <1.4
31−- resourcet >=0.3 && <1.4
32−
33−library:
34− c-sources: c/helper.c
35− ghc-options: -Wall
36− include-dirs:
37− - include
38− source-dirs: src
39− when:
40− - condition: flag(no-unicode)
41− cpp-options: -D__NO_UNICODE__
42− - condition: ! '!(flag(system-libyaml))'
43− then:
44− dependencies:
45− - libyaml-clib
46− else:
47− pkg-config-dependencies:
48− - yaml-0.1
49− - condition: os(windows)
50− cpp-options: -DWINDOWS
51− dependencies:
52− - directory
53−
libyaml/src/Text/Libyaml.hsdeleted−856
@@ -1,856 +0,0 @@
1−{-# LANGUAGE EmptyDataDecls #-}
2−{-# LANGUAGE ForeignFunctionInterface #-}
3−{-# LANGUAGE DeriveDataTypeable #-}
4−{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE MultiParamTypeClasses #-}
7−{-# LANGUAGE RankNTypes #-}
8−{-# LANGUAGE CPP #-}
9−{-# LANGUAGE TypeFamilies #-}
10−{-# LANGUAGE ScopedTypeVariables #-}
11−
12−-- | Low-level, streaming YAML interface. For a higher-level interface, see
13−-- "Data.Yaml".
14−module Text.Libyaml
15− ( -- * The event stream
16− MarkedEvent(..)
17− , Event (..)
18− , Style (..)
19− , SequenceStyle (..)
20− , MappingStyle (..)
21− , Tag (..)
22− , AnchorName
23− , Anchor
24− -- * Encoding and decoding
25− , encode
26− , encodeWith
27− , decode
28− , decodeMarked
29− , encodeFile
30− , decodeFile
31− , decodeFileMarked
32− , encodeFileWith
33− , FormatOptions
34− , defaultFormatOptions
35− , setWidth
36− , setTagRendering
37− , renderScalarTags
38− , renderAllTags
39− , renderNoTags
40− , renderUriTags
41− -- * Error handling
42− , YamlException (..)
43− , YamlMark (..)
44− ) where
45−
46−import Prelude hiding (pi)
47−
48−import Data.Bits ((.|.))
49−import Foreign.C
50−import Foreign.Ptr
51−import Foreign.ForeignPtr
52−#if MIN_VERSION_base(4,7,0)
53−import Foreign.ForeignPtr.Unsafe
54−#endif
55−import Foreign.Marshal.Alloc
56−import qualified System.Posix.Internals as Posix
57−
58−#if !MIN_VERSION_base(4,8,0)
59−import Control.Applicative
60−#endif
61−import Control.Exception (mask_, throwIO, Exception, finally)
62−import Control.Monad
63−import Control.Monad.IO.Class
64−import Control.Monad.Trans.Resource
65−import Data.Conduit hiding (Source, Sink, Conduit)
66−import Data.Data
67−
68−import Data.ByteString (ByteString, packCString, packCStringLen)
69−import qualified Data.ByteString.Char8 as B8
70−import qualified Data.ByteString.Internal as B
71−import qualified Data.ByteString.Unsafe as BU
72−
73−#if WINDOWS && __GLASGOW_HASKELL__ >= 806
74−import System.Directory (removeFile)
75−import qualified Control.Exception
76−#endif
77−
78−data Event =
79− EventStreamStart
80− | EventStreamEnd
81− | EventDocumentStart
82− | EventDocumentEnd
83− | EventAlias !AnchorName
84− | EventScalar !ByteString !Tag !Style !Anchor
85− | EventSequenceStart !Tag !SequenceStyle !Anchor
86− | EventSequenceEnd
87− | EventMappingStart !Tag !MappingStyle !Anchor
88− | EventMappingEnd
89− deriving (Show, Eq)
90−
91−-- | Event with start and end marks.
92−--
93−-- @since 0.10.4.0
94−data MarkedEvent = MarkedEvent
95− { yamlEvent :: Event
96− , yamlStartMark :: YamlMark
97− , yamlEndMark :: YamlMark
98− }
99−
100−-- | Style for scalars - e.g. quoted / folded
101−--
102−data Style = Any
103− | Plain
104− | SingleQuoted
105− | DoubleQuoted
106− | Literal
107− | Folded
108− | PlainNoTag
109− deriving (Show, Read, Eq, Enum, Bounded, Ord, Data, Typeable)
110−
111−-- | Style for sequences - e.g. block or flow
112−--
113−-- @since 0.9.0
114−data SequenceStyle = AnySequence | BlockSequence | FlowSequence
115− deriving (Show, Eq, Enum, Bounded, Ord, Data, Typeable)
116−
117−-- | Style for mappings - e.g. block or flow
118−--
119−-- @since 0.9.0
120−data MappingStyle = AnyMapping | BlockMapping | FlowMapping
121− deriving (Show, Eq, Enum, Bounded, Ord, Data, Typeable)
122−
123−data Tag = StrTag
124− | FloatTag
125− | NullTag
126− | BoolTag
127− | SetTag
128− | IntTag
129− | SeqTag
130− | MapTag
131− | UriTag String
132− | NoTag
133− deriving (Show, Eq, Read, Data, Typeable)
134−
135−tagSuppressed :: Tag -> Bool
136−tagSuppressed (NoTag) = True
137−tagSuppressed (UriTag "") = True
138−tagSuppressed _ = False
139−
140−type AnchorName = String
141−type Anchor = Maybe AnchorName
142−
143−tagToString :: Tag -> String
144−tagToString StrTag = "tag:yaml.org,2002:str"
145−tagToString FloatTag = "tag:yaml.org,2002:float"
146−tagToString NullTag = "tag:yaml.org,2002:null"
147−tagToString BoolTag = "tag:yaml.org,2002:bool"
148−tagToString SetTag = "tag:yaml.org,2002:set"
149−tagToString IntTag = "tag:yaml.org,2002:int"
150−tagToString SeqTag = "tag:yaml.org,2002:seq"
151−tagToString MapTag = "tag:yaml.org,2002:map"
152−tagToString (UriTag s) = s
153−tagToString NoTag = ""
154−
155−bsToTag :: ByteString -> Tag
156−bsToTag = stringToTag . B8.unpack
157−
158−stringToTag :: String -> Tag
159−stringToTag "tag:yaml.org,2002:str" = StrTag
160−stringToTag "tag:yaml.org,2002:float" = FloatTag
161−stringToTag "tag:yaml.org,2002:null" = NullTag
162−stringToTag "tag:yaml.org,2002:bool" = BoolTag
163−stringToTag "tag:yaml.org,2002:set" = SetTag
164−stringToTag "tag:yaml.org,2002:int" = IntTag
165−stringToTag "tag:yaml.org,2002:seq" = SeqTag
166−stringToTag "tag:yaml.org,2002:map" = MapTag
167−stringToTag "" = NoTag
168−stringToTag s = UriTag s
169−
170−data ParserStruct
171−type Parser = Ptr ParserStruct
172−parserSize :: Int
173−parserSize = 480
174−
175−data EventRawStruct
176−type EventRaw = Ptr EventRawStruct
177−eventSize :: Int
178−eventSize = 104
179−
180−foreign import ccall unsafe "yaml_parser_initialize"
181− c_yaml_parser_initialize :: Parser -> IO CInt
182−
183−foreign import ccall unsafe "yaml_parser_delete"
184− c_yaml_parser_delete :: Parser -> IO ()
185−
186−foreign import ccall unsafe "yaml_parser_set_input_string"
187− c_yaml_parser_set_input_string :: Parser
188− -> Ptr CUChar
189− -> CULong
190− -> IO ()
191−
192−foreign import ccall unsafe "yaml_parser_set_input_file"
193− c_yaml_parser_set_input_file :: Parser
194− -> File
195− -> IO ()
196−
197−data MarkRawStruct
198−type MarkRaw = Ptr MarkRawStruct
199−
200−foreign import ccall unsafe "get_mark_index"
201− c_get_mark_index :: MarkRaw -> IO CULong
202−
203−foreign import ccall unsafe "get_mark_line"
204− c_get_mark_line :: MarkRaw -> IO CULong
205−
206−foreign import ccall unsafe "get_mark_column"
207− c_get_mark_column :: MarkRaw -> IO CULong
208−
209−getMark :: MarkRaw -> IO YamlMark
210−getMark m = YamlMark
211− <$> (fromIntegral <$> c_get_mark_index m)
212− <*> (fromIntegral <$> c_get_mark_line m)
213− <*> (fromIntegral <$> c_get_mark_column m)
214−
215−data FileStruct
216−type File = Ptr FileStruct
217−
218−#ifdef WINDOWS
219−foreign import ccall unsafe "_fdopen"
220−#else
221−foreign import ccall unsafe "fdopen"
222−#endif
223− c_fdopen :: CInt
224− -> Ptr CChar
225− -> IO File
226−foreign import ccall unsafe "fclose"
227− c_fclose :: File
228− -> IO CInt
229−
230−foreign import ccall unsafe "fclose_helper"
231− c_fclose_helper :: File -> IO CInt
232−
233−foreign import ccall unsafe "yaml_parser_parse"
234− c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
235−
236−foreign import ccall unsafe "yaml_event_delete"
237− c_yaml_event_delete :: EventRaw -> IO ()
238−
239−foreign import ccall "get_parser_error_problem"
240− c_get_parser_error_problem :: Parser -> IO (Ptr CUChar)
241−
242−foreign import ccall "get_parser_error_context"
243− c_get_parser_error_context :: Parser -> IO (Ptr CUChar)
244−
245−foreign import ccall unsafe "get_parser_error_mark"
246− c_get_parser_error_mark :: Parser -> IO MarkRaw
247−
248−makeString :: MonadIO m => (a -> m (Ptr CUChar)) -> a -> m String
249−makeString f a = do
250− cchar <- castPtr `liftM` f a
251− if cchar == nullPtr
252− then return ""
253− else liftIO $ peekCString cchar
254−
255−data EventType = YamlNoEvent
256− | YamlStreamStartEvent
257− | YamlStreamEndEvent
258− | YamlDocumentStartEvent
259− | YamlDocumentEndEvent
260− | YamlAliasEvent
261− | YamlScalarEvent
262− | YamlSequenceStartEvent
263− | YamlSequenceEndEvent
264− | YamlMappingStartEvent
265− | YamlMappingEndEvent
266− deriving (Enum,Show)
267−
268−foreign import ccall unsafe "get_event_type"
269− c_get_event_type :: EventRaw -> IO CInt
270−
271−foreign import ccall unsafe "get_start_mark"
272− c_get_start_mark :: EventRaw -> IO MarkRaw
273−
274−foreign import ccall unsafe "get_end_mark"
275− c_get_end_mark :: EventRaw -> IO MarkRaw
276−
277−foreign import ccall unsafe "get_scalar_value"
278− c_get_scalar_value :: EventRaw -> IO (Ptr CUChar)
279−
280−foreign import ccall unsafe "get_scalar_length"
281− c_get_scalar_length :: EventRaw -> IO CULong
282−
283−foreign import ccall unsafe "get_scalar_tag"
284− c_get_scalar_tag :: EventRaw -> IO (Ptr CUChar)
285−
286−foreign import ccall unsafe "get_scalar_style"
287− c_get_scalar_style :: EventRaw -> IO CInt
288−
289−foreign import ccall unsafe "get_scalar_anchor"
290− c_get_scalar_anchor :: EventRaw -> IO CString
291−
292−foreign import ccall unsafe "get_sequence_start_anchor"
293− c_get_sequence_start_anchor :: EventRaw -> IO CString
294−
295−foreign import ccall unsafe "get_sequence_start_style"
296− c_get_sequence_start_style :: EventRaw -> IO CInt
297−
298−foreign import ccall unsafe "get_sequence_start_tag"
299− c_get_sequence_start_tag :: EventRaw -> IO (Ptr CUChar)
300−
301−foreign import ccall unsafe "get_mapping_start_anchor"
302− c_get_mapping_start_anchor :: EventRaw -> IO CString
303−
304−foreign import ccall unsafe "get_mapping_start_style"
305− c_get_mapping_start_style :: EventRaw -> IO CInt
306−
307−foreign import ccall unsafe "get_mapping_start_tag"
308− c_get_mapping_start_tag :: EventRaw -> IO (Ptr CUChar)
309−
310−foreign import ccall unsafe "get_alias_anchor"
311− c_get_alias_anchor :: EventRaw -> IO CString
312−
313−readAnchor :: (EventRaw -> IO CString) -> EventRaw -> IO Anchor
314−readAnchor getAnchor er = do
315− yanchor <- getAnchor er
316− if yanchor == nullPtr
317− then return Nothing
318− else Just <$> peekCString yanchor
319−
320−readStyle :: (Enum a) => (EventRaw -> IO CInt) -> EventRaw -> IO a
321−readStyle getStyle er = toEnum . fromEnum <$> getStyle er
322−
323−readTag :: (EventRaw -> IO (Ptr CUChar)) -> EventRaw -> IO Tag
324−readTag getTag er = bsToTag <$> (getTag er >>= packCString . castPtr)
325−
326−getEvent :: EventRaw -> IO (Maybe MarkedEvent)
327−getEvent er = do
328− et <- c_get_event_type er
329− startMark <- c_get_start_mark er >>= getMark
330− endMark <- c_get_end_mark er >>= getMark
331− event <- case toEnum $ fromEnum et of
332− YamlNoEvent -> return Nothing
333− YamlStreamStartEvent -> return $ Just EventStreamStart
334− YamlStreamEndEvent -> return $ Just EventStreamEnd
335− YamlDocumentStartEvent -> return $ Just EventDocumentStart
336− YamlDocumentEndEvent -> return $ Just EventDocumentEnd
337− YamlAliasEvent -> do
338− yanchor <- c_get_alias_anchor er
339− anchor <- if yanchor == nullPtr
340− then error "got YamlAliasEvent with empty anchor"
341− else peekCString yanchor
342− return $ Just $ EventAlias anchor
343− YamlScalarEvent -> do
344− yvalue <- c_get_scalar_value er
345− ylen <- c_get_scalar_length er
346− let yvalue' = castPtr yvalue
347− let ylen' = fromEnum ylen
348− bs <- packCStringLen (yvalue', ylen')
349− tag <- readTag c_get_scalar_tag er
350− style <- readStyle c_get_scalar_style er
351− anchor <- readAnchor c_get_scalar_anchor er
352− return $ Just $ EventScalar bs tag style anchor
353− YamlSequenceStartEvent -> do
354− tag <- readTag c_get_sequence_start_tag er
355− style <- readStyle c_get_sequence_start_style er
356− anchor <- readAnchor c_get_sequence_start_anchor er
357− return $ Just $ EventSequenceStart tag style anchor
358− YamlSequenceEndEvent -> return $ Just EventSequenceEnd
359− YamlMappingStartEvent -> do
360− tag <- readTag c_get_mapping_start_tag er
361− style <- readStyle c_get_mapping_start_style er
362− anchor <- readAnchor c_get_mapping_start_anchor er
363− return $ Just $ EventMappingStart tag style anchor
364− YamlMappingEndEvent -> return $ Just EventMappingEnd
365− return $ (\e -> MarkedEvent e startMark endMark) <$> event
366−
367−-- Emitter
368−
369−data EmitterStruct
370−type Emitter = Ptr EmitterStruct
371−emitterSize :: Int
372−emitterSize = 432
373−
374−foreign import ccall unsafe "yaml_emitter_initialize"
375− c_yaml_emitter_initialize :: Emitter -> IO CInt
376−
377−foreign import ccall unsafe "yaml_emitter_delete"
378− c_yaml_emitter_delete :: Emitter -> IO ()
379−
380−data BufferStruct
381−type Buffer = Ptr BufferStruct
382−bufferSize :: Int
383−bufferSize = 16
384−
385−foreign import ccall unsafe "buffer_init"
386− c_buffer_init :: Buffer -> IO ()
387−
388−foreign import ccall unsafe "get_buffer_buff"
389− c_get_buffer_buff :: Buffer -> IO (Ptr CUChar)
390−
391−foreign import ccall unsafe "get_buffer_used"
392− c_get_buffer_used :: Buffer -> IO CULong
393−
394−foreign import ccall unsafe "my_emitter_set_output"
395− c_my_emitter_set_output :: Emitter -> Buffer -> IO ()
396−
397−#ifndef __NO_UNICODE__
398−foreign import ccall unsafe "yaml_emitter_set_unicode"
399− c_yaml_emitter_set_unicode :: Emitter -> CInt -> IO ()
400−#endif
401−
402−foreign import ccall unsafe "yaml_emitter_set_output_file"
403− c_yaml_emitter_set_output_file :: Emitter -> File -> IO ()
404−
405−foreign import ccall unsafe "yaml_emitter_set_width"
406− c_yaml_emitter_set_width :: Emitter -> CInt -> IO ()
407−
408−foreign import ccall unsafe "yaml_emitter_emit"
409− c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
410−
411−foreign import ccall unsafe "yaml_stream_start_event_initialize"
412− c_yaml_stream_start_event_initialize :: EventRaw -> CInt -> IO CInt
413−
414−foreign import ccall unsafe "yaml_stream_end_event_initialize"
415− c_yaml_stream_end_event_initialize :: EventRaw -> IO CInt
416−
417−foreign import ccall unsafe "yaml_scalar_event_initialize"
418− c_yaml_scalar_event_initialize
419− :: EventRaw
420− -> Ptr CUChar -- anchor
421− -> Ptr CUChar -- tag
422− -> Ptr CUChar -- value
423− -> CInt -- length
424− -> CInt -- plain_implicit
425− -> CInt -- quoted_implicit
426− -> CInt -- style
427− -> IO CInt
428−
429−foreign import ccall unsafe "simple_document_start"
430− c_simple_document_start :: EventRaw -> IO CInt
431−
432−foreign import ccall unsafe "yaml_document_end_event_initialize"
433− c_yaml_document_end_event_initialize :: EventRaw -> CInt -> IO CInt
434−
435−foreign import ccall unsafe "yaml_sequence_start_event_initialize"
436− c_yaml_sequence_start_event_initialize
437− :: EventRaw
438− -> Ptr CUChar
439− -> Ptr CUChar
440− -> CInt
441− -> CInt
442− -> IO CInt
443−
444−foreign import ccall unsafe "yaml_sequence_end_event_initialize"
445− c_yaml_sequence_end_event_initialize :: EventRaw -> IO CInt
446−
447−foreign import ccall unsafe "yaml_mapping_start_event_initialize"
448− c_yaml_mapping_start_event_initialize
449− :: EventRaw
450− -> Ptr CUChar
451− -> Ptr CUChar
452− -> CInt
453− -> CInt
454− -> IO CInt
455−
456−foreign import ccall unsafe "yaml_mapping_end_event_initialize"
457− c_yaml_mapping_end_event_initialize :: EventRaw -> IO CInt
458−
459−foreign import ccall unsafe "yaml_alias_event_initialize"
460− c_yaml_alias_event_initialize
461− :: EventRaw
462− -> Ptr CUChar
463− -> IO CInt
464−
465−toEventRaw :: FormatOptions -> Event -> (EventRaw -> IO a) -> IO a
466−toEventRaw opts e f = allocaBytes eventSize $ \er -> do
467− ret <- case e of
468− EventStreamStart ->
469− c_yaml_stream_start_event_initialize
470− er
471− 0 -- YAML_ANY_ENCODING
472− EventStreamEnd ->
473− c_yaml_stream_end_event_initialize er
474− EventDocumentStart ->
475− c_simple_document_start er
476− EventDocumentEnd ->
477− c_yaml_document_end_event_initialize er 1
478− EventScalar bs thetag style0 anchor -> do
479− BU.unsafeUseAsCStringLen bs $ \(value, len) -> do
480− let value' = castPtr value :: Ptr CUChar
481− len' = fromIntegral len :: CInt
482− let thetag' = tagToString thetag
483− withCString thetag' $ \tag' -> do
484− let pi0 = tagsImplicit e
485− (pi, style) =
486− case style0 of
487− PlainNoTag -> (1, Plain)
488− x -> (pi0, x)
489− style' = toEnum $ fromEnum style
490− tagP = castPtr tag'
491− case anchor of
492− Nothing ->
493− c_yaml_scalar_event_initialize
494− er
495− nullPtr -- anchor
496− tagP -- tag
497− value' -- value
498− len' -- length
499− pi -- plain_implicit
500− pi -- quoted_implicit
501− style' -- style
502− Just anchor' ->
503− withCString anchor' $ \anchorP' -> do
504− let anchorP = castPtr anchorP'
505− c_yaml_scalar_event_initialize
506− er
507− anchorP -- anchor
508− tagP -- tag
509− value' -- value
510− len' -- length
511− 0 -- plain_implicit
512− pi -- quoted_implicit
513− style' -- style
514− EventSequenceStart tag style Nothing ->
515− withCString (tagToString tag) $ \tag' -> do
516− let tagP = castPtr tag'
517− c_yaml_sequence_start_event_initialize
518− er
519− nullPtr
520− tagP
521− (tagsImplicit e)
522− (toEnum $ fromEnum style)
523− EventSequenceStart tag style (Just anchor) ->
524− withCString (tagToString tag) $ \tag' -> do
525− let tagP = castPtr tag'
526− withCString anchor $ \anchor' -> do
527− let anchorP = castPtr anchor'
528− c_yaml_sequence_start_event_initialize
529− er
530− anchorP
531− tagP
532− (tagsImplicit e)
533− (toEnum $ fromEnum style)
534− EventSequenceEnd ->
535− c_yaml_sequence_end_event_initialize er
536− EventMappingStart tag style Nothing ->
537− withCString (tagToString tag) $ \tag' -> do
538− let tagP = castPtr tag'
539− c_yaml_mapping_start_event_initialize
540− er
541− nullPtr
542− tagP
543− (tagsImplicit e)
544− (toEnum $ fromEnum style)
545− EventMappingStart tag style (Just anchor) ->
546− withCString (tagToString tag) $ \tag' -> do
547− withCString anchor $ \anchor' -> do
548− let tagP = castPtr tag'
549− let anchorP = castPtr anchor'
550− c_yaml_mapping_start_event_initialize
551− er
552− anchorP
553− tagP
554− (tagsImplicit e)
555− (toEnum $ fromEnum style)
556− EventMappingEnd ->
557− c_yaml_mapping_end_event_initialize er
558− EventAlias anchor ->
559− withCString anchor $ \anchorP' -> do
560− let anchorP = castPtr anchorP'
561− c_yaml_alias_event_initialize
562− er
563− anchorP
564− unless (ret == 1) $ throwIO $ ToEventRawException ret
565− f er
566− where
567− tagsImplicit (EventScalar _ t _ _) | tagSuppressed t = 1
568− tagsImplicit (EventMappingStart t _ _) | tagSuppressed t = 1
569− tagsImplicit (EventSequenceStart t _ _) | tagSuppressed t = 1
570− tagsImplicit evt = toImplicitParam $ formatOptionsRenderTags opts evt
571−
572−newtype ToEventRawException = ToEventRawException CInt
573− deriving (Show, Typeable)
574−instance Exception ToEventRawException
575−
576−-- | Create a conduit that yields events from a bytestring.
577−decode :: MonadResource m => B.ByteString -> ConduitM i Event m ()
578−decode = mapOutput yamlEvent . decodeMarked
579−
580−-- | Create a conduit that yields marked events from a bytestring.
581−--
582−-- This conduit will yield identical events to that of "decode", but also
583−-- includes start and end marks for each event.
584−--
585−-- @since 0.10.4.0
586−decodeMarked :: MonadResource m => B.ByteString -> ConduitM i MarkedEvent m ()
587−decodeMarked bs | B8.null bs = return ()
588−decodeMarked bs =
589− bracketP alloc cleanup (runParser . fst)
590− where
591− alloc = mask_ $ do
592− ptr <- mallocBytes parserSize
593− res <- c_yaml_parser_initialize ptr
594− if res == 0
595− then do
596− c_yaml_parser_delete ptr
597− free ptr
598− throwIO $ YamlException "Yaml out of memory"
599− else do
600− let (bsfptr, offset, len) = B.toForeignPtr bs
601− let bsptrOrig = unsafeForeignPtrToPtr bsfptr
602− let bsptr = castPtr bsptrOrig `plusPtr` offset
603− c_yaml_parser_set_input_string ptr bsptr (fromIntegral len)
604− return (ptr, bsfptr)
605− cleanup (ptr, bsfptr) = do
606− touchForeignPtr bsfptr
607− c_yaml_parser_delete ptr
608− free ptr
609−
610−-- XXX copied from GHC.IO.FD
611−std_flags, read_flags, output_flags, write_flags :: CInt
612−std_flags = Posix.o_NOCTTY
613−output_flags = std_flags .|. Posix.o_CREAT .|. Posix.o_TRUNC
614−read_flags = std_flags .|. Posix.o_RDONLY
615−write_flags = output_flags .|. Posix.o_WRONLY
616−
617−-- | Open a C FILE* from a file path, using internal GHC API to work correctly
618−-- on all platforms, even on non-ASCII filenames. The opening mode must be
619−-- indicated via both 'rawOpenFlags' and 'openMode'.
620−openFile :: FilePath -> CInt -> String -> IO File
621−openFile file rawOpenFlags openMode = do
622− fd <- liftIO $ Posix.withFilePath file $ \file' ->
623− Posix.c_open file' rawOpenFlags 0o666
624− if fd /= (-1)
625− then withCString openMode $ \openMode' -> c_fdopen fd openMode'
626− else return nullPtr
627−
628−-- | Creata a conduit that yields events from a file.
629−decodeFile :: MonadResource m => FilePath -> ConduitM i Event m ()
630−decodeFile = mapOutput yamlEvent . decodeFileMarked
631−
632−-- | Create a conduit that yields marked events from a file.
633−--
634−-- This conduit will yield identical events to that of "decodeFile", but also
635−-- includes start and end marks for each event.
636−--
637−-- @since 0.10.4.0
638−decodeFileMarked :: MonadResource m => FilePath -> ConduitM i MarkedEvent m ()
639−decodeFileMarked file =
640− bracketP alloc cleanup (runParser . fst)
641− where
642− alloc = mask_ $ do
643− ptr <- mallocBytes parserSize
644− res <- c_yaml_parser_initialize ptr
645− if res == 0
646− then do
647− c_yaml_parser_delete ptr
648− free ptr
649− throwIO $ YamlException "Yaml out of memory"
650− else do
651− file' <- openFile file read_flags "r"
652− if file' == nullPtr
653− then do
654− c_yaml_parser_delete ptr
655− free ptr
656− throwIO $ YamlException
657− $ "Yaml file not found: " ++ file
658− else do
659− c_yaml_parser_set_input_file ptr file'
660− return (ptr, file')
661− cleanup (ptr, file') = do
662− res <- c_fclose_helper file'
663− when (res /= 0) $ throwIO $ YamlException $ "could not close file: " ++ file
664− c_yaml_parser_delete ptr
665− free ptr
666−
667−runParser :: MonadResource m => Parser -> ConduitM i MarkedEvent m ()
668−runParser parser = do
669− e <- liftIO $ parserParseOne' parser
670− case e of
671− Left err -> liftIO $ throwIO err
672− Right Nothing -> return ()
673− Right (Just ev) -> yield ev >> runParser parser
674−
675−parserParseOne' :: Parser
676− -> IO (Either YamlException (Maybe MarkedEvent))
677−parserParseOne' parser = allocaBytes eventSize $ \er -> do
678− res <- liftIO $ c_yaml_parser_parse parser er
679− flip finally (c_yaml_event_delete er) $
680− if res == 0
681− then do
682− problem <- makeString c_get_parser_error_problem parser
683− context <- makeString c_get_parser_error_context parser
684− problemMark <- c_get_parser_error_mark parser >>= getMark
685− return $ Left $ YamlParseException problem context problemMark
686− else Right <$> getEvent er
687−
688−-- | Whether a tag should be rendered explicitly in the output or left
689−-- implicit.
690−--
691−-- @since 0.1.1.0
692−data TagRender = Explicit | Implicit
693− deriving (Enum)
694−
695−toImplicitParam :: TagRender -> CInt
696−toImplicitParam Explicit = 0
697−toImplicitParam Implicit = 1
698−
699−-- | A value for 'formatOptionsRenderTags' that renders no
700−-- collection tags but all scalar tags (unless suppressed with styles
701−-- 'NoTag or 'PlainNoTag').
702−--
703−-- @since 0.1.1.0
704−renderScalarTags :: Event -> TagRender
705−renderScalarTags (EventScalar _ _ _ _) = Explicit
706−renderScalarTags (EventSequenceStart _ _ _) = Implicit
707−renderScalarTags (EventMappingStart _ _ _) = Implicit
708−renderScalarTags _ = Implicit
709−
710−-- | A value for 'formatOptionsRenderTags' that renders all
711−-- tags (except 'NoTag' tag and 'PlainNoTag' style).
712−--
713−-- @since 0.1.1.0
714−renderAllTags :: Event -> TagRender
715−renderAllTags _ = Explicit
716−
717−-- | A value for 'formatOptionsRenderTags' that renders no
718−-- tags.
719−--
720−-- @since 0.1.1.0
721−renderNoTags :: Event -> TagRender
722−renderNoTags _ = Implicit
723−
724−-- | A value for 'formatOptionsRenderCollectionTags' that renders tags
725−-- which are instances of 'UriTag'
726−--
727−-- @since 0.1.1.0
728−renderUriTags :: Event -> TagRender
729−renderUriTags (EventScalar _ UriTag{} _ _) = Explicit
730−renderUriTags (EventSequenceStart UriTag{} _ _) = Explicit
731−renderUriTags (EventMappingStart UriTag{} _ _) = Explicit
732−renderUriTags _ = Implicit
733−
734−-- | Contains options relating to the formatting (indendation, width) of the YAML output.
735−--
736−-- @since 0.10.2.0
737−data FormatOptions = FormatOptions
738− { formatOptionsWidth :: Maybe Int
739− , formatOptionsRenderTags :: Event -> TagRender
740− }
741−
742−-- |
743−-- @since 0.10.2.0
744−defaultFormatOptions :: FormatOptions
745−defaultFormatOptions = FormatOptions
746− { formatOptionsWidth = Just 80 -- by default the width is set to 0 in the C code, which gets turned into 80 in yaml_emitter_emit_stream_start
747− , formatOptionsRenderTags = renderScalarTags
748− }
749−
750−-- | Set the maximum number of columns in the YAML output, or 'Nothing' for infinite. By default, the limit is 80 characters.
751−--
752−-- @since 0.10.2.0
753−setWidth :: Maybe Int -> FormatOptions -> FormatOptions
754−setWidth w opts = opts { formatOptionsWidth = w }
755−
756−-- | Control when and whether tags are rendered to output.
757−--
758−-- @since 0.1.1.0
759−setTagRendering :: (Event -> TagRender) -> FormatOptions -> FormatOptions
760−setTagRendering f opts = opts { formatOptionsRenderTags = f }
761−
762−encode :: MonadResource m => ConduitM Event o m ByteString
763−encode = encodeWith defaultFormatOptions
764−
765−-- |
766−-- @since 0.10.2.0
767−encodeWith :: MonadResource m => FormatOptions -> ConduitM Event o m ByteString
768−encodeWith opts =
769− runEmitter opts alloc close
770− where
771− alloc emitter = do
772− fbuf <- mallocForeignPtrBytes bufferSize
773− withForeignPtr fbuf c_buffer_init
774− withForeignPtr fbuf $ c_my_emitter_set_output emitter
775− return fbuf
776− close _ fbuf = withForeignPtr fbuf $ \b -> do
777− ptr' <- c_get_buffer_buff b
778− len <- c_get_buffer_used b
779− fptr <- newForeignPtr finalizerFree $ castPtr ptr'
780− return $ B.fromForeignPtr fptr 0 $ fromIntegral len
781−
782−
783−encodeFile :: MonadResource m
784− => FilePath
785− -> ConduitM Event o m ()
786−encodeFile = encodeFileWith defaultFormatOptions
787−
788−-- |
789−-- @since 0.10.2.0
790−encodeFileWith :: MonadResource m
791− => FormatOptions
792− -> FilePath
793− -> ConduitM Event o m ()
794−encodeFileWith opts filePath =
795− bracketP getFile cleanup $ \file -> runEmitter opts (alloc file) (\u _ -> return u)
796− where
797− cleanup file = do
798− res <- c_fclose file
799− when (res /= 0) $ throwIO $ YamlException $ "could not close file: " ++ filePath
800−
801− getFile = do
802−#if WINDOWS && __GLASGOW_HASKELL__ >= 806
803− -- See: https://github.com/snoyberg/yaml/issues/178#issuecomment-550180027
804− removeFile filePath `Control.Exception.catch`
805− (\(_ :: Control.Exception.IOException) -> pure ())
806−#endif
807− file <- openFile filePath write_flags "w"
808− if file == nullPtr
809− then throwIO $ YamlException $ "could not open file for write: " ++ filePath
810− else return file
811−
812− alloc file emitter = c_yaml_emitter_set_output_file emitter file
813−
814−runEmitter :: MonadResource m
815− => FormatOptions
816− -> (Emitter -> IO a) -- ^ alloc
817− -> (() -> a -> IO b) -- ^ close
818− -> ConduitM Event o m b
819−runEmitter opts allocI closeI =
820− bracketP alloc cleanup go
821− where
822− alloc = mask_ $ do
823− emitter <- mallocBytes emitterSize
824− res <- c_yaml_emitter_initialize emitter
825− when (res == 0) $ throwIO $ YamlException "c_yaml_emitter_initialize failed"
826−#ifndef __NO_UNICODE__
827− c_yaml_emitter_set_unicode emitter 1
828−#endif
829− c_yaml_emitter_set_width emitter $ case formatOptionsWidth opts of
830− Nothing -> -1 --infinite
831− Just width -> fromIntegral width
832− a <- allocI emitter
833− return (emitter, a)
834− cleanup (emitter, _) = do
835− c_yaml_emitter_delete emitter
836− free emitter
837−
838− go (emitter, a) =
839− loop
840− where
841− loop = await >>= maybe (close ()) push
842−
843− push e = do
844− _ <- liftIO $ toEventRaw opts e $ c_yaml_emitter_emit emitter
845− loop
846− close u = liftIO $ closeI u a
847−
848−-- | The pointer position
849−data YamlMark = YamlMark { yamlIndex :: Int, yamlLine :: Int, yamlColumn :: Int }
850− deriving Show
851−
852−data YamlException = YamlException String
853− -- | problem, context, index, position line, position column
854− | YamlParseException { yamlProblem :: String, yamlContext :: String, yamlProblemMark :: YamlMark }
855− deriving (Show, Typeable)
856−instance Exception YamlException
runtests.hsnew file+176
@@ -0,0 +1,176 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE PackageImports #-}
3+import Test.Framework (defaultMain)
4+
5+import Text.Libyaml
6+import qualified Data.ByteString.Char8 as B8
7+
8+import Test.Framework.Providers.HUnit
9+import Test.HUnit hiding (Test, path)
10+
11+import qualified Data.Enumerator as E
12+import Data.Enumerator (($$))
13+import Data.List (foldl')
14+
15+import System.Directory
16+import Control.Monad
17+
18+main :: IO ()
19+main = defaultMain
20+ [ testCase "count scalars with anchor" caseCountScalarsWithAnchor
21+ , testCase "count sequences with anchor" caseCountSequencesWithAnchor
22+ , testCase "count mappings with anchor" caseCountMappingsWithAnchor
23+ , testCase "count aliases" caseCountAliases
24+ , testCase "count scalars" caseCountScalars
25+ , testCase "largest string" caseLargestString
26+ , testCase "encode/decode" caseEncodeDecode
27+ , testCase "encode/decode file" caseEncodeDecodeFile
28+ , testCase "interleaved encode/decode" caseInterleave
29+ , testCase "decode invalid document (without segfault)" caseDecodeInvalidDocument
30+ ]
31+
32+counter :: (Event -> Bool) -> Int -> E.Step Event IO Int
33+counter pred' acc =
34+ E.Continue go
35+ where
36+ go E.EOF = E.yield acc E.EOF
37+ go (E.Chunks c) = E.returnI $ counter pred' $ length (filter pred' c) + acc
38+
39+caseHelper :: String
40+ -> (Event -> Bool)
41+ -> Int
42+ -> Assertion
43+caseHelper yamlString pred' expRes = do
44+ Right res <- E.run $ decode (B8.pack yamlString) (counter pred' 0)
45+ res @?= expRes
46+
47+caseCountScalarsWithAnchor :: Assertion
48+caseCountScalarsWithAnchor =
49+ caseHelper yamlString isScalarA 1
50+ where
51+ yamlString = "foo:\n - &anchor bin1\n - bin2\n - bin3"
52+ isScalarA (EventScalar _ _ _ (Just _)) = True
53+ isScalarA _ = False
54+
55+caseCountSequencesWithAnchor :: Assertion
56+caseCountSequencesWithAnchor =
57+ caseHelper yamlString isSequenceStartA 1
58+ where
59+ yamlString = "foo: &anchor\n - bin1\n - bin2\n - bin3"
60+ isSequenceStartA (EventSequenceStart (Just _)) = True
61+ isSequenceStartA _ = False
62+
63+caseCountMappingsWithAnchor :: Assertion
64+caseCountMappingsWithAnchor =
65+ caseHelper yamlString isMappingA 1
66+ where
67+ yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3"
68+ isMappingA (EventMappingStart (Just _)) = True
69+ isMappingA _ = False
70+
71+caseCountAliases :: Assertion
72+caseCountAliases =
73+ caseHelper yamlString isAlias 1
74+ where
75+ yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3\nboo: *anchor"
76+ isAlias EventAlias{} = True
77+ isAlias _ = False
78+
79+caseCountScalars :: Assertion
80+caseCountScalars = do
81+ Right res <- E.run $ decode yamlBS $ counter' accum
82+ res @?= (7, 1, 2)
83+ where
84+ yamlString = "foo:\n baz: [bin1, bin2, bin3]\nbaz: bazval"
85+ yamlBS = B8.pack yamlString
86+ counter' acc = E.Continue $ \s ->
87+ case s of
88+ E.EOF -> E.yield acc E.EOF
89+ E.Chunks c -> E.returnI $ counter' $ foldl' adder acc c
90+ adder (s, l, m) (EventScalar{}) = (s + 1, l, m)
91+ adder (s, l, m) (EventSequenceStart{}) = (s, l + 1, m)
92+ adder (s, l, m) (EventMappingStart{}) = (s, l, m + 1)
93+ adder a _ = a
94+ accum = (0, 0, 0) :: (Int, Int, Int)
95+
96+caseLargestString :: Assertion
97+caseLargestString = do
98+ Right res <- E.run $ decodeFile filePath $ dec accum
99+ res @?= (length expected, expected)
100+ where
101+ expected = "this one is just a little bit bigger than the others"
102+ filePath = "test/largest-string.yaml"
103+ dec acc = E.Continue $ \s ->
104+ case s of
105+ E.EOF -> E.yield acc E.EOF
106+ E.Chunks c ->
107+ let acc' = foldl' adder acc c
108+ in E.returnI $ dec acc'
109+ adder (i, s) (EventScalar bs _ _ _) =
110+ let s' = B8.unpack bs
111+ i' = length s'
112+ in if i' > i then (i', s') else (i, s)
113+ adder acc _ = acc
114+ accum = (0, "no strings found")
115+
116+newtype MyEvent = MyEvent Event deriving Show
117+instance Eq MyEvent where
118+ (MyEvent (EventScalar s t _ _)) == (MyEvent (EventScalar s' t' _ _)) =
119+ s == s' && t == t'
120+ MyEvent e1 == MyEvent e2 = e1 == e2
121+
122+caseEncodeDecode :: Assertion
123+caseEncodeDecode = do
124+ Right eList <- E.run $ decode yamlBS $$ E.consume
125+ Right bs <- E.run $ E.enumList 1 eList $$ encode
126+ Right eList2 <- E.run $ decode bs $$ E.consume
127+ map MyEvent eList @=? map MyEvent eList2
128+ where
129+ yamlString = "foo: bar\nbaz:\n - bin1\n - bin2\n"
130+ yamlBS = B8.pack yamlString
131+
132+removeFile' :: FilePath -> IO ()
133+removeFile' fp = do
134+ x <- doesFileExist fp
135+ when x $ removeFile fp
136+
137+caseEncodeDecodeFile :: Assertion
138+caseEncodeDecodeFile = do
139+ removeFile' tmpPath
140+ Right eList <- E.run $ decodeFile filePath $$ E.consume
141+ E.run $ E.enumList 1 eList $$ encodeFile tmpPath
142+ Right eList2 <- E.run $ decodeFile filePath $$ E.consume
143+ map MyEvent eList @=? map MyEvent eList2
144+ where
145+ filePath = "test/largest-string.yaml"
146+ tmpPath = "tmp.yaml"
147+
148+caseInterleave :: Assertion
149+caseInterleave = do
150+ removeFile' tmpPath
151+ removeFile' tmpPath2
152+ Right () <- E.run $ decodeFile filePath $$ encodeFile tmpPath
153+ Right () <- E.run $ decodeFile tmpPath $$ encodeFile tmpPath2
154+ f1 <- readFile tmpPath
155+ f2 <- readFile tmpPath2
156+ f1 @=? f2
157+ where
158+ filePath = "test/largest-string.yaml"
159+ tmpPath = "tmp.yaml"
160+ tmpPath2 = "tmp2.yaml"
161+
162+caseDecodeInvalidDocument :: Assertion
163+caseDecodeInvalidDocument = do
164+ x <- E.run $ decode yamlBS ignore
165+ case x of
166+ Left _ -> return ()
167+ Right y -> do
168+ putStrLn $ "bad return value: " ++ show y
169+ assertFailure "expected parsing exception, but got no errors"
170+ where
171+ yamlString = " - foo\n - baz\nbuz"
172+ yamlBS = B8.pack yamlString
173+ ignore = E.Continue $ \s ->
174+ case s of
175+ E.EOF -> E.yield () E.EOF
176+ E.Chunks _-> E.returnI ignore
stack.yamldeleted−12
@@ -1,12 +0,0 @@
1−resolver: lts-22.13
2−
3−flags:
4− yaml:
5− no-examples: false
6−
7−packages:
8− - yaml
9− - libyaml
10−
11−extra-deps:
12− - libyaml-clib-0.2.5
yaml/test/largest-string.yaml → test/largest-string.yamlrenamed

The content is the same.

yaml.cabalnew file+74
@@ -0,0 +1,74 @@
1+name: yaml
2+version: 0.4.0
3+license: BSD3
4+license-file: LICENSE
5+author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>
6+maintainer: Michael Snoyman <michael@snoyman.com>
7+synopsis: Low-level binding to the libyaml C library.
8+description: Provides support for parsing and emitting Yaml documents. Includes the full C library in the package so you don't need to worry about any non-Haskell dependencies.
9+category: Web
10+stability: unstable
11+cabal-version: >= 1.2
12+build-type: Simple
13+homepage: http://github.com/snoyberg/yaml/
14+extra-source-files: c/helper.h,
15+ c/yaml_private.h,
16+ c/yaml.h
17+
18+flag nolib
19+ description: Skip building the library
20+ default: False
21+flag buildtests
22+ description: Build the executable to run unit tests
23+ default: False
24+
25+library
26+ if flag(nolib)
27+ Buildable: False
28+ else
29+ Buildable: True
30+ build-depends: base >= 4 && < 5
31+ , transformers >= 0.1 && < 0.3
32+ , bytestring >= 0.9.1.4 && < 0.10
33+ , enumerator >= 0.4 && < 0.5
34+ , MonadCatchIO-transformers >= 0.2.2 && < 0.3
35+ exposed-modules: Text.Libyaml
36+ ghc-options: -Wall
37+ c-sources: c/helper.c,
38+ c/api.c,
39+ c/dumper.c,
40+ c/emitter.c,
41+ c/loader.c,
42+ c/parser.c,
43+ c/reader.c,
44+ c/scanner.c,
45+ c/writer.c
46+ include-dirs: c
47+
48+executable runtests
49+ if flag(buildtests)
50+ Buildable: True
51+ cpp-options: -DTEST
52+ build-depends: test-framework
53+ , test-framework-hunit
54+ , HUnit
55+ , directory
56+ , base >= 4 && < 5
57+ , transformers >= 0.1 && < 0.3
58+ , bytestring >= 0.9.1.4 && < 0.10
59+ , enumerator >= 0.4 && < 0.5
60+ , MonadCatchIO-transformers >= 0.2.2 && < 0.3
61+ else
62+ Buildable: False
63+ ghc-options: -Wall
64+ c-sources: c/helper.c,
65+ c/api.c,
66+ c/dumper.c,
67+ c/emitter.c,
68+ c/loader.c,
69+ c/parser.c,
70+ c/reader.c,
71+ c/scanner.c,
72+ c/writer.c
73+ include-dirs: c
74+ main-is: runtests.hs
yaml/ChangeLog.mddeleted−303
@@ -1,303 +0,0 @@
1−# ChangeLog for yaml
2−
3−## 0.11.11.2
4−
5−* Compat with aeson 2.2
6−
7−## 0.11.11.1
8−
9−* For optparse-applicative-0.18: use `pretty` instead of `text` [#216](https://github.com/snoyberg/yaml/pull/216)
10−
11−## 0.11.11.0
12−
13−* Fix ambiguous occurrence `AesonException`
14−
15−## 0.11.10.0
16−
17−* Undo previous change (breakage with aeson 2)
18−
19−## 0.11.9.0
20−
21−* Data.Yaml.Pretty: provide key-sorting function with path to parent object [#206](https://github.com/snoyberg/yaml/pull/206)
22−
23−## 0.11.8.0
24−
25−* Export `Parse` and `StringStyle` [#204](https://github.com/snoyberg/yaml/pull/204)
26−
27−## 0.11.7.0
28−
29−* Support `aeson` 2 [#202](https://github.com/snoyberg/yaml/pull/202)
30−
31−## 0.11.6.0
32−
33−* `yaml2json`: add `--help` and `--version` options [#197](https://github.com/snoyberg/yaml/pull/197)
34−* `json2yaml`: add `--help` and `--version` options [#198](https://github.com/snoyberg/yaml/pull/198)
35−* Add the `-o` options to both `yaml2json` and `json2yaml` [#200](https://github.com/snoyberg/yaml/pull/200)
36−
37−## 0.11.5.0
38−
39−* New functions capable of parsing YAML streams containing multiple documents into a list of results:
40− * `decodeAllEither'`
41− * `decodeAllFileEither`
42− * `decodeAllFileWithWarnings`
43− * `decodeAllThrow`
44− * `decodeAllFileThrow`
45−
46−## 0.11.4.0
47−
48−* add `ToYaml` instance for `String` [#186](https://github.com/snoyberg/yaml/pull/186)
49−
50−## 0.11.3.0
51−
52−* Don't wrap up async exceptions [#185](https://github.com/snoyberg/yaml/issues/185)
53−
54−## 0.11.2.0
55−
56−* Reduces some of the code duplication between the `encode` and `encodePretty` functions
57−* The output of `encodePretty` has been improved:
58− - Multiline strings now use `Literal` style instead of `SingleQuoted`
59− - Special keys are now quoted in mappings [#179](https://github.com/snoyberg/yaml/issues/179)
60−* Support for complex keys in mappings: [#182](https://github.com/snoyberg/yaml/issues/182)
61− - Adds `complexMapping` function to `Data.Yaml.Builder`
62− - Decode functions now return a `NonStringKey` error when attempting to decode a mapping with a complex key as it is not possible to decode these to an Aeson `Value`
63−* Adds missing `ToYaml` instances
64−
65−## 0.11.1.2
66−
67−* Compiles with GHC 8.8.1 (`MonadFail` split)
68−
69−## 0.11.1.1
70−
71−* Use the appropriate `Scientific` rendering function to avoid a memory overflow when rendering. The previously used function from `aeson` would not use scientific notation, and could use large amounts of memory for values such as `1e9999999999999`.
72−
73−## 0.11.1.0
74−
75−* Better error messages in the `Data.Yaml.Config` module [#168](https://github.com/snoyberg/yaml/issues/168)
76−* Add `LoadSettingsException` exception and remove error printing from `loadYamlSettings` [#172](https://github.com/snoyberg/yaml/pull/172)
77−
78−## 0.11.0.0
79−
80−* Split out the `libyaml` and `Text.Libyaml` code into its own package. [#145](https://github.com/snoyberg/yaml/issues/145)
81−
82−## 0.10.4.0
83−
84−* Add `decodeMarked` and `decodeFileMarked` functions to `Text.Libyaml`, and
85− extend native bindings to extract mark information. [#157](https://github.com/snoyberg/yaml/issues/157)
86−
87−## 0.10.3.0
88−
89−* Add support for anchors and aliases to Data.Yaml.Builder [#155](https://github.com/snoyberg/yaml/pull/155)
90−* Fix test suite for 32 bit machines [#158](https://github.com/snoyberg/yaml/issues/158)
91−
92−## 0.10.2.0
93−
94−* Add `EncodeOptions` and `FormatOptions` to control the style of the encoded YAML. [#153](https://github.com/snoyberg/yaml/pull/153)
95−* Default to using literal style for multiline strings [#152](https://github.com/snoyberg/yaml/issues/152)
96−
97−## 0.10.1.1
98−
99−* Correctly declare libyaml dependency on system-libyaml flag [#151](https://github.com/snoyberg/yaml/pull/151)
100−
101−## 0.10.1
102−
103−* Avoid incurring a `semigroups` dependency on recent GHCs.
104−* Fix a space leak that was introduced with `0.10.0` [#147](https://github.com/snoyberg/yaml/issues/147)
105−
106−## 0.10.0
107−
108−* Add `decodeFileWithWarnings` which returns warnings for duplicate fields
109−
110−## 0.9.0
111−
112−* Expose style and tags on mappings and sequences in Text.Libyaml [#141](https://github.com/snoyberg/yaml/pull/141)
113−
114−## 0.8.32
115−
116−* Escape keys as necessary [#137](https://github.com/snoyberg/yaml/issues/137)
117−* Support hexadecimal and octal number values [#135](https://github.com/snoyberg/yaml/issues/135)
118−* More resilient `isNumeric` (should reduce cases of unneeded quoting)
119−* hpackify
120−* src subdir
121−
122−## 0.8.31.1
123−
124−* Add a workaround for a cabal bug [haskell-infra/hackage-trustees#165](https://github.com/haskell-infra/hackage-trustees/issues/165)
125−
126−## 0.8.31
127−
128−* Add `decodeThrow` and `decodeFileThrow` convenience functions.
129−* Upgrade libyaml versions
130−* Deprecate `decode` and `decodeEither`
131−
132−## 0.8.30
133−
134−* Removed `AppSettings` mentioned in `loadYamlSettings` error message.
135−
136−## 0.8.29
137−
138−* Deprecated `decodeFile` [#129](https://github.com/snoyberg/yaml/issues/129)
139−* Turn off executables by default [#103](https://github.com/snoyberg/yaml/issues/103)
140−
141−## 0.8.28
142−
143−* Add `Data.Yaml.TH.yamlQQ`
144−
145−## 0.8.27
146−
147−* Support conduit 1.3
148−
149−## 0.8.26
150−
151−* Add `Semigroup` instance [#123](https://github.com/snoyberg/yaml/pull/123)
152−
153−## 0.8.25.2
154−
155−* Use `throwM` instead of `monadThrow`
156−
157−## 0.8.25.1
158−
159−* Drop aeson-qq dep (incompatible with Stackage Nightly)
160−
161−## 0.8.25
162−
163−* Tweaks to the executable `yaml2json` [#119](https://github.com/snoyberg/yaml/pull/119):
164− - Add command-line option `-h` and `--help` to show help message
165− - Error messages are now written to `stderr` instead of `stdout`
166−
167−## 0.8.24
168−
169−* New encodePretty option `setConfDropNull` to drop null values from objects [#116](https://github.com/snoyberg/yaml/issues/116)
170−
171−## 0.8.23.3
172−
173−* Avoid over-escaping `*` [#113](https://github.com/snoyberg/yaml/issues/113)
174−
175−## 0.8.23.2
176−
177−* Update libyaml [#110](https://github.com/snoyberg/yaml/issues/110)
178−
179−## 0.8.23.1
180−
181−* Update CPP `MIN_VERSION_*` checks [#109](https://github.com/snoyberg/yaml/pull/109)
182−
183−## 0.8.23
184−
185−* Re-export the with helpers from aeson
186−
187−## 0.8.22.1
188−
189−* Make numeric string detection slightly smarter so, e.g., `.` does
190− not get quoted
191−
192−## 0.8.22
193−
194−* Update to libyaml hosted on Github [#105](https://github.com/snoyberg/yaml/issues/105)
195−
196−## 0.8.21.2
197−
198−* Fix wrong file not found exception in `Data.Yaml.Include` with pre-1.2.3.0 `directory` [#104](https://github.com/snoyberg/yaml/pull/104)
199−
200−## 0.8.21.1
201−
202−* Add missing test files [#102](https://github.com/snoyberg/yaml/pull/102)
203−
204−## 0.8.21
205−
206−* Decode empty inputs as Null [#101](https://github.com/snoyberg/yaml/pull/101)
207−
208−## 0.8.20
209−
210−* Upgrade to libyaml 0.1.7
211−
212−## 0.8.19.0
213−
214−* Add `Data.Yaml.TH` module
215−
216−## 0.8.18.7
217−
218−* Add `O_TRUNC` when opening files
219−
220−## 0.8.18.6
221−
222−* s/fdopen/_fdopen on Windows [#96](https://github.com/snoyberg/yaml/issues/96)
223−
224−## 0.8.18.5
225−
226−* Properly fix previous bug (fixes #94)
227−
228−## 0.8.18.4
229−
230−* Remove file with non-ASCII name due to Stack/cabal-install/Hackage
231− restrictions (see [#92](https://github.com/snoyberg/yaml/issues/92))
232−
233−## 0.8.18.2
234−
235−* Handle non-ASCII filenames correctly on Windows [#91](https://github.com/snoyberg/yaml/pull/91)
236−
237−## 0.8.18.1
238−
239−* Improve prettyPrintParseException when context is empty [#89](https://github.com/snoyberg/yaml/pull/89)
240−
241−## 0.8.18
242−
243−* Switched yaml decode function for config file readers in `Data.Yaml.Config` to
244− the one from `Data.Yaml.Include` that supports `!include` syntax.
245−
246−## 0.8.17.2
247−
248−* Fix pretty-printing order of UnexpectedEvent's fields (fixes [#84](https://github.com/snoyberg/yaml/issues/84)) [#85](https://github.com/snoyberg/yaml/pull/85)
249−
250−## 0.8.17.1
251−
252−* Avoid bug in Cabal [#83](https://github.com/snoyberg/yaml/pull/83)
253−
254−## 0.8.17
255−
256−* `loadYamlSettingsArgs`
257−
258−## 0.8.16.1
259−
260−* Slight doc improvement
261−
262−## 0.8.16
263−
264−Add env variable parsing. `loadYamlSettings` can read config values from the environment with Yaml that specifies an env var.
265−The syntax is
266−
267−`var: _env:ENV_VAR:default`
268−
269−## 0.8.15.3
270−
271−* Give a warning when compiling with GHCJS
272−
273−## 0.8.15.2
274−
275−* Canonicalise Monad instances [#76](https://github.com/snoyberg/yaml/pull/76)
276−
277−## 0.8.15.1
278−
279−* Compile with aeson below 0.7 [#70](https://github.com/snoyberg/yaml/pull/70)
280−
281−## 0.8.15
282−
283−* Parse `Scientific` directly, avoiding loss in precision. [#68](https://github.com/snoyberg/yaml/pull/68)
284−
285−## 0.8.14
286−
287−* Pretty print improvements for exceptions [#67](https://github.com/snoyberg/yaml/pull/67)
288−
289−## 0.8.13
290−
291−* Pretty module [#66](https://github.com/snoyberg/yaml/pull/66)
292−
293−## 0.8.12
294−
295−* Proper handling of `String "+123"` [#64](https://github.com/snoyberg/yaml/issues/64)
296−
297−## 0.8.11
298−
299−* Function to print prettier parse exceptions [#59](https://github.com/snoyberg/yaml/pull/59)
300−
301−## 0.8.10
302−
303−Add the Data.Yaml.Include module
yaml/LICENSEdeleted−25
@@ -1,25 +0,0 @@
1−The following license covers this documentation, and the source code, except
2−where otherwise indicated.
3−
4−Copyright 2008, Michael Snoyman. All rights reserved.
5−
6−Redistribution and use in source and binary forms, with or without
7−modification, are permitted provided that the following conditions are met:
8−
9−* Redistributions of source code must retain the above copyright notice, this
10− list of conditions and the following disclaimer.
11−
12−* Redistributions in binary form must reproduce the above copyright notice,
13− this list of conditions and the following disclaimer in the documentation
14− and/or other materials provided with the distribution.
15−
16−THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
17−IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18−MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19−EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
20−INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21−NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22−OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23−LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24−OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25−ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
yaml/README.mddeleted−26
@@ -1,26 +0,0 @@
1−## yaml
2−
3−[![GitHub build and test status](https://github.com/snoyberg/yaml/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/snoyberg/yaml/actions/workflows/tests.yml)
4−[![Appveyor build status](https://ci.appveyor.com/api/projects/status/hqy2jketp8m502so/branch/master?svg=true)](https://ci.appveyor.com/project/snoyberg/yaml/branch/master)
5−
6−Provides support for parsing and emitting Yaml documents.
7−
8−`Data.Yaml` provides a high-level interface based around the JSON datatypes provided by the `aeson` package. It uses `Text.Libyaml` from `libyaml` in its implementation of the low-level yaml encoder/decoder.
9−
10−### Examples
11−
12−Usage examples can be found in the `Data.Yaml` documentation or in the [examples](https://github.com/snoyberg/yaml/tree/master/yaml/examples) directory.
13−
14−### Additional `yaml` modules
15−
16−* `Data.Yaml.Include` supports adding `!include` directives to your YAML files.
17−* `Data.Yaml.Builder` and `Data.Yaml.Parser` allow more fine-grained control of parsing an rendering, as opposed to just using the aeson typeclass and datatype system for parsing and rendering.
18−* `Data.Yaml.Aeson` is currently a re-export of `Data.Yaml` to explicitly choose to use the aeson-compatible API.
19−
20−### Executables
21−
22−Converters `json2yaml` and `yaml2json` can be built by disabling flag `no-exe`, e.g., one of:
23−```
24−cabal install yaml -f-no-exe
25−stack install yaml --flag yaml:-no-exe
26−```
yaml/builder-test.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−import Data.Yaml.Builder
3−import qualified Data.ByteString as S
4−import Data.Text (Text)
5−
6−data Person = Person
7− { name :: !Text
8− , age :: !Int
9− }
10−instance ToYaml Person where
11− toYaml (Person n a) = mapping
12− [ "name" .= n
13− , "age" .= a
14− ]
15−
16−main :: IO ()
17−main = do
18− S.putStr $ toByteString
19− [ Person "Alice" 57
20− , Person "Bob" 23
21− , Person "12345" 23
22− ]
23− writeYamlFile "/tmp/foo.yaml" $
24− [ Person "Alice" 57
25− , Person "Bob" 23
26− , Person "12345" 23
27− ]
yaml/examples/Config.hsdeleted−55
@@ -1,55 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE QuasiQuotes #-}
3−
4−module Config where
5−
6−import Data.Text (Text)
7−import qualified Data.Yaml as Y
8−import Data.Yaml (FromJSON(..), (.:))
9−import Text.RawString.QQ
10−import Data.ByteString (ByteString)
11−import Control.Applicative
12−import Prelude -- Ensure Applicative is in scope and we have no warnings, before/after AMP.
13−
14−configYaml :: ByteString
15−configYaml = [r|
16−resolver: lts-3.7
17−packages:
18− - ./yesod-core
19− - ./yesod-static
20− - ./yesod-persistent
21− - ./yesod-newsfeed
22− - ./yesod-form
23− - ./yesod-auth
24− - ./yesod-auth-oauth
25− - ./yesod-sitemap
26− - ./yesod-test
27− - ./yesod-bin
28− - ./yesod
29− - ./yesod-eventsource
30− - ./yesod-websockets
31−
32−# Needed for LTS 2
33−extra-deps:
34−- wai-app-static-3.1.4.1
35−|]
36−
37−data Config =
38− Config {
39− resolver :: Text
40− , packages :: [FilePath]
41− , extraDeps :: [Text]
42− } deriving (Eq, Show)
43−
44−instance FromJSON Config where
45− parseJSON (Y.Object v) =
46− Config <$>
47− v .: "resolver" <*>
48− v .: "packages" <*>
49− v .: "extra-deps"
50− parseJSON _ = fail "Expected Object for Config value"
51−
52−main :: IO ()
53−main = do
54− config <- Y.decodeThrow configYaml
55− print (config :: Config)
yaml/examples/Main.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Main where
2−
3−import qualified Config
4−import qualified Simple
5−
6−main :: IO ()
7−main = do
8− Simple.main
9− Config.main
10−
yaml/examples/Simple.hsdeleted−14
@@ -1,14 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module Simple where
4−
5−import qualified Data.Yaml as Y
6−
7−main :: IO ()
8−main = do
9− res <- Y.decodeThrow "[1,2,3]"
10− print (res :: [Integer])
11−
12−-- You can go one step further and decode into a custom type by implementing
13−-- 'FromJSON' for that type. This is also appropriate where extra
14−-- normalization, formatting or manipulation of the YAML is required on decode.
yaml/exe/Common.hsdeleted−68
@@ -1,68 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
3−
4−-- | Code shared between @yaml2json@ and @json2yaml@.
5−
6−module Common where
7−
8−import Data.List ( intercalate )
9−#if !MIN_VERSION_base(4,11,0)
10−import Data.Semigroup ( Semigroup(..) )
11−#endif
12−import Data.Version ( Version(versionBranch) )
13−
14−import Options.Applicative ( Parser, help, hidden, infoOption, long, short )
15−
16−import qualified Paths_yaml as Paths
17−
18−-- * Version info and option
19−---------------------------------------------------------------------------
20−
21−-- | Homepage for @yaml2json@ and @json2yaml@.
22−
23−homepage :: String
24−homepage = "https://github.com/snoyberg/yaml/"
25−
26−-- | Version in @x.y.z@ format.
27−
28−version :: String
29−version = intercalate "." $ map show $ versionBranch Paths.version
30−
31−-- | The version header including given program name and 'homepage'.
32−
33−versionText :: String -> String
34−versionText self = unwords
35− [ self
36− , "version"
37− , version
38− , homepage -- concat [ "<", homepage, ">" ]
39− ]
40−
41−-- | Option @--numeric-version@.
42−
43−numericVersionOption :: Parser (a -> a)
44−numericVersionOption =
45− infoOption version
46− $ long "numeric-version"
47− <> hidden
48− <> help "Show just version number."
49−
50−-- | Option @--version@.
51−
52−versionOption :: String -> Parser (a -> a)
53−versionOption self =
54− infoOption (versionText self)
55− $ long "version"
56− <> short 'V'
57− <> hidden
58− <> help "Show version info."
59−
60−-- * Misc
61−---------------------------------------------------------------------------
62−
63−-- | @Just@ unless argument is @"-"@ (denoting @stdin@ or @stdout@).
64−
65−dashToNothing :: FilePath -> Maybe FilePath
66−dashToNothing = \case
67− "-" -> Nothing
68− file -> Just file
yaml/exe/json2yaml.hsdeleted−106
@@ -1,106 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE NamedFieldPuns #-}
3−
4−import qualified Data.Aeson as J
5−import qualified Data.ByteString as S
6−import qualified Data.ByteString.Lazy as L
7−import qualified Data.Yaml as Y
8−#if !MIN_VERSION_base(4,11,0)
9−import Data.Semigroup ( Semigroup(..) )
10−#endif
11−
12−import Options.Applicative
13− ( Parser, (<|>)
14− , action, execParser, footerDoc, headerDoc, help, helper, hidden, info
15− , long, metavar, short, strArgument, strOption, value
16− )
17−import Options.Applicative.Help.Pretty
18− ( vcat, pretty )
19−
20−import System.Exit ( die )
21−
22−import Common ( dashToNothing, versionText, versionOption, numericVersionOption )
23−
24−data Options = Options
25− { optInput :: Maybe FilePath
26− -- ^ 'Nothing' means @stdin@.
27− , optOutput :: Maybe FilePath
28− -- ^ 'Nothing' means @stdout@.
29− }
30−
31−-- | Name of the executable.
32−
33−self :: String
34−self = "json2yaml"
35−
36−-- | Parse options; handle parse errors, @--help@, @--version@.
37−
38−options :: IO Options
39−options =
40− execParser $
41− info (helper <*> versionOption self <*> numericVersionOption <*> programOptions)
42− $ headerDoc hdoc
43− <> footerDoc fdoc
44−
45− where
46− hdoc = Just $ vcat $ map pretty
47− [ versionText self
48− , "Convert JSON to YAML."
49− ]
50− fdoc = Just $ pretty $ concat
51− [ "The old call pattern '"
52− , self
53− , " IN OUT' is also accepted, but deprecated."
54− ]
55−
56− programOptions :: Parser Options
57− programOptions = Options <$> oInput <*> oOutput
58−
59− oInput :: Parser (Maybe FilePath)
60− oInput = dashToNothing <$> do
61− strArgument
62− $ metavar "IN"
63− <> value "-"
64− <> action "file"
65− <> help "The input file containing the JSON document; use '-' for stdin (default)."
66−
67− oOutput :: Parser (Maybe FilePath)
68− oOutput = dashToNothing <$> do
69− oOutputExplicit <|> oOutputImplicit
70−
71− oOutputExplicit :: Parser FilePath
72− oOutputExplicit =
73− strOption
74− $ long "output"
75− <> short 'o'
76− <> metavar "OUT"
77− <> action "file"
78− -- <> help "The file to hold the produced YAML document; use '-' for stdout (default)."
79−
80− oOutputImplicit :: Parser FilePath
81− oOutputImplicit =
82− strArgument
83− $ metavar "OUT"
84− <> value "-"
85− <> action "file"
86− <> hidden
87− <> help "The file to hold the produced YAML document; use '-' for stdout (default)."
88−
89−-- | Exit with 'self'-stamped error message.
90−
91−abort :: String -> IO a
92−abort msg = die $ concat [ self, ": ", msg ]
93−
94−main :: IO ()
95−main = do
96− Options{ optInput, optOutput } <- options
97−
98− -- Read JSON.
99− mval <- J.decode <$> maybe L.getContents L.readFile optInput
100−
101− -- Write YAML.
102− case mval of
103− Nothing -> abort "Invalid input JSON"
104− Just val -> case optOutput of
105− Nothing -> S.putStr $ Y.encode (val :: Y.Value)
106− Just f -> Y.encodeFile f val
yaml/exe/yaml2json.hsdeleted−87
@@ -1,87 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE NamedFieldPuns #-}
4−
5−import Data.Aeson (encode, Value)
6−import qualified Data.ByteString as S (getContents)
7−import qualified Data.ByteString.Lazy as L (putStr, writeFile)
8−#if !MIN_VERSION_base(4,11,0)
9−import Data.Semigroup (Semigroup(..))
10−#endif
11−import Data.Yaml (decodeFileEither, decodeEither')
12−import System.Exit (die)
13−
14−import Options.Applicative
15− ( Parser
16− , action, execParser, headerDoc, help, helper, info
17− , long, metavar, short, strArgument, strOption, value
18− )
19−import Options.Applicative.Help.Pretty
20− ( vcat, pretty )
21−
22−import Common
23− ( versionText, versionOption, numericVersionOption, dashToNothing )
24−
25−data Options = Options
26− { optInput :: Maybe FilePath
27− -- ^ 'Nothing' means @stdin@.
28− , optOutput :: Maybe FilePath
29− -- ^ 'Nothing' means @stdout@.
30− }
31−
32−-- | Name of the executable.
33−
34−self :: String
35−self = "yaml2json"
36−
37−-- | Parse options; handle parse errors, @--help@, @--version@.
38−
39−options :: IO Options
40−options =
41− execParser $
42− info (helper <*> versionOption self <*> numericVersionOption <*> programOptions)
43− (headerDoc hdoc)
44−
45− where
46− hdoc = Just $ vcat $ map pretty
47− [ versionText self
48− , "Convert YAML to JSON."
49− ]
50−
51− programOptions = Options <$> oInput <*> oOutput
52−
53− oInput :: Parser (Maybe FilePath)
54− oInput = dashToNothing <$> do
55− strArgument
56− $ metavar "IN"
57− <> value "-"
58− <> action "file"
59− <> help "The input file containing the YAML document; use '-' for stdin (default)."
60−
61− oOutput :: Parser (Maybe FilePath)
62− oOutput = dashToNothing <$> do
63− strOption
64− $ long "output"
65− <> short 'o'
66− <> value "-"
67− <> metavar "OUT"
68− <> action "file"
69− <> help "The file to hold the produced JSON document; use '-' for stdout (default)."
70−
71−
72−main :: IO ()
73−main = do
74− Options{ optInput, optOutput } <- options
75−
76− -- Input YAML.
77− result <- case optInput of
78− -- strict getContents will read in all of stdin at once
79− Nothing -> decodeEither' <$> S.getContents
80− Just f -> decodeFileEither f
81−
82− -- Output JSON.
83− case result of
84− Left err -> die $ show err
85− Right val -> do
86− let json = encode (val :: Value)
87− maybe L.putStr L.writeFile optOutput json
yaml/package.yamldeleted−113
@@ -1,113 +0,0 @@
1−name: yaml
2−version: 0.11.11.2
3−synopsis: Support for parsing and rendering YAML documents.
4−description: README and API documentation are available at <https://www.stackage.org/package/yaml>
5−category: Data
6−author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
7−maintainer: Michael Snoyman <michael@snoyman.com>
8−license: BSD3
9−github: snoyberg/yaml
10−stability: stable
11−
12−extra-source-files:
13−- test/largest-string.yaml
14−- test/json.yaml
15−- test/resources/foo.yaml
16−- test/resources/bar.yaml
17−- test/resources/baz.yaml
18−- test/resources/accent/foo.yaml
19−- test/resources/loop/foo.yaml
20−- test/resources/loop/bar.yaml
21−- test/resources/empty.yaml
22−- test/resources/empty2.yaml
23−- README.md
24−- ChangeLog.md
25−
26−flags:
27− no-exe:
28− description: don't install the yaml2json or json2yaml executables
29− manual: false
30− default: true
31− no-examples:
32− description: don't build the examples
33− manual: false
34− default: true
35−
36−dependencies:
37−- base >=4.14 && <5 # GHC 8.10.1 and later
38−- bytestring >=0.9.1.4
39−- transformers >=0.1
40−- mtl
41−- conduit >=1.2.8 && <1.4
42−- resourcet >=0.3 && <1.4
43−- aeson >=0.11
44−- containers
45−- unordered-containers
46−- vector
47−- text
48−- attoparsec >=0.11.3.0
49−- scientific >= 0.3 # for Data.ByteString.Builder.Scientific
50−- filepath
51−- directory
52−- template-haskell
53−- libyaml >=0.1 && <0.2
54−
55−ghc-options: -Wall -Wcompat
56−
57−library:
58− other-extensions:
59− - LambdaCase
60− source-dirs: src
61−
62−executables:
63− json2yaml:
64− main: json2yaml.hs
65− source-dirs: exe
66− dependencies:
67− - optparse-applicative
68− - yaml
69− when:
70− - condition: flag(no-exe)
71− buildable: false
72− yaml2json:
73− main: yaml2json.hs
74− source-dirs: exe
75− dependencies:
76− - optparse-applicative
77− - yaml
78− when:
79− - condition: flag(no-exe)
80− buildable: false
81− other-extensions:
82− - CPP
83− - LambdaCase
84− - NamedFieldPuns
85− examples:
86− main: Main.hs
87− source-dirs: examples
88− when:
89− - condition: flag(no-examples)
90− then:
91− buildable: false
92− else:
93− dependencies:
94− - raw-strings-qq
95− - yaml
96−
97−tests:
98− spec:
99− main: Spec.hs
100− source-dirs: test
101− ghc-options: "-with-rtsopts=-K1K"
102− cpp-options: -DTEST
103− dependencies:
104− - hspec >=1.3
105− - HUnit
106− - yaml
107− - directory
108− - mockery
109− - base-compat
110− - temporary
111− - raw-strings-qq
112− build-tools:
113− - hspec-discover
yaml/parser-test.hsdeleted−22
@@ -1,22 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−import Data.Yaml.Parser
3−import Data.Conduit
4−import Text.Libyaml
5−import Control.Applicative
6−import Data.Text (Text)
7−
8−data Person = Person
9− { name :: !Text
10− , age :: !Int
11− }
12− deriving (Show)
13−
14−instance FromYaml Person where
15− fromYaml = withMapping "Person" $ \o -> Person
16− <$> o .: "name"
17− <*> o .: "age"
18−
19−main :: IO ()
20−main = do
21− persons <- readYamlFile "/tmp/foo.yaml"
22− mapM_ print (persons :: [Person])
yaml/src/Data/Yaml.hsdeleted−292
@@ -1,292 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−-- | Provides a high-level interface for processing YAML files.
6−--
7−-- This module reuses most of the infrastructure from the @aeson@ package.
8−-- This means that you can use all of the existing tools for JSON
9−-- processing for processing YAML files. As a result, much of the
10−-- documentation below mentions JSON; do not let that confuse you, it's
11−-- intentional.
12−--
13−-- For the most part, YAML content translates directly into JSON, and
14−-- therefore there is very little data loss. If you need to deal with YAML
15−-- more directly (e.g., directly deal with aliases), you should use the
16−-- "Text.Libyaml" module instead.
17−--
18−-- For documentation on the @aeson@ types, functions, classes, and
19−-- operators, please see the @Data.Aeson@ module of the @aeson@ package.
20−--
21−-- Look in the examples directory of the source repository for some initial
22−-- pointers on how to use this library.
23−
24−#if (defined (ghcjs_HOST_OS))
25−module Data.Yaml {-# WARNING "GHCJS is not supported yet (will break at runtime once called)." #-}
26−#else
27−module Data.Yaml
28−#endif
29− ( -- * Encoding
30− encode
31− , encodeWith
32− , encodeFile
33− , encodeFileWith
34− -- * Decoding
35− , decodeEither'
36− , decodeFileEither
37− , decodeFileWithWarnings
38− , decodeThrow
39− , decodeFileThrow
40− -- ** Decoding multiple documents
41− --
42− -- | For situations where we need to be able to parse multiple documents
43− -- separated by `---` in a YAML stream, these functions decode a list of
44− -- values rather than a single value.
45− , decodeAllEither'
46− , decodeAllFileEither
47− , decodeAllFileWithWarnings
48− , decodeAllThrow
49− , decodeAllFileThrow
50− -- ** More control over decoding
51− , decodeHelper
52− -- * Types
53− , Value (..)
54− , Parser
55− , Object
56− , Array
57− , ParseException(..)
58− , prettyPrintParseException
59− , YamlException (..)
60− , YamlMark (..)
61− -- * Constructors and accessors
62− , object
63− , array
64− , (.=)
65− , (.:)
66− , (.:?)
67− , (.!=)
68− -- ** With helpers (since 0.8.23)
69− , withObject
70− , withText
71− , withArray
72− , withScientific
73− , withBool
74− -- * Parsing
75− , parseMonad
76− , parseEither
77− , parseMaybe
78− -- * Classes
79− , ToJSON (..)
80− , FromJSON (..)
81− -- * Custom encoding
82− , isSpecialString
83− , EncodeOptions
84− , defaultEncodeOptions
85− , defaultStringStyle
86− , setStringStyle
87− , setFormat
88− , FormatOptions
89− , defaultFormatOptions
90− , setWidth
91− -- * Deprecated
92− , decode
93− , decodeFile
94− , decodeEither
95− ) where
96−#if !MIN_VERSION_base(4,8,0)
97−import Control.Applicative((<$>))
98−#endif
99−import Control.Exception
100−import Control.Monad.IO.Class (MonadIO, liftIO)
101−import Control.Monad.Trans.Resource (MonadThrow, throwM)
102−import Data.Aeson
103− ( Value (..), ToJSON (..), FromJSON (..), object
104− , (.=) , (.:) , (.:?) , (.!=)
105− , Object, Array
106− , withObject, withText, withArray, withScientific, withBool
107− )
108−import Data.Aeson.Types (parseMaybe, parseEither, Parser)
109−import Data.ByteString (ByteString)
110−import Data.Conduit ((.|), runConduitRes)
111−import qualified Data.Conduit.List as CL
112−import qualified Data.Vector as V
113−import System.IO.Unsafe (unsafePerformIO)
114−import Data.Text (Text)
115−
116−import Data.Yaml.Internal
117−import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile, encodeWith, encodeFileWith)
118−import qualified Text.Libyaml as Y
119−
120−-- | Set the string style in the encoded YAML. This is a function that decides
121−-- for each string the type of YAML string to output.
122−--
123−-- __WARNING__: You must ensure that special strings (like @"yes"@\/@"no"@\/@"null"@\/@"1234"@) are not encoded with the 'Plain' style, because
124−-- then they will be decoded as boolean, null or numeric values. You can use 'isSpecialString' to detect them.
125−--
126−-- By default, strings are encoded as follows:
127−--
128−-- * Any string containing a newline character uses the 'Literal' style
129−--
130−-- * Otherwise, any special string (see 'isSpecialString') uses 'SingleQuoted'
131−--
132−-- * Otherwise, use 'Plain'
133−--
134−-- @since 0.10.2.0
135−setStringStyle :: (Text -> ( Tag, Style )) -> EncodeOptions -> EncodeOptions
136−setStringStyle s opts = opts { encodeOptionsStringStyle = s }
137−
138−-- | Set the encoding formatting for the encoded YAML. By default, this is `defaultFormatOptions`.
139−--
140−-- @since 0.10.2.0
141−setFormat :: FormatOptions -> EncodeOptions -> EncodeOptions
142−setFormat f opts = opts { encodeOptionsFormat = f }
143−
144−-- |
145−-- @since 0.10.2.0
146−data EncodeOptions = EncodeOptions
147− { encodeOptionsStringStyle :: Text -> ( Tag, Style )
148− , encodeOptionsFormat :: FormatOptions
149− }
150−
151−-- |
152−-- @since 0.10.2.0
153−defaultEncodeOptions :: EncodeOptions
154−defaultEncodeOptions = EncodeOptions
155− { encodeOptionsStringStyle = defaultStringStyle
156− , encodeOptionsFormat = defaultFormatOptions
157− }
158−
159−-- | Encode a value into its YAML representation.
160−encode :: ToJSON a => a -> ByteString
161−encode = encodeWith defaultEncodeOptions
162−
163−-- | Encode a value into its YAML representation with custom styling.
164−--
165−-- @since 0.10.2.0
166−encodeWith :: ToJSON a => EncodeOptions -> a -> ByteString
167−encodeWith opts obj = unsafePerformIO $ runConduitRes
168− $ CL.sourceList (objToStream (encodeOptionsStringStyle opts) $ toJSON obj)
169− .| Y.encodeWith (encodeOptionsFormat opts)
170−
171−-- | Encode a value into its YAML representation and save to the given file.
172−encodeFile :: ToJSON a => FilePath -> a -> IO ()
173−encodeFile = encodeFileWith defaultEncodeOptions
174−
175−-- | Encode a value into its YAML representation with custom styling and save to the given file.
176−--
177−-- @since 0.10.2.0
178−encodeFileWith :: ToJSON a => EncodeOptions -> FilePath -> a -> IO ()
179−encodeFileWith opts fp obj = runConduitRes
180− $ CL.sourceList (objToStream (encodeOptionsStringStyle opts) $ toJSON obj)
181− .| Y.encodeFileWith (encodeOptionsFormat opts) fp
182−
183−decode :: FromJSON a
184− => ByteString
185− -> Maybe a
186−decode bs = unsafePerformIO
187− $ either (const Nothing) snd
188− <$> decodeHelper_ (Y.decode bs)
189−{-# DEPRECATED decode "Please use decodeEither or decodeThrow, which provide information on how the decode failed" #-}
190−
191−decodeFile :: FromJSON a
192− => FilePath
193− -> IO (Maybe a)
194−decodeFile fp = (fmap snd <$> decodeHelper (Y.decodeFile fp)) >>= either throwIO (return . either (const Nothing) id)
195−{-# DEPRECATED decodeFile "Please use decodeFileEither, which does not confused type-directed and runtime exceptions." #-}
196−
197−-- | A version of 'decodeFile' which should not throw runtime exceptions.
198−--
199−-- @since 0.8.4
200−decodeFileEither
201− :: FromJSON a
202− => FilePath
203− -> IO (Either ParseException a)
204−decodeFileEither = fmap (fmap snd) . decodeFileWithWarnings
205−
206−-- | Like `decodeFileEither`, but decode multiple documents.
207−--
208−-- @since 0.11.5.0
209−decodeAllFileEither
210− :: FromJSON a
211− => FilePath
212− -> IO (Either ParseException [a])
213−decodeAllFileEither = fmap (fmap snd) . decodeAllFileWithWarnings
214−
215−-- | A version of `decodeFileEither` that returns warnings along with the parse
216−-- result.
217−--
218−-- @since 0.10.0
219−decodeFileWithWarnings
220− :: FromJSON a
221− => FilePath
222− -> IO (Either ParseException ([Warning], a))
223−decodeFileWithWarnings = decodeHelper_ . Y.decodeFile
224−
225−-- | Like `decodeFileWithWarnings`, but decode multiple documents.
226−--
227−-- @since 0.11.5.0
228−decodeAllFileWithWarnings
229− :: FromJSON a
230− => FilePath
231− -> IO (Either ParseException ([Warning], [a]))
232−decodeAllFileWithWarnings = decodeAllHelper_ . Y.decodeFile
233−
234−decodeEither :: FromJSON a => ByteString -> Either String a
235−decodeEither bs = unsafePerformIO
236− $ either (Left . prettyPrintParseException) id
237− <$> (fmap snd <$> decodeHelper (Y.decode bs))
238−{-# DEPRECATED decodeEither "Please use decodeEither' or decodeThrow, which provide more useful failures" #-}
239−
240−-- | More helpful version of 'decodeEither' which returns the 'YamlException'.
241−--
242−-- @since 0.8.3
243−decodeEither' :: FromJSON a => ByteString -> Either ParseException a
244−decodeEither' = either Left (either (Left . AesonException) Right)
245− . unsafePerformIO
246− . fmap (fmap snd) . decodeHelper
247− . Y.decode
248−
249−-- | Like 'decodeEither'', but decode multiple documents.
250−--
251−-- @since 0.11.5.0
252−decodeAllEither' :: FromJSON a => ByteString -> Either ParseException [a]
253−decodeAllEither' = either Left (either (Left . AesonException) Right)
254− . unsafePerformIO
255− . fmap (fmap snd) . decodeAllHelper
256− . Y.decode
257−
258−-- | A version of 'decodeEither'' lifted to MonadThrow
259−--
260−-- @since 0.8.31
261−decodeThrow :: (MonadThrow m, FromJSON a) => ByteString -> m a
262−decodeThrow = either throwM return . decodeEither'
263−
264−-- | Like `decodeThrow`, but decode multiple documents.
265−--
266−-- @since 0.11.5.0
267−decodeAllThrow :: (MonadThrow m, FromJSON a) => ByteString -> m [a]
268−decodeAllThrow = either throwM return . decodeAllEither'
269−
270−-- | A version of 'decodeFileEither' lifted to MonadIO
271−--
272−-- @since 0.8.31
273−decodeFileThrow :: (MonadIO m, FromJSON a) => FilePath -> m a
274−decodeFileThrow f = liftIO $ decodeFileEither f >>= either throwIO return
275−
276−-- | Like `decodeFileThrow`, but decode multiple documents.
277−--
278−-- @since 0.11.5.0
279−decodeAllFileThrow :: (MonadIO m, FromJSON a) => FilePath -> m [a]
280−decodeAllFileThrow f = liftIO $ decodeAllFileEither f >>= either throwIO return
281−
282−-- | Construct a new 'Value' from a list of 'Value's.
283−array :: [Value] -> Value
284−array = Array . V.fromList
285−
286−#if MIN_VERSION_base(4, 13, 0)
287−parseMonad :: MonadFail m => (a -> Parser b) -> a -> m b
288−#else
289−parseMonad :: Monad m => (a -> Parser b) -> a -> m b
290−#endif
291−parseMonad p = either fail return . parseEither p
292−{-# DEPRECATED parseMonad "With the MonadFail split, this function is going to be removed in the future. Please migrate to parseEither." #-}
yaml/src/Data/Yaml/Aeson.hsdeleted−7
@@ -1,7 +0,0 @@
1−-- | Just a re-export of @Data.Yaml@. In the future, this will be the canonical
2−-- name for that module\'s contents.
3−module Data.Yaml.Aeson
4− ( module Data.Yaml
5− ) where
6−
7−import Data.Yaml
yaml/src/Data/Yaml/Builder.hsdeleted−240
@@ -1,240 +0,0 @@
1−{-# LANGUAGE FlexibleInstances #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE CPP #-}
4−-- | NOTE: This module is a highly experimental preview release. It may change
5−-- drastically, or be entirely removed, in a future release.
6−module Data.Yaml.Builder
7− ( YamlBuilder (..)
8− , ToYaml (..)
9− , mapping
10− , namedMapping
11− , maybeNamedMapping
12− , mappingComplex
13− , namedMappingComplex
14− , maybeNamedMappingComplex
15− , array
16− , namedArray
17− , maybeNamedArray
18− , string
19− , namedString
20− , maybeNamedString
21− , bool
22− , namedBool
23− , maybeNamedBool
24− , null
25− , namedNull
26− , maybeNamedNull
27− , scientific
28− , namedScientific
29− , maybeNamedScientific
30− , alias
31− , number
32− , toByteString
33− , toByteStringWith
34− , writeYamlFile
35− , writeYamlFileWith
36− , (.=)
37− , FormatOptions
38− , setWidth
39− ) where
40−
41−import Prelude hiding (null)
42−
43−#if MIN_VERSION_aeson(1,0,0)
44−import Data.Aeson.Text (encodeToTextBuilder)
45−#else
46−import Data.Aeson.Encode (encodeToTextBuilder)
47−#endif
48−import Data.Aeson.Types (Value(..))
49−import Data.ByteString (ByteString)
50−import qualified Data.ByteString.Char8 as S8
51−import Data.Conduit
52−import Data.Scientific (Scientific)
53−import Data.Text (Text, unpack)
54−import qualified Data.Text as T
55−import qualified Data.Text.Encoding as TE
56−import qualified Data.Text.Lazy as TL
57−import Data.Text.Lazy.Builder (toLazyText)
58−import System.IO.Unsafe (unsafePerformIO)
59−
60−import Data.Yaml.Internal
61−import Text.Libyaml
62−
63−(.=) :: ToYaml a => Text -> a -> (Text, YamlBuilder)
64−k .= v = (k, toYaml v)
65−
66−newtype YamlBuilder = YamlBuilder { unYamlBuilder :: [Event] -> [Event] }
67−
68−class ToYaml a where
69− toYaml :: a -> YamlBuilder
70−instance ToYaml YamlBuilder where
71− toYaml = id
72−instance (ToYaml a, ToYaml b) => ToYaml [(a, b)] where
73− toYaml = mappingComplex . map (\(k, v) -> (toYaml k, toYaml v))
74−instance ToYaml a => ToYaml [a] where
75− toYaml = array . map toYaml
76−instance ToYaml Text where
77− toYaml = string
78−instance {-# OVERLAPPING #-} ToYaml String where
79− toYaml = string . T.pack
80−instance ToYaml Int where
81− toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) NoTag PlainNoTag Nothing:)
82−instance ToYaml Double where
83− toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) NoTag PlainNoTag Nothing:)
84−instance ToYaml Scientific where
85− toYaml = scientific
86−instance ToYaml Bool where
87− toYaml = bool
88−instance ToYaml a => ToYaml (Maybe a) where
89− toYaml = maybe null toYaml
90−
91−-- |
92−-- @since 0.10.3.0
93−maybeNamedMapping :: Maybe Text -> [(Text, YamlBuilder)] -> YamlBuilder
94−maybeNamedMapping anchor pairs = maybeNamedMappingComplex anchor complexPairs
95− where
96− complexPairs = map (\(k, v) -> (string k, v)) pairs
97−
98−-- |
99−-- @since 0.8.7
100−mapping :: [(Text, YamlBuilder)] -> YamlBuilder
101−mapping = maybeNamedMapping Nothing
102−
103−-- |
104−-- @since 0.10.3.0
105−namedMapping :: Text -> [(Text, YamlBuilder)] -> YamlBuilder
106−namedMapping name = maybeNamedMapping $ Just name
107−
108−-- |
109−-- @since 0.11.2.0
110−maybeNamedMappingComplex :: Maybe Text -> [(YamlBuilder, YamlBuilder)] -> YamlBuilder
111−maybeNamedMappingComplex anchor pairs = YamlBuilder $ \rest ->
112− EventMappingStart NoTag AnyMapping (unpack <$> anchor) : foldr addPair (EventMappingEnd : rest) pairs
113− where
114− addPair (YamlBuilder key, YamlBuilder value) after = key $ value after
115−
116−-- |
117−-- @since 0.11.2.0
118−mappingComplex :: [(YamlBuilder, YamlBuilder)] -> YamlBuilder
119−mappingComplex = maybeNamedMappingComplex Nothing
120−
121−-- |
122−-- @since 0.11.2.0
123−namedMappingComplex :: Text -> [(YamlBuilder, YamlBuilder)] -> YamlBuilder
124−namedMappingComplex name = maybeNamedMappingComplex $ Just name
125−
126−-- |
127−-- @since 0.10.3.0
128−maybeNamedArray :: Maybe Text -> [YamlBuilder] -> YamlBuilder
129−maybeNamedArray anchor bs =
130− YamlBuilder $ (EventSequenceStart NoTag AnySequence (unpack <$> anchor):) . flip (foldr go) bs . (EventSequenceEnd:)
131− where
132− go (YamlBuilder b) = b
133−
134−-- |
135−-- @since 0.8.7
136−array :: [YamlBuilder] -> YamlBuilder
137−array = maybeNamedArray Nothing
138−
139−-- |
140−-- @since 0.10.3.0
141−namedArray :: Text -> [YamlBuilder] -> YamlBuilder
142−namedArray name = maybeNamedArray $ Just name
143−
144−-- |
145−-- @since 0.10.3.0
146−maybeNamedString :: Maybe Text -> Text -> YamlBuilder
147−maybeNamedString anchor s = YamlBuilder (stringScalar defaultStringStyle anchor s :)
148−
149−-- |
150−-- @since 0.8.7
151−string :: Text -> YamlBuilder
152−string = maybeNamedString Nothing
153−
154−-- |
155−-- @since 0.10.3.0
156−namedString :: Text -> Text -> YamlBuilder
157−namedString name = maybeNamedString $ Just name
158−
159−-- Use aeson's implementation which gets rid of annoying decimal points
160−-- |
161−-- @since 0.10.3.0
162−maybeNamedScientific :: Maybe Text -> Scientific -> YamlBuilder
163−maybeNamedScientific anchor n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) NoTag PlainNoTag (unpack <$> anchor) :)
164−
165−-- |
166−-- @since 0.8.13
167−scientific :: Scientific -> YamlBuilder
168−scientific = maybeNamedScientific Nothing
169−
170−-- |
171−-- @since 0.10.3.0
172−namedScientific :: Text -> Scientific -> YamlBuilder
173−namedScientific name = maybeNamedScientific $ Just name
174−
175−-- |
176−-- @since 0.8.13
177−{-# DEPRECATED number "Use scientific" #-}
178−number :: Scientific -> YamlBuilder
179−number = scientific
180−
181−-- |
182−-- @since 0.10.3.0
183−maybeNamedBool :: Maybe Text -> Bool -> YamlBuilder
184−maybeNamedBool anchor True = YamlBuilder (EventScalar "true" NoTag PlainNoTag (unpack <$> anchor) :)
185−maybeNamedBool anchor False = YamlBuilder (EventScalar "false" NoTag PlainNoTag (unpack <$> anchor) :)
186−
187−-- |
188−-- @since 0.8.13
189−bool :: Bool -> YamlBuilder
190−bool = maybeNamedBool Nothing
191−
192−-- |
193−-- @since 0.10.3.0
194−namedBool :: Text -> Bool -> YamlBuilder
195−namedBool name = maybeNamedBool $ Just name
196−
197−-- |
198−-- @since 0.10.3.0
199−maybeNamedNull :: Maybe Text -> YamlBuilder
200−maybeNamedNull anchor = YamlBuilder (EventScalar "null" NoTag PlainNoTag (unpack <$> anchor) :)
201−
202−-- |
203−-- @since 0.8.13
204−null :: YamlBuilder
205−null = maybeNamedNull Nothing
206−
207−-- |
208−-- @since 0.10.3.0
209−namedNull :: Text -> YamlBuilder
210−namedNull name = maybeNamedNull $ Just name
211−
212−-- |
213−-- @since 0.10.3.0
214−alias :: Text -> YamlBuilder
215−alias anchor = YamlBuilder (EventAlias (unpack anchor) :)
216−
217−toEvents :: YamlBuilder -> [Event]
218−toEvents (YamlBuilder front) =
219− EventStreamStart : EventDocumentStart : front [EventDocumentEnd, EventStreamEnd]
220−
221−toSource :: (Monad m, ToYaml a) => a -> ConduitM i Event m ()
222−toSource = mapM_ yield . toEvents . toYaml
223−
224−-- |
225−-- @since 0.8.7
226−toByteString :: ToYaml a => a -> ByteString
227−toByteString = toByteStringWith defaultFormatOptions
228−
229−-- |
230−-- @since 0.10.2.0
231−toByteStringWith :: ToYaml a => FormatOptions -> a -> ByteString
232−toByteStringWith opts yb = unsafePerformIO $ runConduitRes $ toSource yb .| encodeWith opts
233−
234−writeYamlFile :: ToYaml a => FilePath -> a -> IO ()
235−writeYamlFile = writeYamlFileWith defaultFormatOptions
236−
237−-- |
238−-- @since 0.10.2.0
239−writeYamlFileWith :: ToYaml a => FormatOptions -> FilePath -> a -> IO ()
240−writeYamlFileWith opts fp yb = runConduitRes $ toSource yb .| encodeFileWith opts fp
yaml/src/Data/Yaml/Config.hsdeleted−234
@@ -1,234 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−-- | Functionality for using YAML as configuration files
4−--
5−-- In particular, merging environment variables with yaml values
6−--
7−-- 'loadYamlSettings' is a high-level API for loading YAML and merging environment variables.
8−-- A yaml value of @_env:ENV_VAR:default@ or just @_env:ENV_VAR@ will lookup the environment variable @ENV_VAR@.
9−--
10−-- On a historical note, this code was taken directly from the yesod web framework's configuration module.
11−module Data.Yaml.Config
12− ( -- * High-level
13− loadYamlSettings
14− , loadYamlSettingsArgs
15− -- ** EnvUsage
16− , EnvUsage
17− , ignoreEnv
18− , useEnv
19− , requireEnv
20− , useCustomEnv
21− , requireCustomEnv
22− -- * Lower level
23− , applyCurrentEnv
24− , getCurrentEnv
25− , applyEnvValue
26− ) where
27−
28−
29−#if __GLASGOW_HASKELL__ < 710
30−import Control.Applicative ((<$>))
31−import Data.Monoid
32−#endif
33−import Data.Semigroup
34−import Data.List.NonEmpty (nonEmpty)
35−import Data.Aeson
36−#if MIN_VERSION_aeson(2,0,0)
37−import qualified Data.Aeson.Key as K
38−import qualified Data.Aeson.KeyMap as H
39−import Data.Aeson.KeyMap (KeyMap)
40−#else
41−import qualified Data.HashMap.Strict as H
42−#endif
43−import Data.Text (Text, pack)
44−import System.Environment (getArgs, getEnvironment)
45−import Control.Arrow ((***))
46−import Control.Monad (forM)
47−import Control.Exception (throwIO)
48−import Data.Text.Encoding (encodeUtf8)
49−import qualified Data.Yaml as Y
50−import qualified Data.Yaml.Include as YI
51−import Data.Maybe (fromMaybe)
52−import qualified Data.Text as T
53−
54−#if MIN_VERSION_aeson(2,0,0)
55−fromText :: T.Text -> Key
56−fromText = K.fromText
57−#else
58−fromText :: T.Text -> T.Text
59−fromText = id
60−
61−type KeyMap a = H.HashMap T.Text a
62−#endif
63−
64−newtype MergedValue = MergedValue { getMergedValue :: Value }
65−
66−instance Semigroup MergedValue where
67− MergedValue x <> MergedValue y = MergedValue $ mergeValues x y
68−
69−-- | Left biased
70−mergeValues :: Value -> Value -> Value
71−mergeValues (Object x) (Object y) = Object $ H.unionWith mergeValues x y
72−mergeValues x _ = x
73−
74−-- | Override environment variable placeholders in the given @Value@ with
75−-- values from the environment.
76−--
77−-- If the first argument is @True@, then all placeholders _must_ be provided by
78−-- the actual environment. Otherwise, default values from the @Value@ will be
79−-- used.
80−--
81−-- @since 0.8.16
82−applyEnvValue :: Bool -- ^ require an environment variable to be present?
83− -> KeyMap Text -> Value -> Value
84−applyEnvValue requireEnv' env =
85− goV
86− where
87− goV (Object o) = Object $ goV <$> o
88− goV (Array a) = Array (goV <$> a)
89− goV (String t1) = fromMaybe (String t1) $ do
90− t2 <- T.stripPrefix "_env:" t1
91− let (name, t3) = T.break (== ':') t2
92− mdef = fmap parseValue $ T.stripPrefix ":" t3
93− Just $ case H.lookup (fromText name) env of
94− Just val ->
95− -- If the default value parses as a String, we treat the
96− -- environment variable as a raw value and do not parse it.
97− -- This means that things like numeric passwords just work.
98− -- However, for originally numerical or boolean values (e.g.,
99− -- port numbers), we still perform a normal YAML parse.
100− --
101− -- For details, see:
102− -- https://github.com/yesodweb/yesod/issues/1061
103− case mdef of
104− Just (String _) -> String val
105− _ -> parseValue val
106− Nothing ->
107− case mdef of
108− Just val | not requireEnv' -> val
109− _ -> Null
110− goV v = v
111−
112− parseValue val = either
113− (const (String val))
114− id
115− (Y.decodeThrow $ encodeUtf8 val)
116−
117−-- | Get the actual environment as a @HashMap@ from @Text@ to @Text@.
118−--
119−-- @since 0.8.16
120−getCurrentEnv :: IO (KeyMap Text)
121−getCurrentEnv = fmap (H.fromList . map (fromText . pack *** pack)) getEnvironment
122−
123−-- | A convenience wrapper around 'applyEnvValue' and 'getCurrentEnv'
124−--
125−-- @since 0.8.16
126−applyCurrentEnv :: Bool -- ^ require an environment variable to be present?
127− -> Value -> IO Value
128−applyCurrentEnv requireEnv' orig = flip (applyEnvValue requireEnv') orig <$> getCurrentEnv
129−
130−-- | Defines how we want to use the environment variables when loading a config
131−-- file. Use the smart constructors provided by this module.
132−--
133−-- @since 0.8.16
134−data EnvUsage = IgnoreEnv
135− | UseEnv
136− | RequireEnv
137− | UseCustomEnv (KeyMap Text)
138− | RequireCustomEnv (KeyMap Text)
139−
140−-- | Do not use any environment variables, instead relying on defaults values
141−-- in the config file.
142−--
143−-- @since 0.8.16
144−ignoreEnv :: EnvUsage
145−ignoreEnv = IgnoreEnv
146−
147−-- | Use environment variables when available, otherwise use defaults.
148−--
149−-- @since 0.8.16
150−useEnv :: EnvUsage
151−useEnv = UseEnv
152−
153−-- | Do not use default values from the config file, but instead take all
154−-- overrides from the environment. If a value is missing, loading the file will
155−-- throw an exception.
156−--
157−-- @since 0.8.16
158−requireEnv :: EnvUsage
159−requireEnv = RequireEnv
160−
161−-- | Same as 'useEnv', but instead of the actual environment, use the provided
162−-- @HashMap@ as the environment.
163−--
164−-- @since 0.8.16
165−useCustomEnv :: KeyMap Text -> EnvUsage
166−useCustomEnv = UseCustomEnv
167−
168−-- | Same as 'requireEnv', but instead of the actual environment, use the
169−-- provided @HashMap@ as the environment.
170−--
171−-- @since 0.8.16
172−requireCustomEnv :: KeyMap Text -> EnvUsage
173−requireCustomEnv = RequireCustomEnv
174−
175−-- | Load the settings from the following three sources:
176−--
177−-- * Run time config files
178−--
179−-- * Run time environment variables
180−--
181−-- * The default compile time config file
182−--
183−-- For example, to load up settings from @config/foo.yaml@ and allow overriding
184−-- from the actual environment, you can use:
185−--
186−-- > loadYamlSettings ["config/foo.yaml"] [] useEnv
187−--
188−-- Alternatively you can configure settings through the Yaml @Value@ directly in Haskell.
189−-- For example, to load up settings from only from environment variables, you can use:
190−--
191−-- > loadYamlSettings [] [object ["connectionString" .= ("_env:DATABASE_URL" :: String)]] requireEnv
192−--
193−-- @since 0.8.16
194−loadYamlSettings
195− :: FromJSON settings
196− => [FilePath] -- ^ run time config files to use, earlier files have precedence
197− -> [Value] -- ^ any other values to use, usually from compile time config. overridden by files
198− -> EnvUsage
199− -> IO settings
200−loadYamlSettings runTimeFiles compileValues envUsage = do
201− runValues <- forM runTimeFiles $ \fp -> do
202− eres <- YI.decodeFileEither fp
203− case eres of
204− Left e -> throwIO (Y.LoadSettingsException fp e)
205− Right value -> return value
206−
207− value' <-
208− case nonEmpty $ map MergedValue $ runValues ++ compileValues of
209− Nothing -> error "loadYamlSettings: No configuration provided"
210− Just ne -> return $ getMergedValue $ sconcat ne
211− value <-
212− case envUsage of
213− IgnoreEnv -> return $ applyEnvValue False mempty value'
214− UseEnv -> applyCurrentEnv False value'
215− RequireEnv -> applyCurrentEnv True value'
216− UseCustomEnv env -> return $ applyEnvValue False env value'
217− RequireCustomEnv env -> return $ applyEnvValue True env value'
218−
219− case Y.parseEither parseJSON value of
220− Left s -> error $ "Could not convert to expected type: " ++ s
221− Right settings -> return settings
222−
223−-- | Same as @loadYamlSettings@, but get the list of runtime config files from
224−-- the command line arguments.
225−--
226−-- @since 0.8.17
227−loadYamlSettingsArgs
228− :: FromJSON settings
229− => [Value] -- ^ any other values to use, usually from compile time config. overridden by files
230− -> EnvUsage -- ^ use environment variables
231− -> IO settings
232−loadYamlSettingsArgs values env = do
233− args <- getArgs
234− loadYamlSettings args values env
yaml/src/Data/Yaml/Include.hsdeleted−94
@@ -1,94 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE RankNTypes #-}
3−module Data.Yaml.Include (
4− decodeFile
5−, decodeFileEither
6−, decodeFileWithWarnings
7−) where
8−
9−#if !MIN_VERSION_directory(1, 2, 3)
10−import Control.Exception (handleJust)
11−import Control.Monad (guard)
12−import System.IO.Error (ioeGetFileName, ioeGetLocation, isDoesNotExistError)
13−#endif
14−
15−import Control.Exception (throwIO)
16−import Control.Monad (when)
17−import Control.Monad.IO.Class (liftIO)
18−import Control.Monad.Trans.Resource (MonadResource)
19−import Data.Aeson (FromJSON)
20−import Data.Conduit
21−import qualified Data.Conduit.List as CL
22−import Data.Text (unpack)
23−import Data.Text.Encoding (decodeUtf8)
24−import System.Directory
25−import System.FilePath
26−
27−import Data.Yaml.Internal (ParseException(..), Warning(..), decodeHelper_, decodeHelper)
28−import Text.Libyaml hiding (decodeFile)
29−import qualified Text.Libyaml as Y
30−
31−eventsFromFile
32− :: MonadResource m
33− => FilePath
34− -> ConduitM i Event m ()
35−eventsFromFile = go []
36− where
37− go :: MonadResource m => [FilePath] -> FilePath -> ConduitM i Event m ()
38− go seen fp = do
39− cfp <- liftIO $ handleNotFound $ canonicalizePath fp
40− when (cfp `elem` seen) $ do
41− liftIO $ throwIO CyclicIncludes
42− Y.decodeFile cfp .| do
43− awaitForever $ \event -> case event of
44− EventScalar f (UriTag "!include") _ _ -> do
45− let includeFile = takeDirectory cfp </> unpack (decodeUtf8 f)
46− go (cfp : seen) includeFile .| CL.filter (`notElem` irrelevantEvents)
47− _ -> yield event
48−
49− irrelevantEvents = [EventStreamStart, EventDocumentStart, EventDocumentEnd, EventStreamEnd]
50−
51−#if !MIN_VERSION_directory(1, 2, 3)
52− handleNotFound = handleJust
53− (\e -> do
54− guard (isDoesNotExistError e)
55− guard (ioeGetLocation e == "canonicalizePath")
56− ioeGetFileName e)
57− (throwIO . YamlException . ("Yaml file not found: " ++))
58−#else
59− handleNotFound = id
60−#endif
61−
62−-- | Like `Data.Yaml.decodeFile` but with support for relative and absolute
63−-- includes.
64−--
65−-- The syntax for includes follows the form:
66−--
67−-- > somekey: !include ./somefile.yaml
68−decodeFile
69− :: FromJSON a
70− => FilePath
71− -> IO (Maybe a)
72−decodeFile fp = (fmap snd <$> decodeHelper (eventsFromFile fp)) >>= either throwIO (return . either (const Nothing) id)
73−
74−-- | Like `Data.Yaml.decodeFileEither` but with support for relative and
75−-- absolute includes.
76−--
77−-- The syntax for includes follows the form:
78−--
79−-- > somekey: !include ./somefile.yaml
80−decodeFileEither
81− :: FromJSON a
82− => FilePath
83− -> IO (Either ParseException a)
84−decodeFileEither = fmap (fmap snd) . decodeFileWithWarnings
85−
86−-- | A version of `decodeFileEither` that returns warnings along with the parse
87−-- result.
88−--
89−-- @since 0.10.0
90−decodeFileWithWarnings
91− :: FromJSON a
92− => FilePath
93− -> IO (Either ParseException ([Warning], a))
94−decodeFileWithWarnings = decodeHelper_ . eventsFromFile
yaml/src/Data/Yaml/Internal.hsdeleted−469
@@ -1,469 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE PatternGuards #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−{-# LANGUAGE BangPatterns #-}
6−module Data.Yaml.Internal
7− (
8− ParseException(..)
9− , prettyPrintParseException
10− , Warning(..)
11− , parse
12− , Parse
13− , decodeHelper
14− , decodeHelper_
15− , decodeAllHelper
16− , decodeAllHelper_
17− , textToScientific
18− , stringScalar
19− , StringStyle
20− , defaultStringStyle
21− , isSpecialString
22− , specialStrings
23− , isNumeric
24− , objToStream
25− , objToEvents
26− ) where
27−
28−#if !MIN_VERSION_base(4,8,0)
29−import Control.Applicative ((<$>), Applicative(..))
30−#endif
31−import Control.Applicative ((<|>))
32−import Control.Exception
33−import Control.Monad (when, unless)
34−import Control.Monad.Trans.Resource (ResourceT, runResourceT)
35−import Control.Monad.State.Strict
36−import Control.Monad.Reader
37−#if MIN_VERSION_aeson(2,1,2)
38−import Data.Aeson hiding (AesonException)
39−#else
40−import Data.Aeson
41−#endif
42−#if MIN_VERSION_aeson(2,0,0)
43−import qualified Data.Aeson.Key as K
44−import qualified Data.Aeson.KeyMap as M
45−import Data.Aeson.KeyMap (KeyMap)
46−#else
47−import qualified Data.HashMap.Strict as M
48−#endif
49−#if MIN_VERSION_aeson(2,2,0)
50−import Data.Aeson.Types hiding (AesonException, parse)
51−#else
52−import Data.Aeson.Types hiding (parse)
53−import Data.Aeson.Internal (JSONPath, JSONPathElement(..), formatError)
54−#endif
55−import qualified Data.Attoparsec.Text as Atto
56−import Data.Bits (shiftL, (.|.))
57−import Data.ByteString (ByteString)
58−import qualified Data.ByteString.Builder as BB
59−import qualified Data.ByteString.Lazy as BL
60−import Data.ByteString.Builder.Scientific (scientificBuilder)
61−import Data.Char (toUpper, ord)
62−import qualified Data.List as List
63−import Data.Conduit ((.|), ConduitM, runConduit)
64−import qualified Data.Conduit.List as CL
65−import qualified Data.HashSet as HashSet
66−import Data.Map (Map)
67−import qualified Data.Map as Map
68−import Data.Set (Set)
69−import qualified Data.Set as Set
70−import Data.Scientific (Scientific, base10Exponent, coefficient)
71−import Data.Text (Text)
72−import qualified Data.Text as T
73−import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
74−import Data.Text.Encoding.Error (lenientDecode)
75−import Data.Typeable
76−import qualified Data.Vector as V
77−import Data.Void (Void)
78−
79−import qualified Text.Libyaml as Y
80−import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile)
81−
82−#if MIN_VERSION_aeson(2,0,0)
83−fromText :: T.Text -> K.Key
84−fromText = K.fromText
85−
86−toText :: K.Key -> T.Text
87−toText = K.toText
88−#else
89−fromText :: T.Text -> T.Text
90−fromText = id
91−
92−toText :: Key -> T.Text
93−toText = id
94−
95−type KeyMap a = M.HashMap Text a
96−type Key = Text
97−#endif
98−
99−data ParseException = NonScalarKey
100− | UnknownAlias { _anchorName :: Y.AnchorName }
101− | UnexpectedEvent { _received :: Maybe Event
102− , _expected :: Maybe Event
103− }
104− | InvalidYaml (Maybe YamlException)
105− | MultipleDocuments
106− | AesonException String
107− | OtherParseException SomeException
108− | NonStringKey JSONPath
109− | NonStringKeyAlias Y.AnchorName Value
110− | CyclicIncludes
111− | LoadSettingsException FilePath ParseException
112− deriving (Show, Typeable)
113−
114−instance Exception ParseException where
115−#if MIN_VERSION_base(4, 8, 0)
116− displayException = prettyPrintParseException
117−#endif
118−
119−-- | Alternative to 'show' to display a 'ParseException' on the screen.
120−-- Instead of displaying the data constructors applied to their arguments,
121−-- a more textual output is returned. For example, instead of printing:
122−--
123−-- > InvalidYaml (Just (YamlParseException {yamlProblem = "did not find expected ',' or '}'", yamlContext = "while parsing a flow mapping", yamlProblemMark = YamlMark {yamlIndex = 42, yamlLine = 2, yamlColumn = 12}})))
124−--
125−-- It looks more pleasant to print:
126−--
127−-- > YAML parse exception at line 2, column 12,
128−-- > while parsing a flow mapping:
129−-- > did not find expected ',' or '}'
130−--
131−-- Since 0.8.11
132−prettyPrintParseException :: ParseException -> String
133−prettyPrintParseException pe = case pe of
134− NonScalarKey -> "Non scalar key"
135− UnknownAlias anchor -> "Unknown alias `" ++ anchor ++ "`"
136− UnexpectedEvent { _expected = mbExpected, _received = mbUnexpected } -> unlines
137− [ "Unexpected event: expected"
138− , " " ++ show mbExpected
139− , "but received"
140− , " " ++ show mbUnexpected
141− ]
142− InvalidYaml mbYamlError -> case mbYamlError of
143− Nothing -> "Unspecified YAML error"
144− Just yamlError -> case yamlError of
145− YamlException s -> "YAML exception:\n" ++ s
146− YamlParseException problem context mark -> concat
147− [ "YAML parse exception at line " ++ show (yamlLine mark) ++
148− ", column " ++ show (yamlColumn mark)
149− , case context of
150− "" -> ":\n"
151− -- The context seems to include a leading "while" or similar.
152− _ -> ",\n" ++ context ++ ":\n"
153− , problem
154− ]
155− MultipleDocuments -> "Multiple YAML documents encountered"
156− AesonException s -> "Aeson exception:\n" ++ s
157− OtherParseException exc -> "Generic parse exception:\n" ++ show exc
158− NonStringKey path -> formatError path "Non-string keys are not supported"
159− NonStringKeyAlias anchor value -> unlines
160− [ "Non-string key alias:"
161− , " Anchor name: " ++ anchor
162− , " Value: " ++ show value
163− ]
164− CyclicIncludes -> "Cyclic includes"
165− LoadSettingsException fp exc -> "Could not parse file as YAML: " ++ fp ++ "\n" ++ prettyPrintParseException exc
166−
167−defineAnchor :: Value -> String -> ReaderT JSONPath (ConduitM e o Parse) ()
168−defineAnchor value name = modify (modifyAnchors $ Map.insert name value)
169− where
170− modifyAnchors :: (Map String Value -> Map String Value) -> ParseState -> ParseState
171− modifyAnchors f st = st {parseStateAnchors = f (parseStateAnchors st)}
172−
173−lookupAnchor :: String -> ReaderT JSONPath (ConduitM e o Parse) (Maybe Value)
174−lookupAnchor name = gets (Map.lookup name . parseStateAnchors)
175−
176−data Warning = DuplicateKey JSONPath
177− deriving (Eq, Show)
178−
179−addWarning :: Warning -> ReaderT JSONPath (ConduitM e o Parse) ()
180−addWarning w = modify (modifyWarnings (w :))
181− where
182− modifyWarnings :: ([Warning] -> [Warning]) -> ParseState -> ParseState
183− modifyWarnings f st = st {parseStateWarnings = f (parseStateWarnings st)}
184−
185−data ParseState = ParseState {
186− parseStateAnchors :: Map String Value
187−, parseStateWarnings :: [Warning]
188−}
189−
190−type Parse = StateT ParseState (ResourceT IO)
191−
192−requireEvent :: Event -> ReaderT JSONPath (ConduitM Event o Parse) ()
193−requireEvent e = do
194− f <- lift CL.head
195− unless (f == Just e) $ liftIO $ throwIO $ UnexpectedEvent f $ Just e
196−
197−parse :: ReaderT JSONPath (ConduitM Event o Parse) Value
198−parse = do
199− docs <- parseAll
200− case docs of
201− [] -> return Null
202− [doc] -> return doc
203− _ -> liftIO $ throwIO MultipleDocuments
204−
205−parseAll :: ReaderT JSONPath (ConduitM Event o Parse) [Value]
206−parseAll = do
207− streamStart <- lift CL.head
208− case streamStart of
209− Nothing ->
210− -- empty string input
211− return []
212− Just EventStreamStart ->
213− -- empty file input, comment only string/file input
214− parseDocs
215− _ -> missed streamStart
216− where
217− parseDocs = do
218− documentStart <- lift CL.head
219− case documentStart of
220− Just EventStreamEnd -> return []
221− Just EventDocumentStart -> do
222− res <- parseO
223− requireEvent EventDocumentEnd
224− (res :) <$> parseDocs
225− _ -> missed documentStart
226− missed event = liftIO $ throwIO $ UnexpectedEvent event Nothing
227−
228−parseScalar :: ByteString -> Anchor -> Style -> Tag
229− -> ReaderT JSONPath (ConduitM Event o Parse) Text
230−parseScalar v a style tag = do
231− let res = decodeUtf8With lenientDecode v
232− mapM_ (defineAnchor (textToValue style tag res)) a
233− return res
234−
235−textToValue :: Style -> Tag -> Text -> Value
236−textToValue SingleQuoted _ t = String t
237−textToValue DoubleQuoted _ t = String t
238−textToValue _ StrTag t = String t
239−textToValue Folded _ t = String t
240−textToValue _ _ t
241− | t `elem` ["null", "Null", "NULL", "~", ""] = Null
242− | any (t `isLike`) ["y", "yes", "on", "true"] = Bool True
243− | any (t `isLike`) ["n", "no", "off", "false"] = Bool False
244− | Right x <- textToScientific t = Number x
245− | otherwise = String t
246− where x `isLike` ref = x `elem` [ref, T.toUpper ref, titleCased]
247− where titleCased = toUpper (T.head ref) `T.cons` T.tail ref
248−
249−textToScientific :: Text -> Either String Scientific
250−textToScientific = Atto.parseOnly (num <* Atto.endOfInput)
251− where
252− num = (fromInteger <$> ("0x" *> Atto.hexadecimal))
253− <|> (fromInteger <$> ("0o" *> octal))
254− <|> Atto.scientific
255−
256− octal = T.foldl' step 0 <$> Atto.takeWhile1 isOctalDigit
257− where
258− isOctalDigit c = (c >= '0' && c <= '7')
259− step a c = (a `shiftL` 3) .|. fromIntegral (ord c - 48)
260−
261−parseO :: ReaderT JSONPath (ConduitM Event o Parse) Value
262−parseO = do
263− me <- lift CL.head
264− case me of
265− Just (EventScalar v tag style a) -> textToValue style tag <$> parseScalar v a style tag
266− Just (EventSequenceStart _ _ a) -> parseS 0 a id
267− Just (EventMappingStart _ _ a) -> parseM mempty a M.empty
268− Just (EventAlias an) -> do
269− m <- lookupAnchor an
270− case m of
271− Nothing -> liftIO $ throwIO $ UnknownAlias an
272− Just v -> return v
273− _ -> liftIO $ throwIO $ UnexpectedEvent me Nothing
274−
275−parseS :: Int
276− -> Y.Anchor
277− -> ([Value] -> [Value])
278− -> ReaderT JSONPath (ConduitM Event o Parse) Value
279−parseS !n a front = do
280− me <- lift CL.peek
281− case me of
282− Just EventSequenceEnd -> do
283− lift $ CL.drop 1
284− let res = Array $ V.fromList $ front []
285− mapM_ (defineAnchor res) a
286− return res
287− _ -> do
288− o <- local (Index n :) parseO
289− parseS (succ n) a $ front . (:) o
290−
291−parseM :: Set Key
292− -> Y.Anchor
293− -> KeyMap Value
294− -> ReaderT JSONPath (ConduitM Event o Parse) Value
295−parseM mergedKeys a front = do
296− me <- lift CL.head
297− case me of
298− Just EventMappingEnd -> do
299− let res = Object front
300− mapM_ (defineAnchor res) a
301− return res
302− _ -> do
303− s <- case me of
304− Just (EventScalar v tag style a') -> fromText <$> parseScalar v a' style tag
305− Just (EventAlias an) -> do
306− m <- lookupAnchor an
307− case m of
308− Nothing -> liftIO $ throwIO $ UnknownAlias an
309− Just (String t) -> return $ fromText t
310− Just v -> liftIO $ throwIO $ NonStringKeyAlias an v
311− _ -> do
312− path <- ask
313− liftIO $ throwIO $ NonStringKey path
314−
315− (mergedKeys', al') <- local (Key s :) $ do
316− o <- parseO
317− let al = do
318− when (M.member s front && Set.notMember s mergedKeys) $ do
319− path <- reverse <$> ask
320− addWarning (DuplicateKey path)
321− return (Set.delete s mergedKeys, M.insert s o front)
322− if s == "<<"
323− then case o of
324− Object l -> return (merge l)
325− Array l -> return $ merge $ List.foldl' mergeObjects M.empty $ V.toList l
326− _ -> al
327− else al
328− parseM mergedKeys' a al'
329− where mergeObjects al (Object om) = M.union al om
330− mergeObjects al _ = al
331−
332− merge xs = (Set.fromList (M.keys xs List.\\ M.keys front), M.union front xs)
333−
334−parseSrc :: ReaderT JSONPath (ConduitM Event Void Parse) val
335− -> ConduitM () Event Parse ()
336− -> IO (val, ParseState)
337−parseSrc eventParser src = runResourceT $ runStateT
338− (runConduit $ src .| runReaderT eventParser [])
339− (ParseState Map.empty [])
340−
341−mkHelper :: ReaderT JSONPath (ConduitM Event Void Parse) val -- ^ parse libyaml events as Value or [Value]
342− -> (SomeException -> IO (Either ParseException a)) -- ^ what to do with unhandled exceptions
343− -> ((val, ParseState) -> Either ParseException a) -- ^ further transform and parse results
344− -> ConduitM () Event Parse () -- ^ the libyaml event (string/file) source
345− -> IO (Either ParseException a)
346−mkHelper eventParser onOtherExc extractResults src = catches
347− (extractResults <$> parseSrc eventParser src)
348− [ Handler $ \pe -> return $ Left (pe :: ParseException)
349− , Handler $ \ye -> return $ Left $ InvalidYaml $ Just (ye :: YamlException)
350− , Handler $ \sae -> throwIO (sae :: SomeAsyncException)
351− , Handler onOtherExc
352− ]
353−
354−decodeHelper :: FromJSON a
355− => ConduitM () Y.Event Parse ()
356− -> IO (Either ParseException ([Warning], Either String a))
357−decodeHelper = mkHelper parse throwIO $ \(v, st) ->
358− Right (parseStateWarnings st, parseEither parseJSON v)
359−
360−decodeAllHelper :: FromJSON a
361− => ConduitM () Event Parse ()
362− -> IO (Either ParseException ([Warning], Either String [a]))
363−decodeAllHelper = mkHelper parseAll throwIO $ \(vs, st) ->
364− Right (parseStateWarnings st, mapM (parseEither parseJSON) vs)
365−
366−catchLeft :: SomeException -> IO (Either ParseException a)
367−catchLeft = return . Left . OtherParseException
368−
369−decodeHelper_ :: FromJSON a
370− => ConduitM () Event Parse ()
371− -> IO (Either ParseException ([Warning], a))
372−decodeHelper_ = mkHelper parse catchLeft $ \(v, st) ->
373− case parseEither parseJSON v of
374− Left e -> Left $ AesonException e
375− Right x -> Right (parseStateWarnings st, x)
376−
377−decodeAllHelper_ :: FromJSON a
378− => ConduitM () Event Parse ()
379− -> IO (Either ParseException ([Warning], [a]))
380−decodeAllHelper_ = mkHelper parseAll catchLeft $ \(vs, st) ->
381− case mapM (parseEither parseJSON) vs of
382− Left e -> Left $ AesonException e
383− Right xs -> Right (parseStateWarnings st, xs)
384−
385−type StringStyle = Text -> ( Tag, Style )
386−
387−-- | Encodes a string with the supplied style. This function handles the empty
388−-- string case properly to avoid https://github.com/snoyberg/yaml/issues/24
389−--
390−-- @since 0.11.2.0
391−stringScalar :: StringStyle -> Maybe Text -> Text -> Event
392−stringScalar _ anchor "" = EventScalar "" NoTag SingleQuoted (T.unpack <$> anchor)
393−stringScalar stringStyle anchor s = EventScalar (encodeUtf8 s) tag style (T.unpack <$> anchor)
394− where
395− ( tag, style ) = stringStyle s
396−
397−-- |
398−-- @since 0.11.2.0
399−defaultStringStyle :: StringStyle
400−defaultStringStyle = \s ->
401− case () of
402− ()
403− | "\n" `T.isInfixOf` s -> ( NoTag, Literal )
404− | isSpecialString s -> ( NoTag, SingleQuoted )
405− | otherwise -> ( NoTag, PlainNoTag )
406−
407−-- | Determine whether a string must be quoted in YAML and can't appear as plain text.
408−-- Useful if you want to use 'setStringStyle'.
409−--
410−-- @since 0.10.2.0
411−isSpecialString :: Text -> Bool
412−isSpecialString s = s `HashSet.member` specialStrings || isNumeric s
413−
414−-- | Strings which must be escaped so as not to be treated as non-string scalars.
415−--
416−-- @since 0.8.32
417−specialStrings :: HashSet.HashSet Text
418−specialStrings = HashSet.fromList $ T.words
419− "y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL ~ *"
420−
421−-- |
422−-- @since 0.8.32
423−isNumeric :: Text -> Bool
424−isNumeric = either (const False) (const True) . textToScientific
425−
426−-- | Encode a value as a YAML document stream.
427−--
428−-- @since 0.11.2.0
429−objToStream :: ToJSON a => StringStyle -> a -> [Y.Event]
430−objToStream stringStyle o =
431− (:) EventStreamStart
432− . (:) EventDocumentStart
433− $ objToEvents stringStyle o
434− [ EventDocumentEnd
435− , EventStreamEnd
436− ]
437−
438−-- | Encode a value as a list of 'Event's.
439−--
440−-- @since 0.11.2.0
441−objToEvents :: ToJSON a => StringStyle -> a -> [Y.Event] -> [Y.Event]
442−objToEvents stringStyle = objToEvents' . toJSON
443− where
444− objToEvents' (Array list) rest =
445− EventSequenceStart NoTag AnySequence Nothing
446− : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list)
447−
448− objToEvents' (Object o) rest =
449− EventMappingStart NoTag AnyMapping Nothing
450− : foldr pairToEvents (EventMappingEnd : rest) (M.toList o)
451− where
452− pairToEvents :: Pair -> [Y.Event] -> [Y.Event]
453− pairToEvents (k, v) = objToEvents' (String $ toText k) . objToEvents' v
454−
455− objToEvents' (String s) rest = stringScalar stringStyle Nothing s : rest
456−
457− objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest
458−
459− objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest
460− objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest
461−
462− objToEvents' (Number s) rest =
463− let builder
464− -- Special case the 0 exponent to remove the trailing .0
465− | base10Exponent s == 0 = BB.integerDec $ coefficient s
466− | otherwise = scientificBuilder s
467− lbs = BB.toLazyByteString builder
468− bs = BL.toStrict lbs
469− in EventScalar bs IntTag PlainNoTag Nothing : rest
yaml/src/Data/Yaml/Parser.hsdeleted−204
@@ -1,204 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−-- | NOTE: This module is a highly experimental preview release. It may change
5−-- drastically, or be entirely removed, in a future release.
6−module Data.Yaml.Parser where
7−
8−import Control.Applicative
9−import Control.Exception (Exception)
10−import Control.Monad (MonadPlus (..), liftM, ap)
11−import Control.Monad.Trans.Class (lift)
12−import Control.Monad.Trans.Resource (MonadThrow, throwM)
13−import Control.Monad.Trans.Writer.Strict (tell, WriterT)
14−import Data.ByteString (ByteString)
15−import Data.Conduit
16−import Data.Conduit.Lift (runWriterC)
17−import qualified Data.Map as Map
18−#if !MIN_VERSION_base(4,8,0)
19−import Data.Monoid (Monoid (..))
20−#endif
21−#if !MIN_VERSION_base(4,11,0)
22−import Data.Semigroup (Semigroup(..))
23−#endif
24−import Data.Text (Text, pack, unpack)
25−import Data.Text.Encoding (decodeUtf8)
26−import Data.Text.Read (signed, decimal)
27−import Data.Typeable (Typeable)
28−
29−import Text.Libyaml
30−
31−newtype YamlParser a = YamlParser
32− { unYamlParser :: AnchorMap -> Either Text a
33− }
34−instance Functor YamlParser where
35− fmap = liftM
36−instance Applicative YamlParser where
37− pure = YamlParser . const . Right
38− (<*>) = ap
39−instance Alternative YamlParser where
40− empty = fail "empty"
41− (<|>) = mplus
42−instance Semigroup (YamlParser a) where
43− (<>) = mplus
44−instance Monoid (YamlParser a) where
45− mempty = fail "mempty"
46−#if !MIN_VERSION_base(4,11,0)
47− mappend = (<>)
48−#endif
49−instance Monad YamlParser where
50− return = pure
51− YamlParser f >>= g = YamlParser $ \am ->
52− case f am of
53− Left t -> Left t
54− Right x -> unYamlParser (g x) am
55−#if MIN_VERSION_base(4,13,0)
56−instance MonadFail YamlParser where
57−#endif
58− fail = YamlParser . const . Left . pack
59−instance MonadPlus YamlParser where
60− mzero = fail "mzero"
61− mplus a b = YamlParser $ \am ->
62− case unYamlParser a am of
63− Left _ -> unYamlParser b am
64− x -> x
65−
66−lookupAnchor :: AnchorName -> YamlParser (Maybe YamlValue)
67−lookupAnchor name = YamlParser $ Right . Map.lookup name
68−
69−withAnchor :: AnchorName -> Text -> (YamlValue -> YamlParser a) -> YamlParser a
70−withAnchor name expected f = do
71− mv <- lookupAnchor name
72− case mv of
73− Nothing -> fail $ unpack expected ++ ": unknown alias " ++ name
74− Just v -> f v
75−
76−withMapping :: Text -> ([(Text, YamlValue)] -> YamlParser a) -> YamlValue -> YamlParser a
77−withMapping _ f (Mapping m _) = f m
78−withMapping expected f (Alias an) = withAnchor an expected $ withMapping expected f
79−withMapping expected _ v = typeMismatch expected v
80−
81−withSequence :: Text -> ([YamlValue] -> YamlParser a) -> YamlValue -> YamlParser a
82−withSequence _ f (Sequence s _) = f s
83−withSequence expected f (Alias an) = withAnchor an expected $ withSequence expected f
84−withSequence expected _ v = typeMismatch expected v
85−
86−withText :: Text -> (Text -> YamlParser a) -> YamlValue -> YamlParser a
87−withText _ f (Scalar s _ _ _) = f $ decodeUtf8 s
88−withText expected f (Alias an) = withAnchor an expected $ withText expected f
89−withText expected _ v = typeMismatch expected v
90−
91−typeMismatch :: Text -> YamlValue -> YamlParser a
92−typeMismatch expected v =
93− fail $ concat
94− [ "Expected "
95− , unpack expected
96− , ", but got: "
97− , t
98− ]
99− where
100− t = case v of
101− Mapping _ _ -> "mapping"
102− Sequence _ _ -> "sequence"
103− Scalar _ _ _ _ -> "scalar"
104− Alias _ -> "alias"
105−
106−class FromYaml a where
107− fromYaml :: YamlValue -> YamlParser a
108−instance FromYaml YamlValue where
109− fromYaml = return
110−instance FromYaml a => FromYaml [a] where
111− fromYaml = withSequence "[a]" (mapM fromYaml)
112−instance FromYaml Text where
113− fromYaml = withText "Text" return
114−instance FromYaml Int where
115− fromYaml =
116− withText "Int" go
117− where
118− go t =
119− case signed decimal t of
120− Right (i, "") -> return i
121− _ -> fail $ "Invalid Int: " ++ unpack t
122−
123−data YamlValue
124− = Mapping [(Text, YamlValue)] Anchor
125− | Sequence [YamlValue] Anchor
126− | Scalar ByteString Tag Style Anchor
127− | Alias AnchorName
128− deriving Show
129−
130−type AnchorMap = Map.Map AnchorName YamlValue
131−data RawDoc = RawDoc YamlValue AnchorMap
132− deriving Show
133−
134−parseRawDoc :: (FromYaml a, MonadThrow m) => RawDoc -> m a
135−parseRawDoc (RawDoc val am) =
136− case unYamlParser (fromYaml val) am of
137− Left t -> throwM $ FromYamlException t
138− Right x -> return x
139−
140−(.:) :: FromYaml a => [(Text, YamlValue)] -> Text -> YamlParser a
141−o .: k =
142− case lookup k o of
143− Nothing -> fail $ "Key not found: " ++ unpack k
144− Just v -> fromYaml v
145−
146−data YamlParseException
147− = UnexpectedEndOfEvents
148− | UnexpectedEvent Event
149− | FromYamlException Text
150− deriving (Show, Typeable)
151−instance Exception YamlParseException
152−
153−sinkValue :: MonadThrow m => ConduitM Event o (WriterT AnchorMap m) YamlValue
154−sinkValue =
155− start
156− where
157− start = await >>= maybe (throwM UnexpectedEndOfEvents) go
158−
159− tell' Nothing val = return val
160− tell' (Just name) val = do
161− lift $ tell $ Map.singleton name val
162− return val
163−
164− go EventStreamStart = start
165− go EventDocumentStart = start
166− go (EventAlias a) = return $ Alias a
167− go (EventScalar a b c d) = tell' d $ Scalar a b c d
168− go (EventSequenceStart _tag _style mname) = do
169− vals <- goS id
170− let val = Sequence vals mname
171− tell' mname val
172− go (EventMappingStart _tag _style mname) = do
173− pairs <- goM id
174− let val = Mapping pairs mname
175− tell' mname val
176−
177− go e = throwM $ UnexpectedEvent e
178−
179− goS front = do
180− me <- await
181− case me of
182− Nothing -> throwM UnexpectedEndOfEvents
183− Just EventSequenceEnd -> return $ front []
184− Just e -> do
185− val <- go e
186− goS (front . (val:))
187−
188− goM front = do
189− mk <- await
190− case mk of
191− Nothing -> throwM UnexpectedEndOfEvents
192− Just EventMappingEnd -> return $ front []
193− Just (EventScalar a b c d) -> do
194− _ <- tell' d $ Scalar a b c d
195− let k = decodeUtf8 a
196− v <- start
197− goM (front . ((k, v):))
198− Just e -> throwM $ UnexpectedEvent e
199−
200−sinkRawDoc :: MonadThrow m => ConduitM Event o m RawDoc
201−sinkRawDoc = uncurry RawDoc <$> runWriterC sinkValue
202−
203−readYamlFile :: FromYaml a => FilePath -> IO a
204−readYamlFile fp = runConduitRes (decodeFile fp .| sinkRawDoc) >>= parseRawDoc
yaml/src/Data/Yaml/Pretty.hsdeleted−102
@@ -1,102 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−-- | Prettier YAML encoding.
3−--
4−-- @since 0.8.13
5−module Data.Yaml.Pretty
6− ( encodePretty
7− , Config
8− , getConfCompare
9− , setConfCompare
10− , getConfDropNull
11− , setConfDropNull
12− , defConfig
13− , pretty
14− ) where
15−
16−import Prelude hiding (null)
17−
18−#if !MIN_VERSION_base(4,8,0)
19−import Control.Applicative ((<$>))
20−#endif
21−import Data.Bifunctor (first)
22−#if MIN_VERSION_aeson(2,0,0)
23−import qualified Data.Aeson.Key as K
24−import qualified Data.Aeson.KeyMap as HM
25−#else
26−import qualified Data.HashMap.Strict as HM
27−#endif
28−import Data.Aeson.Types
29−import Data.ByteString (ByteString)
30−import Data.Function (on)
31−import Data.List (sortBy)
32−#if !MIN_VERSION_base(4,8,0)
33−import Data.Monoid
34−#endif
35−import Data.Text (Text)
36−import qualified Data.Vector as V
37−
38−import Data.Yaml.Builder
39−
40−#if MIN_VERSION_aeson(2,0,0)
41−toText :: Key -> Text
42−toText = K.toText
43−#else
44−toText :: Key -> Text
45−toText = id
46−
47−type Key = Text
48−#endif
49−
50−-- |
51−-- @since 0.8.13
52−data Config = Config
53− { confCompare :: Text -> Text -> Ordering -- ^ Function used to sort keys in objects
54− , confDropNull :: Bool -- ^ Drop null values from objects
55− }
56−
57−-- | The default configuration: do not sort objects or drop keys
58−--
59−-- @since 0.8.13
60−defConfig :: Config
61−defConfig = Config mempty False
62−
63−-- |
64−-- @since 0.8.13
65−getConfCompare :: Config -> Text -> Text -> Ordering
66−getConfCompare = confCompare
67−
68−-- | Sets ordering for object keys
69−--
70−-- @since 0.8.13
71−setConfCompare :: (Text -> Text -> Ordering) -> Config -> Config
72−setConfCompare cmp c = c { confCompare = cmp }
73−
74−-- |
75−-- @since 0.8.24
76−getConfDropNull :: Config -> Bool
77−getConfDropNull = confDropNull
78−
79−-- | Drop entries with `Null` value from objects, if set to `True`
80−--
81−-- @since 0.8.24
82−setConfDropNull :: Bool -> Config -> Config
83−setConfDropNull m c = c { confDropNull = m }
84−
85−pretty :: Config -> Value -> YamlBuilder
86−pretty cfg = go
87− where go (Object o) = let sort = sortBy (confCompare cfg `on` fst)
88− select
89− | confDropNull cfg = HM.filter (/= Null)
90− | otherwise = id
91− in mapping (sort $ fmap (first toText) $ HM.toList $ HM.map go $ select o)
92− go (Array a) = array (go <$> V.toList a)
93− go Null = null
94− go (String s) = string s
95− go (Number n) = scientific n
96− go (Bool b) = bool b
97−
98−-- | Configurable 'encode'.
99−--
100−-- @since 0.8.13
101−encodePretty :: ToJSON a => Config -> a -> ByteString
102−encodePretty cfg = toByteString . pretty cfg . toJSON
yaml/src/Data/Yaml/TH.hsdeleted−80
@@ -1,80 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−
5−module Data.Yaml.TH
6− ( -- * Decoding
7− yamlQQ
8−#if MIN_VERSION_template_haskell(2,9,0)
9− , decodeFile
10−#endif
11− -- * Re-exports from "Data.Yaml"
12− , Value (..)
13− , Parser
14− , Object
15− , Array
16− , object
17− , array
18− , (.=)
19− , (.:)
20− , (.:?)
21− , (.!=)
22− , FromJSON (..)
23− ) where
24−
25−import Data.Text.Encoding
26−import qualified Data.Text as T
27−import Language.Haskell.TH
28−import Language.Haskell.TH.Syntax
29−import Language.Haskell.TH.Quote
30−
31−import Data.Yaml hiding (decodeFile)
32−
33−-- | Decode a YAML file at compile time. Only available on GHC version @7.8.1@
34−-- or higher.
35−--
36−-- @since 0.8.19.0
37−--
38−-- ==== __Examples__
39−--
40−-- @
41−-- {-\# LANGUAGE TemplateHaskell \#-}
42−--
43−-- config :: Config
44−-- config = $$('decodeFile' "config.yaml")
45−-- @
46−decodeFile :: forall a. (Lift a, FromJSON a) => FilePath -> Q (TExp a)
47−decodeFile path = do
48− addDependentFile path
49− x <- runIO $ decodeFileThrow path
50− fmap TExp (lift (x :: a))
51−
52−yamlExp :: String -> Q Exp
53−yamlExp input = do
54− val <- runIO $ decodeThrow $ encodeUtf8 $ T.pack input
55− lift (val :: Value)
56−
57−-- | A @QuasiQuoter@ for YAML.
58−--
59−-- @since 0.8.28.0
60−--
61−-- ==== __Examples__
62−--
63−-- @
64−-- {-\# LANGUAGE QuasiQuotes \#-}
65−-- import Data.Yaml.TH
66−--
67−-- value :: Value
68−-- value = [yamlQQ|
69−-- name: John Doe
70−-- age: 23
71−-- |]
72−-- @
73−yamlQQ :: QuasiQuoter
74−yamlQQ = QuasiQuoter {
75− quoteExp = yamlExp
76−, quotePat = notDefined "quotePat"
77−, quoteType = notDefined "quoteType"
78−, quoteDec = notDefined "quoteDec"
79−} where
80− notDefined name _ = fail (name ++ " is not defined for yamlQQ")
yaml/test/Data/Yaml/IncludeSpec.hsdeleted−139
@@ -1,139 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE QuasiQuotes #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−module Data.Yaml.IncludeSpec (main, spec) where
5−
6−import Test.Hspec
7−import Data.List (isPrefixOf)
8−import qualified Data.ByteString.Lazy as LB
9−import Data.Aeson
10−#if MIN_VERSION_aeson(2,2,0)
11−import Data.Aeson.Types (JSONPathElement(..))
12−#else
13−import Data.Aeson.Internal (JSONPathElement(..))
14−#endif
15−import Data.Yaml (ParseException(InvalidYaml))
16−import Data.Yaml.Include
17−import Data.Yaml.Internal
18−import Text.Libyaml (YamlException(YamlException))
19−import Test.Mockery.Directory
20−import Text.RawString.QQ
21−import Data.Yaml.TH (yamlQQ)
22−
23−main :: IO ()
24−main = hspec spec
25−
26−asInt :: Int -> Int
27−asInt = id
28−
29−spec :: Spec
30−spec = do
31− describe "decodeFile" $ do
32− it "supports includes" $ do
33− decodeFile "test/resources/foo.yaml" `shouldReturn` Just (object
34− [ "foo" .= asInt 23
35− , "bar" .= object
36− [ "one" .= asInt 1
37− , "two" .= asInt 2
38− ]
39− , "baz" .= asInt 42
40− ])
41−
42− it "supports recursive includes" $ do
43− decodeFile "test/resources/baz.yaml" `shouldReturn` Just (object
44− [ "foo" .= object
45− [ "foo" .= asInt 23
46− , "bar" .= object
47− [ "one" .= asInt 1
48− , "two" .= asInt 2
49− ]
50− , "baz" .= asInt 42
51− ]
52− ])
53−
54− it "aborts on cyclic includes" $ do
55− (decodeFile "test/resources/loop/foo.yaml" :: IO (Maybe Value)) `shouldThrow` anyException
56−
57− context "when file does not exist" $ do
58− it "throws Left (InvalidYaml (Just (YamlException \"Yaml file not found: ...\")))" $ do
59− (decodeFile "./does_not_exist.yaml" :: IO (Maybe Value)) `shouldThrow` isYamlFileNotFoundException
60−
61− context "with a 1K stack size limit" $ around_ inTempDirectory $ do
62− context "with a large list" $ do
63− it "succeeds" $ do
64− let
65− xs :: [Value]
66− xs = replicate 5000 (Number 23)
67− LB.writeFile "foo.yaml" (encode xs)
68− decodeFile "foo.yaml" `shouldReturn` Just xs
69−
70− describe "decodeFileEither" $ do
71− context "when file does not exist" $ do
72− it "returns Left (InvalidYaml (Just (YamlException \"Yaml file not found: ...\")))" $ do
73− (decodeFileEither "./does_not_exist.yaml" :: IO (Either ParseException Value)) >>=
74− (`shouldSatisfy` either isYamlFileNotFoundException (const False))
75−
76− describe "decodeFileWithWarnings" $ around_ inTempDirectory $ do
77− it "warns on duplicate keys" $ do
78− writeFile "foo.yaml" [r|
79− foo: 23
80− foo: bar
81− |]
82− Right result <- decodeFileWithWarnings "foo.yaml"
83− result `shouldBe` ([DuplicateKey [Key "foo"]], [yamlQQ|
84− foo: bar
85− |])
86−
87− it "warns on nested duplicate keys" $ do
88− writeFile "foo.yaml" [r|
89− foo:
90− - 42
91− - bar: 23
92− bar: baz
93− |]
94− Right result <- decodeFileWithWarnings "foo.yaml"
95− result `shouldBe` ([DuplicateKey [Key "foo", Index 1, Key "bar"]], [yamlQQ|
96− foo:
97− - 42
98− - bar: baz
99− |])
100−
101− context "when overriding a merged key" $ do
102− it "does not warn" $ do
103− writeFile "foo.yaml" [r|
104− foo-1: &my-ref
105− bar: 23
106− foo-2:
107− <<: *my-ref
108− bar: 42
109− |]
110− Right result <- decodeFileWithWarnings "foo.yaml"
111− result `shouldBe` ([], [yamlQQ|
112− foo-1:
113− bar: 23
114− foo-2:
115− bar: 42
116− |])
117−
118− context "when overriding twice" $ do
119− it "warns" $ do
120− writeFile "foo.yaml" [r|
121− foo-1: &my-ref
122− bar: 23
123− foo-2:
124− <<: *my-ref
125− bar: 42
126− bar: 65
127− |]
128− Right result <- decodeFileWithWarnings "foo.yaml"
129− result `shouldBe` ([DuplicateKey [Key "foo-2", Key "bar"]], [yamlQQ|
130− foo-1:
131− bar: 23
132− foo-2:
133− bar: 65
134− |])
135−
136−isYamlFileNotFoundException :: ParseException -> Bool
137−isYamlFileNotFoundException (InvalidYaml (Just (YamlException msg)))
138− | "Yaml file not found: " `isPrefixOf` msg = True
139−isYamlFileNotFoundException _ = False
yaml/test/Data/Yaml/THSpec.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE QuasiQuotes #-}
3−module Data.Yaml.THSpec (spec) where
4−
5−import Test.Hspec
6−import Data.Aeson
7−
8−import Data.Yaml.TH
9−
10−spec :: Spec
11−spec = do
12− describe "yamlQQ" $ do
13− it "parses yaml" $ do
14− [yamlQQ|
15− name: John Doe
16− age: 23
17− |] `shouldBe` object ["name" .= String "John Doe", "age" .= Number 23]
yaml/test/Data/YamlSpec.hsdeleted−899
@@ -1,899 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE PackageImports #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−{-# LANGUAGE TemplateHaskell #-}
6−{-# LANGUAGE TupleSections #-}
7−
8−module Data.YamlSpec (main, spec) where
9−
10−import qualified Text.Libyaml as Y
11−import qualified Data.ByteString as BS
12−import qualified Data.ByteString.Char8 as B8
13−import Data.Int (Int64)
14−import qualified Data.Scientific as S
15−
16−import Test.HUnit hiding (Test, path)
17−
18−import Data.Conduit (runConduitRes, (.|), ConduitM)
19−import qualified Data.Conduit.List as CL
20−
21−import Control.Monad
22−import Control.Exception (try, SomeException)
23−import Test.Hspec
24−import Test.Hspec.QuickCheck
25−import Data.Either.Compat
26−import System.Directory (createDirectory, createDirectoryIfMissing)
27−import Test.Mockery.Directory
28−
29−import qualified Data.Yaml as D
30−import qualified Data.Yaml.Builder as B
31−import qualified Data.Yaml.Internal as Internal
32−import qualified Data.Yaml.Pretty as Pretty
33−import Data.Yaml (object, array, (.=))
34−import Data.Maybe
35−import qualified Data.HashMap.Strict as HM
36−#if MIN_VERSION_aeson(2,0,0)
37−import qualified Data.Aeson.KeyMap as M
38−import qualified Data.Aeson.Key as K
39−import Data.Aeson.KeyMap (KeyMap)
40−#else
41−import qualified Data.HashMap.Strict as M
42−#endif
43−import qualified Data.Text as T
44−import Data.Aeson.TH
45−import Data.Scientific (Scientific)
46−import Data.String (fromString)
47−import Data.Text (Text)
48−import Data.Text.Encoding (decodeUtf8, encodeUtf8)
49−import Data.Vector (Vector)
50−import qualified Data.Vector as V
51−import Data.HashMap.Strict (HashMap)
52−import qualified Data.HashMap.Strict as HM
53−import System.IO (hClose)
54−import System.IO.Temp (withSystemTempFile)
55−
56−#if MIN_VERSION_aeson(2,0,0)
57−fromText :: T.Text -> K.Key
58−fromText = K.fromText
59−
60−toText :: K.Key -> T.Text
61−toText = K.toText
62−#else
63−fromText :: T.Text -> T.Text
64−fromText = id
65−
66−toText :: Key -> T.Text
67−toText = id
68−
69−type KeyMap a = M.HashMap Text a
70−type Key = Text
71−#endif
72−
73−data TestJSON = TestJSON
74− { string :: Text
75− , number :: Int
76− , anArray :: Vector Text
77− , hash :: HashMap Text Text
78− , extrastring :: Text
79− } deriving (Show, Eq)
80−
81−deriveJSON defaultOptions ''TestJSON
82−
83−testJSON :: TestJSON
84−testJSON = TestJSON
85− { string = "str"
86− , number = 2
87− , anArray = V.fromList ["a", "b"]
88− , hash = HM.fromList [("key1", "value1"), ("key2", "value2")]
89− , extrastring = "1234-foo"
90− }
91−
92−shouldDecode :: (Show a, D.FromJSON a, Eq a) => B8.ByteString -> a -> IO ()
93−shouldDecode bs expected = do
94− actual <- D.decodeThrow bs
95− actual `shouldBe` expected
96−
97−shouldDecodeAll :: (Show a, D.FromJSON a, Eq a) => B8.ByteString -> [a] -> IO ()
98−shouldDecodeAll bs expected = do
99− actual <- D.decodeAllThrow bs
100− actual `shouldBe` expected
101−
102−shouldDecodeEvents :: B8.ByteString -> [Y.Event] -> IO ()
103−shouldDecodeEvents bs expected = do
104− actual <- runConduitRes $ Y.decode bs .| CL.consume
105− map anyStyle actual `shouldBe` map anyStyle expected
106−
107−anyStyle :: Y.Event -> Y.Event
108−anyStyle (Y.EventScalar bs tag _ anchor) = Y.EventScalar bs tag Y.Any anchor
109−anyStyle (Y.EventSequenceStart tag _ anchor) = Y.EventSequenceStart tag Y.AnySequence anchor
110−anyStyle (Y.EventMappingStart tag _ anchor) = Y.EventMappingStart tag Y.AnyMapping anchor
111−anyStyle event = event
112−
113−testEncodeWith :: Y.FormatOptions -> [Y.Event] -> IO BS.ByteString
114−testEncodeWith opts es = runConduitRes $ CL.sourceList (eventStream es) .| Y.encodeWith opts
115−
116−eventStream :: [Y.Event] -> [Y.Event]
117−eventStream events =
118− [Y.EventStreamStart, Y.EventDocumentStart]
119− ++ events
120− ++ [Y.EventDocumentEnd, Y.EventStreamEnd]
121−
122−main :: IO ()
123−main = hspec spec
124−
125−spec :: Spec
126−spec = do
127− describe "streaming" $ do
128− it "count scalars with anchor" caseCountScalarsWithAnchor
129− it "count sequences with anchor" caseCountSequencesWithAnchor
130− it "count mappings with anchor" caseCountMappingsWithAnchor
131− it "count sequences with custom tag" caseCountSequenceTags
132− it "count mappings with custom tag" caseCountMappingTags
133− it "count count sequences with ! tag" caseCountEmptySequenceTags
134− it "count count mappings with ! tag" caseCountEmptyMappingTags
135− it "count block style sequences" caseCountBlockStyleSequences
136− it "count flow style sequences" caseCountFlowStyleSequences
137− it "count block style mappings" caseCountBlockStyleMappings
138− it "count flow style mappings" caseCountFlowStyleMappings
139− it "count aliases" caseCountAliases
140− it "count scalars" caseCountScalars
141− it "largest string" caseLargestString
142− it "encode/decode" caseEncodeDecode
143− it "encode/decode events" caseEncodeDecodeEvents
144− it "encode/decode file" caseEncodeDecodeFile
145− it "interleaved encode/decode" caseInterleave
146− it "decode invalid document (without segfault)" caseDecodeInvalidDocument
147− describe "Data.Yaml" $ do
148− it "encode/decode" caseEncodeDecodeData
149− it "encode/decode file" caseEncodeDecodeFileData
150− it "encode/decode files with non-ASCII names" caseEncodeDecodeNonAsciiFileData
151− it "encode/decode strings" caseEncodeDecodeStrings
152− it "decode invalid file" caseDecodeInvalid
153− it "processes datatypes" caseDataTypes
154− it "encode invalid numbers" caseEncodeInvalidNumbers
155− describe "Data.Yaml.Pretty" $ do
156− it "encode/decode" caseEncodeDecodeDataPretty
157− it "encode/decode strings" caseEncodeDecodeStringsPretty
158− it "processes datatypes" caseDataTypesPretty
159− describe "Data.Yaml.Builder" $ do
160− it "encode/decode" caseEncodeDecodeDataBuilder
161− it "encode/decode complex mapping" caseEncodeDecodeComplexMappingBuilder
162− describe "Data.Yaml aliases" $ do
163− it "simple scalar alias" caseSimpleScalarAlias
164− it "simple sequence alias" caseSimpleSequenceAlias
165− it "simple mapping alias" caseSimpleMappingAlias
166− it "mapping alias before anchor" caseMappingAliasBeforeAnchor
167− it "mapping alias inside anchor" caseMappingAliasInsideAnchor
168− it "scalar alias overriding" caseScalarAliasOverriding
169− describe "Data.Yaml merge keys" $ do
170− it "test uniqueness of keys" caseAllKeysShouldBeUnique
171− it "test mapping merge" caseSimpleMappingMerge
172− it "test sequence of mappings merging" caseMergeSequence
173− describe "numbers" $ do
174− it "parses as string when quoted" caseQuotedNumber
175− it "parses as number when unquoted" caseUnquotedNumber
176− it "parses as number !!str is present" caseAttribNumber
177− it "integers have no decimals" caseIntegerDecimals
178− describe "booleans" $ do
179− it "parses when all lowercase" caseLowercaseBool
180− it "parses when all uppercase" caseUppercaseBool
181− it "parses when titlecase" caseTitlecaseBool
182− describe "empty input" $ do
183− it "parses as Null" caseEmptyInput
184− it "parses as Null from file" caseEmptyInputFile
185− describe "comment only input" $ do
186− it "parses as Null" caseCommentOnlyInput
187− it "parses as Null from file" caseCommentOnlyInputFile
188− describe "alias stripping" $ do
189− it "works" caseStripAlias
190− describe "nulls" $ do
191− checkNull "null"
192− checkNull "Null"
193− checkNull "NULL"
194− checkNull "~"
195− checkNull ""
196−
197− describe "pretty output" $ do
198− it "simple nulls" $ D.encode (object ["foo" .= D.Null]) `shouldBe` "foo: null\n"
199− it "simple numbers" $ D.encode (object ["foo" .= (4 :: Int)]) `shouldBe` "foo: 4\n"
200− it "True" $ D.encode (object ["foo" .= True]) `shouldBe` "foo: true\n"
201− it "False" $ D.encode (object ["foo" .= False]) `shouldBe` "foo: false\n"
202− it "simple string" $ D.encode (object ["foo" .= ("bar" :: T.Text)]) `shouldBe` "foo: bar\n"
203− it "*" $ D.encode (object ["foo" .= ("*" :: T.Text)]) `shouldBe` "foo: '*'\n"
204−
205− describe "special keys" $ do
206− let tester key = it (T.unpack key) $
207− let value = object [fromText key .= True]
208− in D.encode value `shouldDecode` value
209− mapM_ tester specialStrings
210−
211− describe "special values" $ do
212− let tester value = it (T.unpack value) $
213− let value' = object ["foo" .= value]
214− in D.encode value' `shouldDecode` value'
215− mapM_ tester specialStrings
216−
217− describe "decodeFileEither" $ do
218− it "loads YAML through JSON into Haskell data" $ do
219− tj <- either (error . show) id `fmap` D.decodeFileEither "test/json.yaml"
220− tj `shouldBe` testJSON
221−
222− context "when file does not exist" $ do
223− it "returns Left" $ do
224− (D.decodeFileEither "./does_not_exist.yaml" :: IO (Either D.ParseException D.Value)) >>= (`shouldSatisfy` isLeft)
225−
226− describe "multiple document support" $ do
227− it "decodes zero-length input" $
228− "" `shouldDecodeAll` ([] :: [D.Value])
229− it "decodes comment-only input" $
230− "# foo\n# bar" `shouldDecodeAll` ([] :: [D.Value])
231− it "decodes a single document stream" $
232− "foo: true" `shouldDecodeAll` [object ["foo" .= True]]
233− it "decodes multiple documents" $
234− "--- 1\n--- 2" `shouldDecodeAll` [D.Number 1, D.Number 2]
235−
236− describe "round-tripping of special scalars" $ do
237− let special = words "y Y On ON false 12345 12345.0 12345a 12e3"
238− forM_ special $ \w -> it w $
239− let v = object ["word" .= w]
240− in D.encode v `shouldDecode` v
241− it "no tags" $ D.encode (object ["word" .= ("true" :: String)]) `shouldBe` "word: 'true'\n"
242−
243− it "aliases in keys #49" caseIssue49
244−
245− it "serialization of +123 #64" $ do
246− D.encode ("+123" :: String) `shouldDecode` ("+123" :: String)
247−
248− it "preserves Scientific precision" casePreservesScientificPrecision
249−
250− it "truncates files" caseTruncatesFiles
251−
252− it "encode quotes special keys #137" $ caseSpecialKeys D.encode
253−
254− it "encodePretty quotes special keys #179" $ caseSpecialKeys (Pretty.encodePretty Pretty.defConfig)
255−
256− describe "non-decimal numbers #135" $ do
257− let go str val = it str $ encodeUtf8 (T.pack str) `shouldDecode` val
258− go "12345" (12345 :: Int)
259− go "+12345" (12345 :: Int)
260− go "0o14" (12 :: Int)
261− go "0o123" (83 :: Int)
262− go "0xC" (12 :: Int)
263− go "0xc" (12 :: Int)
264− go "0xdeadBEEF" (3735928559 :: Int64)
265− go "0xDEADBEEF" (3735928559 :: Int64)
266− go "1.23015e+3" (1230.15 :: Scientific)
267− go "12.3015e+02" (1230.15 :: Scientific)
268− go "1230.15" (1230.15 :: Scientific)
269−
270− describe "Text.Libyaml with default tag rendering" $ do
271− let enc = testEncodeWith Y.defaultFormatOptions
272− it "elides custom sequence tags" $
273− enc taggedSequence `shouldReturn` "[]\n"
274− it "elides custom mapping tags" $
275− enc taggedMapping `shouldReturn` "{}\n"
276− it "elides default sequence tags" $
277− enc defaultTaggedSequence `shouldReturn` "[]\n"
278− it "elides default mapping tags" $
279− enc defaultTaggedMapping `shouldReturn` "{}\n"
280− it "handles NoTag on sequences" $
281− enc untaggedSequence `shouldReturn` "[]\n"
282− it "handles NoTag on mappings" $
283− enc untaggedMapping `shouldReturn` "{}\n"
284− it "handles mixed tag usages but elides all mapping and sequence tags" $
285− enc mixedTagSampleA `shouldReturn` "- {}\n"
286− it "in combination of tags, anchors and styles, outputs only the scalar tags" $
287− enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c [&d !!null '']\n"
288− it "outputs tags when double quoted" $
289− enc [Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing] `shouldReturn` "!!str \"foo\"\n"
290− it "outputs tags when single quoted" $
291− enc [Y.EventScalar "foo" Y.StrTag Y.SingleQuoted Nothing] `shouldReturn` "!!str 'foo'\n"
292− it "outputs tags on literal text" $
293− enc [Y.EventScalar "foo" Y.StrTag Y.Literal Nothing] `shouldReturn` "!!str |-\n foo\n"
294− it "outputs tags on folded text" $
295− enc [Y.EventScalar "foo" Y.StrTag Y.Folded Nothing] `shouldReturn` "!!str >-\n foo\n"
296− describe "Text.Libyaml with all tags on" $ do
297− let enc = testEncodeWith $ Y.setTagRendering Y.renderAllTags Y.defaultFormatOptions
298− it "will output custom sequence tags" $
299− enc taggedSequence `shouldReturn` "!foo []\n"
300− it "will output custom mapping tags" $
301− enc taggedMapping `shouldReturn` "!foo {}\n"
302− it "will output default sequence tags" $
303− enc defaultTaggedSequence `shouldReturn` "!!seq []\n"
304− it "will output default mapping tags" $
305− enc defaultTaggedMapping `shouldReturn` "!!map {}\n"
306− it "handles NoTag on sequences" $
307− enc untaggedSequence `shouldReturn` "[]\n"
308− it "handles NoTag on mappings" $
309− enc untaggedMapping `shouldReturn` "{}\n"
310− it "handles mixed tag usages outputting all mapping and sequence tags" $
311− enc mixedTagSampleA `shouldReturn` "- !foo {}\n"
312− it "in combination of tags, anchors and styles, outputs all the tags" $
313− enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c !baz [&d !!null '']\n"
314− it "outputs plain tags" $
315− enc [Y.EventScalar "foo" Y.StrTag Y.Plain Nothing] `shouldReturn` "!!str foo\n"
316− it "respects PlainNoTag tags" $
317− enc [Y.EventScalar "foo" Y.StrTag Y.PlainNoTag Nothing] `shouldReturn` "foo\n"
318− describe "Text.Libyaml with uri tags on" $ do
319− let enc = testEncodeWith $ Y.setTagRendering Y.renderUriTags Y.defaultFormatOptions
320− it "will output custom sequence tags" $
321− enc taggedSequence `shouldReturn` "!foo []\n"
322− it "will output custom mapping tags" $
323− enc taggedMapping `shouldReturn` "!foo {}\n"
324− it "will output default sequence tags" $
325− enc defaultTaggedSequence `shouldReturn` "[]\n"
326− it "will output default mapping tags" $
327− enc defaultTaggedMapping `shouldReturn` "{}\n"
328− it "handles NoTag on sequences" $
329− enc untaggedSequence `shouldReturn` "[]\n"
330− it "handles NoTag on mappings" $
331− enc untaggedMapping `shouldReturn` "{}\n"
332− it "handles mixed tag usages outputting all mapping and sequence tags" $
333− enc mixedTagSampleA `shouldReturn` "- !foo {}\n"
334− it "in combination of tags, anchors and styles, outputs all the tags" $
335− enc mixedTagSampleB `shouldReturn` "&a\n&b !<bar> foo: &c !baz [&d '']\n"
336− describe "Text.Libyaml with tags off" $ do
337− let enc = testEncodeWith $ Y.setTagRendering Y.renderNoTags Y.defaultFormatOptions
338− it "outputs plain tags" $
339− enc [Y.EventScalar "foo" Y.StrTag Y.Plain Nothing] `shouldReturn` "foo\n"
340− it "respects PlainNoTag tags" $
341− enc [Y.EventScalar "foo" Y.StrTag Y.PlainNoTag Nothing] `shouldReturn` "foo\n"
342− it "elides tags when double quoted" $
343− enc [Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing] `shouldReturn` "\"foo\"\n"
344− it "elides tags when single quoted" $
345− enc [Y.EventScalar "foo" Y.StrTag Y.SingleQuoted Nothing] `shouldReturn` "'foo'\n"
346− it "elides tags on literal text" $
347− enc [Y.EventScalar "foo" Y.StrTag Y.Literal Nothing] `shouldReturn` "|-\n foo\n"
348− it "elides tags on folded text" $
349− enc [Y.EventScalar "foo" Y.StrTag Y.Folded Nothing] `shouldReturn` ">-\n foo\n"
350− describe "Text.Libyaml with only UriTags set to render " $ do
351− let enc =
352− testEncodeWith $
353− Y.setTagRendering Y.renderUriTags $ Y.defaultFormatOptions
354− it "outputs only UriTags" $
355− enc
356− [ Y.EventSequenceStart Y.NoTag Y.FlowSequence Nothing
357− , Y.EventScalar "foo" Y.StrTag Y.DoubleQuoted Nothing
358− , Y.EventScalar "99" Y.IntTag Y.Plain Nothing
359− , Y.EventScalar "99.99" Y.FloatTag Y.Plain Nothing
360− , Y.EventScalar "bar" Y.NoTag Y.Plain Nothing
361− , Y.EventScalar "foo" (Y.UriTag "!foo") Y.DoubleQuoted Nothing
362− , Y.EventScalar "foo" (Y.UriTag "!foo") Y.Plain Nothing
363− , Y.EventSequenceEnd
364− ] `shouldReturn`
365− "[\"foo\", 99, 99.99, bar, !foo \"foo\", !foo foo]\n"
366−
367− prop "Scientific values round-trip" $ \coeff expon -> do
368− let val = D.Number $ S.scientific coeff expon
369− let rendered = D.encode val
370− case D.decodeEither' rendered of
371− Left e -> error $ show (coeff, expon, e)
372− Right val' -> val' `shouldBe` val
373−
374−specialStrings :: [T.Text]
375−specialStrings =
376− [ "fo\"o"
377− , "fo\'o"
378− , "fo\\'o"
379− , "fo: o"
380− , "foo\nbar\nbaz\n"
381− ]
382−
383−counter :: Monad m => (Y.Event -> Bool) -> ConduitM Y.Event o m Int
384−counter pred' =
385− CL.fold (\cnt e -> (if pred' e then 1 else 0) + cnt) 0
386−
387−caseHelper :: String
388− -> (Y.Event -> Bool)
389− -> Int
390− -> Assertion
391−caseHelper yamlString pred' expRes = do
392− res <- runConduitRes $ Y.decode (B8.pack yamlString) .| counter pred'
393− res @?= expRes
394−
395−caseCountScalarsWithAnchor :: Assertion
396−caseCountScalarsWithAnchor =
397− caseHelper yamlString isScalarA 1
398− where
399− yamlString = "foo:\n - &anchor bin1\n - bin2\n - bin3"
400− isScalarA (Y.EventScalar _ _ _ (Just _)) = True
401− isScalarA _ = False
402−
403−caseCountSequencesWithAnchor :: Assertion
404−caseCountSequencesWithAnchor =
405− caseHelper yamlString isSequenceStartA 1
406− where
407− yamlString = "foo: &anchor\n - bin1\n - bin2\n - bin3"
408− isSequenceStartA (Y.EventSequenceStart Y.NoTag _ (Just _)) = True
409− isSequenceStartA _ = False
410−
411−caseCountMappingsWithAnchor :: Assertion
412−caseCountMappingsWithAnchor =
413− caseHelper yamlString isMappingA 1
414− where
415− yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3"
416− isMappingA (Y.EventMappingStart _ _ (Just _)) = True
417− isMappingA _ = False
418−
419−caseCountAliases :: Assertion
420−caseCountAliases =
421− caseHelper yamlString isAlias 1
422− where
423− yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3\nboo: *anchor"
424− isAlias Y.EventAlias{} = True
425− isAlias _ = False
426−
427−caseCountMappingTags :: Assertion
428−caseCountMappingTags =
429− caseHelper yamlString isCustomTaggedMapping 1
430− where
431− yamlString = "foo: !bar\n k: v\n k2: v2"
432− isCustomTaggedMapping (Y.EventMappingStart (Y.UriTag "!bar") _ _) = True
433− isCustomTaggedMapping _ = False
434−
435−caseCountEmptyMappingTags :: Assertion
436−caseCountEmptyMappingTags =
437− caseHelper yamlString isCustomTaggedMapping 1
438− where
439− yamlString = "foo: !\n k: v\n k2: v2"
440− isCustomTaggedMapping (Y.EventMappingStart (Y.UriTag "!") _ _) = True
441− isCustomTaggedMapping _ = False
442−
443−caseCountSequenceTags :: Assertion
444−caseCountSequenceTags =
445− caseHelper yamlString isCustomTaggedSequence 1
446− where
447− yamlString = "foo: !bar [x, y, z]"
448− isCustomTaggedSequence (Y.EventSequenceStart (Y.UriTag "!bar") _ _) = True
449− isCustomTaggedSequence _ = False
450−
451−caseCountEmptySequenceTags :: Assertion
452−caseCountEmptySequenceTags =
453− caseHelper yamlString isCustomTaggedSequence 1
454− where
455− yamlString = "foo: ! [x, y, z]"
456− isCustomTaggedSequence (Y.EventSequenceStart (Y.UriTag "!") _ _) = True
457− isCustomTaggedSequence _ = False
458−
459−caseCountFlowStyleSequences :: Assertion
460−caseCountFlowStyleSequences =
461− caseHelper yamlString isFlowStyleSequence 1
462− where
463− yamlString = "foo: [x, y, z]"
464− isFlowStyleSequence (Y.EventSequenceStart _ Y.FlowSequence _) = True
465− isFlowStyleSequence _ = False
466−
467−caseCountBlockStyleSequences :: Assertion
468−caseCountBlockStyleSequences =
469− caseHelper yamlString isBlockStyleSequence 1
470− where
471− yamlString = "foo:\n- x\n- y\n- z\n"
472− isBlockStyleSequence (Y.EventSequenceStart _ Y.BlockSequence _) = True
473− isBlockStyleSequence _ = False
474−
475−caseCountFlowStyleMappings :: Assertion
476−caseCountFlowStyleMappings =
477− caseHelper yamlString isFlowStyleMapping 1
478− where
479− yamlString = "foo: { bar: 1, baz: 2 }"
480− isFlowStyleMapping (Y.EventMappingStart _ Y.FlowMapping _) = True
481− isFlowStyleMapping _ = False
482−
483−caseCountBlockStyleMappings :: Assertion
484−caseCountBlockStyleMappings =
485− caseHelper yamlString isBlockStyleMapping 1
486− where
487− yamlString = "foo: bar\nbaz: quux"
488− isBlockStyleMapping (Y.EventMappingStart _ Y.BlockMapping _) = True
489− isBlockStyleMapping _ = False
490−
491−caseCountScalars :: Assertion
492−caseCountScalars = do
493− res <- runConduitRes $ Y.decode yamlBS .| CL.fold adder accum
494− res @?= (7, 1, 2)
495− where
496− yamlString = "foo:\n baz: [bin1, bin2, bin3]\nbaz: bazval"
497− yamlBS = B8.pack yamlString
498− adder (s, l, m) (Y.EventScalar{}) = (s + 1, l, m)
499− adder (s, l, m) (Y.EventSequenceStart{}) = (s, l + 1, m)
500− adder (s, l, m) (Y.EventMappingStart{}) = (s, l, m + 1)
501− adder a _ = a
502− accum = (0, 0, 0) :: (Int, Int, Int)
503−
504−caseLargestString :: Assertion
505−caseLargestString = do
506− res <- runConduitRes $ Y.decodeFile filePath .| CL.fold adder accum
507− res @?= (length expected, expected)
508− where
509− expected = "this one is just a little bit bigger than the others"
510− filePath = "test/largest-string.yaml"
511− adder (i, s) (Y.EventScalar bs _ _ _) =
512− let s' = B8.unpack bs
513− i' = length s'
514− in if i' > i then (i', s') else (i, s)
515− adder acc _ = acc
516− accum = (0, "no strings found")
517−
518−newtype MyEvent = MyEvent Y.Event deriving Show
519−instance Eq MyEvent where
520− (MyEvent (Y.EventScalar s t _ _)) == (MyEvent (Y.EventScalar s' t' _ _)) =
521− s == s' && t == t'
522− MyEvent e1 == MyEvent e2 = e1 == e2
523−
524−caseEncodeDecode :: Assertion
525−caseEncodeDecode = do
526− eList <- runConduitRes $ Y.decode yamlBS .| CL.consume
527− bs <- runConduitRes $ CL.sourceList eList .| Y.encode
528− eList2 <- runConduitRes $ Y.decode bs .| CL.consume
529− map MyEvent eList @=? map MyEvent eList2
530− where
531− yamlString = "foo: bar\nbaz:\n - bin1\n - bin2\n"
532− yamlBS = B8.pack yamlString
533−
534−caseEncodeDecodeEvents :: Assertion
535−caseEncodeDecodeEvents = do
536− let events = Internal.objToEvents D.defaultStringStyle testJSON []
537− result <- Internal.decodeHelper_ . CL.sourceList $ eventStream events
538− let (_, value) = either (error . show) id result
539− value @?= testJSON
540−
541−caseEncodeDecodeFile :: Assertion
542−caseEncodeDecodeFile = withFile "" $ \tmpPath -> do
543− eList <- runConduitRes $ Y.decodeFile filePath .| CL.consume
544− runConduitRes $ CL.sourceList eList .| Y.encodeFile tmpPath
545− eList2 <- runConduitRes $ Y.decodeFile filePath .| CL.consume
546− map MyEvent eList @=? map MyEvent eList2
547− where
548− filePath = "test/largest-string.yaml"
549−
550−caseInterleave :: Assertion
551−caseInterleave = withFile "" $ \tmpPath -> withFile "" $ \tmpPath2 -> do
552− () <- runConduitRes $ Y.decodeFile filePath .| Y.encodeFile tmpPath
553− () <- runConduitRes $ Y.decodeFile tmpPath .| Y.encodeFile tmpPath2
554− f1 <- readFile tmpPath
555− f2 <- readFile tmpPath2
556− f1 @=? f2
557− where
558− filePath = "test/largest-string.yaml"
559−
560−caseDecodeInvalidDocument :: Assertion
561−caseDecodeInvalidDocument = do
562− x <- try $ runConduitRes $ Y.decode yamlBS .| CL.sinkNull
563− case x of
564− Left (_ :: SomeException) -> return ()
565− Right y -> do
566− putStrLn $ "bad return value: " ++ show y
567− assertFailure "expected parsing exception, but got no errors"
568− where
569− yamlString = " - foo\n - baz\nbuz"
570− yamlBS = B8.pack yamlString
571−
572−mkScalar :: String -> D.Value
573−mkScalar = mkStrScalar
574−
575−mkStrScalar :: String -> D.Value
576−mkStrScalar = D.String . T.pack
577−
578−mappingKey :: D.Value-> String -> D.Value
579−mappingKey (D.Object m) k = (fromJust . M.lookup (fromText $ T.pack k) $ m)
580−mappingKey _ _ = error "expected Object"
581−
582−sample :: D.Value
583−sample = array
584− [ D.String "foo"
585− , object
586− [ ("bar1", D.String "bar2")
587− , ("bar3", D.String "")
588− ]
589− , D.String ""
590− , D.Number 1
591− , D.Number 0.1
592− , D.Bool True
593− , D.Null
594− ]
595−
596−sampleBuilder :: B.YamlBuilder
597−sampleBuilder = B.array
598− [ B.string "foo"
599− , B.mapping
600− [ ("bar1", B.string "bar2")
601− , ("bar3", B.string "")
602− ]
603− , B.string ""
604− , B.scientific 1
605− , B.scientific 0.1
606− , B.bool True
607− , B.null
608− ]
609−
610−caseEncodeDecodeData :: Assertion
611−caseEncodeDecodeData = D.encode sample `shouldDecode` sample
612−
613−caseEncodeDecodeDataPretty :: Assertion
614−caseEncodeDecodeDataPretty =
615− Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample
616−
617−caseEncodeDecodeDataBuilder :: Assertion
618−caseEncodeDecodeDataBuilder = do
619− let events = B.unYamlBuilder sampleBuilder []
620− bs <- testEncodeWith Y.defaultFormatOptions events
621− bs `shouldDecodeEvents` eventStream events
622−
623−caseEncodeDecodeComplexMappingBuilder :: Assertion
624−caseEncodeDecodeComplexMappingBuilder = do
625− let events = B.unYamlBuilder builder []
626− bs <- testEncodeWith Y.defaultFormatOptions events
627− bs `shouldDecodeEvents` eventStream events
628− where
629− builder :: B.YamlBuilder
630− builder = B.mappingComplex
631− [ ( B.mapping
632− [ ("foo", B.scientific 1)
633− , ("bar", B.scientific 2)
634− ]
635− , B.bool True
636− )
637− ]
638−
639−caseEncodeDecodeFileData :: Assertion
640−caseEncodeDecodeFileData = withFile "" $ \fp -> do
641− D.encodeFile fp sample
642− out <- D.decodeFileThrow fp
643− out @?= sample
644−
645−caseEncodeDecodeNonAsciiFileData :: Assertion
646−caseEncodeDecodeNonAsciiFileData = do
647− let mySample = (object ["foo" .= True])
648− inTempDirectory $ do
649− createDirectory "accenté"
650− D.encodeFile "accenté/bar.yaml" mySample
651− out1 <- D.decodeFileThrow "accenté/bar.yaml"
652− out1 @?= mySample
653−
654− c <- readFile "test/resources/accent/foo.yaml"
655− inTempDirectory $ do
656− createDirectoryIfMissing True "test/resources/unicode/accenté/"
657− writeFile "test/resources/unicode/accenté/foo.yaml" c
658− out2 <- D.decodeFileThrow "test/resources/unicode/accenté/foo.yaml"
659− out2 @?= mySample
660−
661−caseEncodeDecodeStrings :: Assertion
662−caseEncodeDecodeStrings = D.encode sample `shouldDecode` sample
663−
664−caseEncodeDecodeStringsPretty :: Assertion
665−caseEncodeDecodeStringsPretty =
666− Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample
667−
668−caseDecodeInvalid :: Assertion
669−caseDecodeInvalid =
670− D.decodeThrow "\tthis is 'not' valid :-)" `shouldBe`
671− (Nothing :: Maybe D.Value)
672−
673−caseSimpleScalarAlias :: Assertion
674−caseSimpleScalarAlias =
675− "- &anch foo\n- baz\n- *anch" `shouldDecode`
676− array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")]
677−
678−caseSimpleSequenceAlias :: Assertion
679−caseSimpleSequenceAlias =
680− "seq: &anch\n - foo\n - baz\nseq2: *anch" `shouldDecode`
681− object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])]
682−
683−caseSimpleMappingAlias :: Assertion
684−caseSimpleMappingAlias =
685− "map: &anch\n key1: foo\n key2: baz\nmap2: *anch" `shouldDecode`
686− object [(packStr "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (packStr "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])]
687− where
688− packStr = fromText . T.pack
689−
690−caseMappingAliasBeforeAnchor :: Assertion
691−caseMappingAliasBeforeAnchor =
692− case D.decodeThrow "map: *anch\nmap2: &anch\n key1: foo\n key2: baz" of
693− Nothing -> pure ()
694− Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias"
695−
696−caseMappingAliasInsideAnchor :: Assertion
697−caseMappingAliasInsideAnchor = do
698− case D.decodeThrow "map: &anch\n key1: foo\n key2: *anch" of
699− Nothing -> pure ()
700− Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias"
701−
702−caseScalarAliasOverriding :: Assertion
703−caseScalarAliasOverriding =
704− "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch" `shouldDecode`
705− array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")]
706−
707−caseAllKeysShouldBeUnique :: Assertion
708−caseAllKeysShouldBeUnique = do
709− res <- D.decodeThrow "foo1: foo\nfoo2: baz\nfoo1: buz"
710− mappingKey res "foo1" `shouldBe` mkScalar "buz"
711−
712−caseSimpleMappingMerge :: Assertion
713−caseSimpleMappingMerge = do
714− res <- D.decodeThrow "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"
715− mappingKey res "foo1" `shouldBe` mkScalar "foo"
716− mappingKey res "foo3" `shouldBe` mkScalar "fuz"
717−
718−caseMergeSequence :: Assertion
719−caseMergeSequence = do
720− res <- D.decodeThrow "m1: &m1\n k1: !!str 1\n k2: !!str 2\nm2: &m2\n k1: !!str 3\n k3: !!str 4\nfoo1: foo\n<<: [ *m1, *m2 ]"
721− mappingKey res "foo1" @?= (mkScalar "foo")
722− mappingKey res "k1" @?= (D.String "1")
723− mappingKey res "k2" @?= (D.String "2")
724− mappingKey res "k3" @?= (D.String "4")
725−
726−caseDataTypes :: Assertion
727−caseDataTypes =
728− D.encode val `shouldDecode` val
729− where
730− val = object
731− [ ("string", D.String "foo")
732− , ("int", D.Number 5)
733− , ("float", D.Number 4.3)
734− , ("true", D.Bool True)
735− , ("false", D.Bool False)
736− , ("null", D.Null)
737− ]
738−
739−caseEncodeInvalidNumbers :: Assertion
740−caseEncodeInvalidNumbers =
741− D.encode (D.String ".") `shouldBe` ".\n"
742−
743−caseDataTypesPretty :: Assertion
744−caseDataTypesPretty =
745− Pretty.encodePretty Pretty.defConfig val `shouldDecode` val
746− where
747− val = object
748− [ ("string", D.String "foo")
749− , ("int", D.Number 5)
750− , ("float", D.Number 4.3)
751− , ("true", D.Bool True)
752− , ("false", D.Bool False)
753− , ("null", D.Null)
754− ]
755−caseQuotedNumber, caseUnquotedNumber, caseAttribNumber, caseIntegerDecimals :: Assertion
756−caseQuotedNumber = "foo: \"1234\"" `shouldDecode` object [("foo", D.String "1234")]
757−caseUnquotedNumber = "foo: 1234" `shouldDecode` object [("foo", D.Number 1234)]
758−caseAttribNumber = "foo: !!str 1234" `shouldDecode` object [("foo", D.String "1234")]
759−caseIntegerDecimals = "1\n" `shouldDecode` (1 :: Int)
760−
761−obj :: D.Value
762−obj = object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)]
763−
764−caseLowercaseBool, caseUppercaseBool, caseTitlecaseBool :: Assertion
765−caseLowercaseBool = "foo: off\nbar: y\nbaz: true" `shouldDecode` obj
766−caseUppercaseBool = "foo: FALSE\nbar: Y\nbaz: ON" `shouldDecode` obj
767−caseTitlecaseBool = "foo: No\nbar: Yes\nbaz: True" `shouldDecode` obj
768−
769−caseEmptyInput :: Assertion
770−caseEmptyInput = B8.empty `shouldDecode` D.Null
771−
772−caseEmptyInputFile :: Assertion
773−caseEmptyInputFile = do
774− out <- D.decodeFileEither "test/resources/empty.yaml"
775− either (Left . D.prettyPrintParseException) Right out @?= Right D.Null
776−
777−caseCommentOnlyInput :: Assertion
778−caseCommentOnlyInput = "# comment\n" `shouldDecode` D.Null
779−
780−caseCommentOnlyInputFile :: Assertion
781−caseCommentOnlyInputFile = do
782− out <- D.decodeFileEither "test/resources/empty2.yaml"
783− either (Left . D.prettyPrintParseException) Right out @?= Right D.Null
784−
785−checkNull :: T.Text -> Spec
786−checkNull x =
787− it ("null recognized: " ++ show x) $
788− B8.pack ("foo: " ++ T.unpack x) `shouldDecode` object [("foo", D.Null)]
789−
790−caseStripAlias :: Assertion
791−caseStripAlias =
792− src `shouldDecode` object
793− [ "Default" .= object
794− [ "foo" .= (1 :: Int)
795− , "bar" .= (2 :: Int)
796− ]
797− , "Obj" .= object
798− [ "foo" .= (1 :: Int)
799− , "bar" .= (2 :: Int)
800− , "key" .= (3 :: Int)
801− ]
802− ]
803− where
804− src = "Default: &def\n foo: 1\n bar: 2\nObj:\n <<: *def\n key: 3\n"
805−
806−caseIssue49 :: Assertion
807−caseIssue49 =
808− src `shouldDecode` object
809− [ "a" .= object [ "value" .= (1.0 :: Double) ]
810− , "b" .= object [ "value" .= (1.2 :: Double) ]
811− ]
812− where
813− src = "---\na:\n &id5 value: 1.0\nb:\n *id5: 1.2"
814−
815−-- | We cannot guarantee this before aeson started using 'Scientific'.
816−casePreservesScientificPrecision :: Assertion
817−casePreservesScientificPrecision = do
818− "x: 1e-100000" `shouldDecode` object
819− [ "x" .= D.Number (read "1e-100000") ]
820− -- Note that this ought to work also without 'Scientific', given
821− -- that @read (show "9.78159610558926e-5") == 9.78159610558926e-5@.
822− -- However, it didn't work (and still doesn't work with aeson < 0.7)
823− -- for two reasons:
824− --
825− -- - We use 'Data.Text.Read.double', which is not as accurate as it
826− -- can be;
827− -- - Even if we used 'Data.Text.Read.rational' we would not get good
828− -- results, because of <https://github.com/bos/text/issues/34>.
829− "x: 9.78159610558926e-5" `shouldDecode` object
830− [ "x" .= D.Number (read "9.78159610558926e-5") ]
831−
832−caseTruncatesFiles :: Assertion
833−caseTruncatesFiles = withSystemTempFile "truncate.yaml" $ \fp h -> do
834− replicateM_ 500 $ B8.hPut h "HELLO WORLD!!!!!\n"
835− hClose h
836− let val = object ["hello" .= ("world" :: String)]
837− D.encodeFile fp val
838− res <- D.decodeFileEither fp
839− either (Left . show) Right res `shouldBe` Right val
840−
841−caseSpecialKeys :: (KeyMap () -> B8.ByteString) -> Assertion
842−caseSpecialKeys encoder = do
843− let keys = T.words "true false NO YES 1.2 1e5 null"
844− bs = encoder $ M.fromList $ map (, ()) $ fmap fromText keys
845− text = decodeUtf8 bs
846− forM_ keys $ \key -> do
847− let quoted = T.concat ["'", key, "'"]
848− unless (quoted `T.isInfixOf` text) $ error $ concat
849− [ "Could not find quoted key: "
850− , T.unpack quoted
851− , "\n\n"
852− , T.unpack text
853− ] :: IO ()
854−
855−taggedSequence :: [Y.Event]
856−taggedSequence =
857− [ Y.EventSequenceStart (Y.UriTag "!foo") Y.FlowSequence Nothing
858− , Y.EventSequenceEnd
859− ]
860−
861−taggedMapping :: [Y.Event]
862−taggedMapping =
863− [ Y.EventMappingStart (Y.UriTag "!foo") Y.FlowMapping Nothing
864− , Y.EventMappingEnd
865− ]
866−
867−defaultTaggedSequence :: [Y.Event]
868−defaultTaggedSequence =
869− [Y.EventSequenceStart Y.SeqTag Y.FlowSequence Nothing, Y.EventSequenceEnd]
870−
871−defaultTaggedMapping :: [Y.Event]
872−defaultTaggedMapping =
873− [Y.EventMappingStart Y.MapTag Y.FlowMapping Nothing, Y.EventMappingEnd]
874−
875−untaggedSequence :: [Y.Event]
876−untaggedSequence =
877− [Y.EventSequenceStart Y.NoTag Y.FlowSequence Nothing, Y.EventSequenceEnd]
878−
879−untaggedMapping :: [Y.Event]
880−untaggedMapping =
881− [Y.EventMappingStart Y.NoTag Y.FlowMapping Nothing, Y.EventMappingEnd]
882−
883−mixedTagSampleA :: [Y.Event]
884−mixedTagSampleA =
885− [ Y.EventSequenceStart Y.NoTag Y.BlockSequence Nothing
886− , Y.EventMappingStart (Y.UriTag "!foo") Y.FlowMapping Nothing
887− , Y.EventMappingEnd
888− , Y.EventSequenceEnd
889− ]
890−
891−mixedTagSampleB :: [Y.Event]
892−mixedTagSampleB =
893− [ Y.EventMappingStart Y.NoTag Y.BlockMapping (Just "a")
894− , Y.EventScalar "foo" (Y.UriTag "bar") Y.Plain (Just "b")
895− , Y.EventSequenceStart (Y.UriTag "!baz") Y.FlowSequence (Just "c")
896− , Y.EventScalar "" Y.NullTag Y.Plain (Just "d")
897− , Y.EventSequenceEnd
898− , Y.EventMappingEnd
899− ]
yaml/test/Spec.hsdeleted−1
@@ -1 +0,0 @@
1−{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
yaml/test/json.yamldeleted−9
@@ -1,9 +0,0 @@
1−string: str
2−number: 2
3−anArray:
4− - a
5− - b
6−hash:
7− key1: value1
8− key2: value2
9−extrastring: 1234-foo
yaml/test/resources/accent/foo.yamldeleted−1
@@ -1 +0,0 @@
1−foo: true
yaml/test/resources/bar.yamldeleted−2
@@ -1,2 +0,0 @@
1−one: 1
2−two: 2
yaml/test/resources/baz.yamldeleted−1
@@ -1 +0,0 @@
1−foo: !include foo.yaml
yaml/test/resources/empty.yamldeleted

No changes to the content.

yaml/test/resources/empty2.yamldeleted−1
@@ -1 +0,0 @@
1−# comment
yaml/test/resources/foo.yamldeleted−3
@@ -1,3 +0,0 @@
1−foo: 23
2−bar: !include bar.yaml
3−baz: 42
yaml/test/resources/loop/bar.yamldeleted−2
@@ -1,2 +0,0 @@
1−one: 1
2−two: !include foo.yaml
yaml/test/resources/loop/foo.yamldeleted−3
@@ -1,3 +0,0 @@
1−foo: 23
2−bar: !include bar.yaml
3−baz: 42
yaml/yaml.cabaldeleted−228
@@ -1,228 +0,0 @@
1−cabal-version: 1.12
2−
3−-- This file has been generated from package.yaml by hpack version 0.35.1.
4−--
5−-- see: https://github.com/sol/hpack
6−
7−name: yaml
8−version: 0.11.11.2
9−synopsis: Support for parsing and rendering YAML documents.
10−description: README and API documentation are available at <https://www.stackage.org/package/yaml>
11−category: Data
12−stability: stable
13−homepage: https://github.com/snoyberg/yaml#readme
14−bug-reports: https://github.com/snoyberg/yaml/issues
15−author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
16−maintainer: Michael Snoyman <michael@snoyman.com>
17−license: BSD3
18−license-file: LICENSE
19−build-type: Simple
20−extra-source-files:
21− test/largest-string.yaml
22− test/json.yaml
23− test/resources/foo.yaml
24− test/resources/bar.yaml
25− test/resources/baz.yaml
26− test/resources/accent/foo.yaml
27− test/resources/loop/foo.yaml
28− test/resources/loop/bar.yaml
29− test/resources/empty.yaml
30− test/resources/empty2.yaml
31− README.md
32− ChangeLog.md
33−
34−source-repository head
35− type: git
36− location: https://github.com/snoyberg/yaml
37−
38−flag no-examples
39− description: don't build the examples
40− manual: False
41− default: True
42−
43−flag no-exe
44− description: don't install the yaml2json or json2yaml executables
45− manual: False
46− default: True
47−
48−library
49− exposed-modules:
50− Data.Yaml
51− Data.Yaml.Aeson
52− Data.Yaml.Builder
53− Data.Yaml.Config
54− Data.Yaml.Include
55− Data.Yaml.Internal
56− Data.Yaml.Parser
57− Data.Yaml.Pretty
58− Data.Yaml.TH
59− other-modules:
60− Paths_yaml
61− hs-source-dirs:
62− src
63− other-extensions:
64− LambdaCase
65− ghc-options: -Wall -Wcompat
66− build-depends:
67− aeson >=0.11
68− , attoparsec >=0.11.3.0
69− , base >=4.9.1 && <5
70− , bytestring >=0.9.1.4
71− , conduit >=1.2.8 && <1.4
72− , containers
73− , directory
74− , filepath
75− , libyaml ==0.1.*
76− , mtl
77− , resourcet >=0.3 && <1.4
78− , scientific >=0.3
79− , template-haskell
80− , text
81− , transformers >=0.1
82− , unordered-containers
83− , vector
84− default-language: Haskell2010
85−
86−executable examples
87− main-is: Main.hs
88− other-modules:
89− Config
90− Simple
91− Paths_yaml
92− hs-source-dirs:
93− examples
94− ghc-options: -Wall -Wcompat
95− build-depends:
96− aeson >=0.11
97− , attoparsec >=0.11.3.0
98− , base >=4.9.1 && <5
99− , bytestring >=0.9.1.4
100− , conduit >=1.2.8 && <1.4
101− , containers
102− , directory
103− , filepath
104− , libyaml ==0.1.*
105− , mtl
106− , resourcet >=0.3 && <1.4
107− , scientific >=0.3
108− , template-haskell
109− , text
110− , transformers >=0.1
111− , unordered-containers
112− , vector
113− default-language: Haskell2010
114− if flag(no-examples)
115− buildable: False
116− else
117− build-depends:
118− raw-strings-qq
119− , yaml
120−
121−executable json2yaml
122− main-is: json2yaml.hs
123− other-modules:
124− Common
125− Paths_yaml
126− hs-source-dirs:
127− exe
128− ghc-options: -Wall -Wcompat
129− build-depends:
130− aeson >=0.11
131− , attoparsec >=0.11.3.0
132− , base >=4.9.1 && <5
133− , bytestring >=0.9.1.4
134− , conduit >=1.2.8 && <1.4
135− , containers
136− , directory
137− , filepath
138− , libyaml ==0.1.*
139− , mtl
140− , optparse-applicative
141− , resourcet >=0.3 && <1.4
142− , scientific >=0.3
143− , template-haskell
144− , text
145− , transformers >=0.1
146− , unordered-containers
147− , vector
148− , yaml
149− default-language: Haskell2010
150− if flag(no-exe)
151− buildable: False
152−
153−executable yaml2json
154− main-is: yaml2json.hs
155− other-modules:
156− Common
157− Paths_yaml
158− hs-source-dirs:
159− exe
160− other-extensions:
161− CPP
162− LambdaCase
163− NamedFieldPuns
164− ghc-options: -Wall -Wcompat
165− build-depends:
166− aeson >=0.11
167− , attoparsec >=0.11.3.0
168− , base >=4.9.1 && <5
169− , bytestring >=0.9.1.4
170− , conduit >=1.2.8 && <1.4
171− , containers
172− , directory
173− , filepath
174− , libyaml ==0.1.*
175− , mtl
176− , optparse-applicative
177− , resourcet >=0.3 && <1.4
178− , scientific >=0.3
179− , template-haskell
180− , text
181− , transformers >=0.1
182− , unordered-containers
183− , vector
184− , yaml
185− default-language: Haskell2010
186− if flag(no-exe)
187− buildable: False
188−
189−test-suite spec
190− type: exitcode-stdio-1.0
191− main-is: Spec.hs
192− other-modules:
193− Data.Yaml.IncludeSpec
194− Data.Yaml.THSpec
195− Data.YamlSpec
196− Paths_yaml
197− hs-source-dirs:
198− test
199− ghc-options: -Wall -Wcompat -with-rtsopts=-K1K
200− cpp-options: -DTEST
201− build-tool-depends:
202− hspec-discover:hspec-discover
203− build-depends:
204− HUnit
205− , aeson >=0.11
206− , attoparsec >=0.11.3.0
207− , base >=4.9.1 && <5
208− , base-compat
209− , bytestring >=0.9.1.4
210− , conduit >=1.2.8 && <1.4
211− , containers
212− , directory
213− , filepath
214− , hspec >=1.3
215− , libyaml ==0.1.*
216− , mockery
217− , mtl
218− , raw-strings-qq
219− , resourcet >=0.3 && <1.4
220− , scientific >=0.3
221− , template-haskell
222− , temporary
223− , text
224− , transformers >=0.1
225− , unordered-containers
226− , vector
227− , yaml
228− default-language: Haskell2010