on master help sign in
73 files changed+3895−14593
since splitsnapshots
unifiedsplit
.github/workflows/tests.yml+44 .gitignore+5 .gitmodules+3 .travis.yml−175 ChangeLog.md−58 Data/Yaml.hs−186 Data/Yaml/Builder.hs−113 Data/Yaml/Internal.hs−279 Makefile−4 README.md+16−10 exe/json2yaml.hs−22 exe/yaml2json.hs−28 libyaml/ChangeLog.md+27 libyaml/LICENSE+22−16 libyaml/Makefile+4−9 libyaml/README.md+3 libyaml/Setup.hs+2 libyaml/api.c−1403 c/helper.c → libyaml/c/helper.c+58−23 libyaml/dumper.c−394 libyaml/emitter.c−2329 c/helper.h → libyaml/include/helper.h+7−4 libyaml/libyaml.cabal+68 libyaml/loader.c−444 libyaml/package.yaml+53 libyaml/parser.c−1374 libyaml/reader.c−469 libyaml/scanner.c−3580 Text/Libyaml.hs → libyaml/src/Text/Libyaml.hs+348−150 libyaml/writer.c−141 libyaml/yaml.h−1973 libyaml/yaml_private.h−661 stack.yaml+8−1 test/Data/Yaml/IncludeSpec.hs−44 test/Data/YamlSpec.hs−486 yaml.cabal−158 yaml/ChangeLog.md+303 LICENSE → yaml/LICENSE yaml/README.md+26 Setup.lhs → yaml/Setup.lhs builder-test.hs → yaml/builder-test.hs examples/Config.hs → yaml/examples/Config.hs+4−2 examples/Main.hs → yaml/examples/Main.hs examples/Simple.hs → yaml/examples/Simple.hs+2−1 yaml/exe/Common.hs+68 yaml/exe/json2yaml.hs+106 yaml/exe/yaml2json.hs+87 yaml/package.yaml+113 parser-test.hs → yaml/parser-test.hs yaml/src/Data/Yaml.hs+292 Data/Yaml/Aeson.hs → yaml/src/Data/Yaml/Aeson.hs yaml/src/Data/Yaml/Builder.hs+240 Data/Yaml/Config.hs → yaml/src/Data/Yaml/Config.hs+40−17 Data/Yaml/Include.hs → yaml/src/Data/Yaml/Include.hs+41−9 yaml/src/Data/Yaml/Internal.hs+469 Data/Yaml/Parser.hs → yaml/src/Data/Yaml/Parser.hs+24−19 Data/Yaml/Pretty.hs → yaml/src/Data/Yaml/Pretty.hs+47−11 yaml/src/Data/Yaml/TH.hs+80 yaml/test/Data/Yaml/IncludeSpec.hs+139 yaml/test/Data/Yaml/THSpec.hs+17 yaml/test/Data/YamlSpec.hs+899 test/Spec.hs → yaml/test/Spec.hs test/json.yaml → yaml/test/json.yaml test/largest-string.yaml → yaml/test/largest-string.yaml yaml/test/resources/accent/foo.yaml+1 test/resources/bar.yaml → yaml/test/resources/bar.yaml test/resources/baz.yaml → yaml/test/resources/baz.yaml yaml/test/resources/empty.yaml yaml/test/resources/empty2.yaml+1 test/resources/foo.yaml → yaml/test/resources/foo.yaml test/resources/loop/bar.yaml → yaml/test/resources/loop/bar.yaml test/resources/loop/foo.yaml → yaml/test/resources/loop/foo.yaml yaml/yaml.cabal+228
.github/workflows/tests.ymlnew file+44
@@ -0,0 +1,44 @@
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+5
@@ -4,3 +4,8 @@ cabal-dev/
44.cabal-sandbox/
55cabal.sandbox.config
66.stack-work/
7+*~
8+tarballs/
9+.dir-locals.el
10+*#
11+stack.yaml.lock
.gitmodulesnew file+3
@@ -0,0 +1,3 @@
1+[submodule "vendor/libyaml"]
2+ path = libyaml/vendor/libyaml
3+ url = https://github.com/snoyberg/libyaml
.travis.ymldeleted−175
@@ -1,175 +0,0 @@
1−# Copy these contents into the root directory of your Github project in a file
2−# named .travis.yml
3−
4−# Use new container infrastructure to enable caching
5−sudo: false
6−
7−# Choose a lightweight base image; we provide our own build tools.
8−language: c
9−
10−# Caching so the next build will be fast too.
11−cache:
12− directories:
13− - $HOME/.ghc
14− - $HOME/.cabal
15− - $HOME/.stack
16−
17−# The different configurations we want to test. We have BUILD=cabal which uses
18−# cabal-install, and BUILD=stack which uses Stack. More documentation on each
19−# of those below.
20−#
21−# We set the compiler values here to tell Travis to use a different
22−# cache file per set of arguments.
23−#
24−# If you need to have different apt packages for each combination in the
25−# matrix, you can use a line such as:
26−# addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
27−matrix:
28− include:
29− # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
30− # https://github.com/hvr/multi-ghc-travis
31− #- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
32− # compiler: ": #GHC 7.0.4"
33− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
34− #- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
35− # compiler: ": #GHC 7.2.2"
36− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
37− #- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
38− # compiler: ": #GHC 7.4.2"
39− # addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
40− - env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
41− compiler: ": #GHC 7.6.3"
42− addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
43− - env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7
44− compiler: ": #GHC 7.8.4"
45− addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
46− - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7
47− compiler: ": #GHC 7.10.3"
48− addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
49−
50− # Build with the newest GHC and cabal-install. This is an accepted failure,
51− # see below.
52− - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
53− compiler: ": #GHC HEAD"
54− addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
55−
56− # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
57− # variable, such as using --stack-yaml to point to a different file.
58− - env: BUILD=stack ARGS=""
59− compiler: ": #stack default"
60− addons: {apt: {packages: [ghc-7.10.3], sources: [hvr-ghc]}}
61−
62− - env: BUILD=stack ARGS="--resolver lts-2"
63− compiler: ": #stack 7.8.4"
64− addons: {apt: {packages: [ghc-7.8.4], sources: [hvr-ghc]}}
65−
66− - env: BUILD=stack ARGS="--resolver lts-3"
67− compiler: ": #stack 7.10.2"
68− addons: {apt: {packages: [ghc-7.10.2], sources: [hvr-ghc]}}
69−
70− - env: BUILD=stack ARGS="--resolver lts-5"
71− compiler: ": #stack 7.10.3"
72− addons: {apt: {packages: [ghc-7.10.3], sources: [hvr-ghc]}}
73−
74− # Nightly builds are allowed to fail
75− - env: BUILD=stack ARGS="--resolver nightly"
76− compiler: ": #stack nightly"
77− addons: {apt: {packages: [libgmp,libgmp-dev]}}
78−
79− # Build on OS X in addition to Linux
80− - env: BUILD=stack ARGS=""
81− compiler: ": #stack default osx"
82− os: osx
83−
84− - env: BUILD=stack ARGS="--resolver lts-2"
85− compiler: ": #stack 7.8.4 osx"
86− os: osx
87−
88− - env: BUILD=stack ARGS="--resolver lts-3"
89− compiler: ": #stack 7.10.2 osx"
90− os: osx
91−
92− - env: BUILD=stack ARGS="--resolver lts-5"
93− compiler: ": #stack 7.10.3 osx"
94− os: osx
95−
96− - env: BUILD=stack ARGS="--resolver nightly"
97− compiler: ": #stack nightly osx"
98− os: osx
99−
100− allow_failures:
101− - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
102− - env: BUILD=stack ARGS="--resolver nightly"
103−
104−before_install:
105−# Using compiler above sets CC to an invalid value, so unset it
106−- unset CC
107−
108−# We want to always allow newer versions of packages when building on GHC HEAD
109−- CABALARGS=""
110−- if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi
111−
112−# Download and unpack the stack executable
113−- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH
114−- mkdir -p ~/.local/bin
115−- |
116− if [ `uname` = "Darwin" ]
117− then
118− travis_retry curl --insecure -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
119− else
120− travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
121− fi
122−
123− # Use the more reliable S3 mirror of Hackage
124− mkdir -p $HOME/.cabal
125− echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config
126− echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config
127−
128− if [ "$CABALVER" != "1.16" ]
129− then
130− echo 'jobs: $ncpus' >> $HOME/.cabal/config
131− fi
132−
133−# Get the list of packages from the stack.yaml file
134−- PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
135−
136−install:
137−- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
138−- if [ -f configure.ac ]; then autoreconf -i; fi
139−- |
140− set -ex
141− case "$BUILD" in
142− stack)
143− stack --no-terminal --install-ghc $ARGS test --only-dependencies
144− ;;
145− cabal)
146− cabal --version
147− travis_retry cabal update
148− cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
149− ;;
150− esac
151− set +ex
152−
153−script:
154−- |
155− set -ex
156− case "$BUILD" in
157− stack)
158− stack --no-terminal $ARGS test --haddock --no-haddock-deps
159− ;;
160− cabal)
161− cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
162−
163− ORIGDIR=$(pwd)
164− for dir in $PACKAGES
165− do
166− cd $dir
167− cabal check || [ "$CABALVER" == "1.16" ]
168− cabal sdist
169− SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz && \
170− (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
171− cd $ORIGDIR
172− done
173− ;;
174− esac
175− set +ex
ChangeLog.mddeleted−58
@@ -1,58 +0,0 @@
1−## 0.8.17.2
2−
3−* 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)
4−
5−## 0.8.17.1
6−
7−* Avoid bug in Cabal [#83](https://github.com/snoyberg/yaml/pull/83)
8−
9−## 0.8.17
10−
11−* `loadYamlSettingsArgs`
12−
13−## 0.8.16.1
14−
15−* Slight doc improvement
16−
17−## 0.8.16
18−
19−Add env variable parsing. `loadYamlSettings` can read config values from the environment with Yaml that specifies an env var.
20−The syntax is
21−
22−`var: _env:ENV_VAR:default`
23−
24−## 0.8.15.3
25−
26−* Give a warning when compiling with GHCJS
27−
28−## 0.8.15.2
29−
30−* Canonicalise Monad instances [#76](https://github.com/snoyberg/yaml/pull/76)
31−
32−## 0.8.15.1
33−
34−* Compile with aeson below 0.7 [#70](https://github.com/snoyberg/yaml/pull/70)
35−
36−## 0.8.15
37−
38−* Parse `Scientific` directly, avoiding loss in precision. [#68](https://github.com/snoyberg/yaml/pull/68)
39−
40−## 0.8.14
41−
42−* Pretty print improvements for exceptions [#67](https://github.com/snoyberg/yaml/pull/67)
43−
44−## 0.8.13
45−
46−* Pretty module [#66](https://github.com/snoyberg/yaml/pull/66)
47−
48−## 0.8.12
49−
50−* Proper handling of `String "+123"` [#64](https://github.com/snoyberg/yaml/issues/64)
51−
52−## 0.8.11
53−
54−* Function to print prettier parse exceptions [#59](https://github.com/snoyberg/yaml/pull/59)
55−
56−## 0.8.10
57−
58−Add the Data.Yaml.Include module
Data/Yaml.hsdeleted−186
@@ -1,186 +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− ( -- * Types
30− Value (..)
31− , Parser
32− , Object
33− , Array
34− , ParseException(..)
35− , prettyPrintParseException
36− , YamlException (..)
37− , YamlMark (..)
38− -- * Constructors and accessors
39− , object
40− , array
41− , (.=)
42− , (.:)
43− , (.:?)
44− , (.!=)
45− -- * Parsing
46− , parseMonad
47− , parseEither
48− , parseMaybe
49− -- * Classes
50− , ToJSON (..)
51− , FromJSON (..)
52− -- * Encoding/decoding
53− , encode
54− , encodeFile
55− , decode
56− , decodeFile
57− -- ** Better error information
58− , decodeEither
59− , decodeEither'
60− , decodeFileEither
61− -- ** More control over decoding
62− , decodeHelper
63− ) where
64−#if !MIN_VERSION_base(4,8,0)
65−import Control.Applicative((<$>))
66−#endif
67−import Control.Exception
68−import Control.Monad.Trans.Resource (runResourceT)
69−import Data.Aeson
70− ( Value (..), ToJSON (..), FromJSON (..), object
71− , (.=) , (.:) , (.:?) , (.!=)
72− , Object, Array
73− )
74−import Data.Aeson.Encode (encodeToTextBuilder)
75−import Data.Aeson.Types (Pair, parseMaybe, parseEither, Parser)
76−import Data.ByteString (ByteString)
77−import qualified Data.Conduit as C
78−import qualified Data.Conduit.List as CL
79−import qualified Data.HashMap.Strict as M
80−import qualified Data.HashSet as HashSet
81−import Data.Text.Encoding (encodeUtf8)
82−import qualified Data.Text.Encoding as TE
83−import qualified Data.Text.Lazy as TL
84−import Data.Text.Lazy.Builder (toLazyText)
85−import qualified Data.Vector as V
86−import System.IO.Unsafe (unsafePerformIO)
87−
88−import Data.Yaml.Internal
89−import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile)
90−import qualified Text.Libyaml as Y
91−
92−encode :: ToJSON a => a -> ByteString
93−encode obj = unsafePerformIO $
94− runResourceT $ CL.sourceList (objToEvents $ toJSON obj)
95− C.$$ Y.encode
96−
97−encodeFile :: ToJSON a => FilePath -> a -> IO ()
98−encodeFile fp obj = runResourceT
99− $ CL.sourceList (objToEvents $ toJSON obj)
100− C.$$ Y.encodeFile fp
101−
102−objToEvents :: Value -> [Y.Event]
103−objToEvents o = (:) EventStreamStart
104− . (:) EventDocumentStart
105− $ objToEvents' o
106− [ EventDocumentEnd
107− , EventStreamEnd
108− ]
109−
110−{- FIXME
111−scalarToEvent :: YamlScalar -> Event
112−scalarToEvent (YamlScalar v t s) = EventScalar v t s Nothing
113−-}
114−
115−objToEvents' :: Value -> [Y.Event] -> [Y.Event]
116−--objToEvents' (Scalar s) rest = scalarToEvent s : rest
117−objToEvents' (Array list) rest =
118− EventSequenceStart Nothing
119− : foldr objToEvents' (EventSequenceEnd : rest) (V.toList list)
120−objToEvents' (Object pairs) rest =
121− EventMappingStart Nothing
122− : foldr pairToEvents (EventMappingEnd : rest) (M.toList pairs)
123−
124−-- Empty strings need special handling to ensure they get quoted. This avoids:
125−-- https://github.com/snoyberg/yaml/issues/24
126−objToEvents' (String "") rest = EventScalar "" NoTag SingleQuoted Nothing : rest
127−
128−objToEvents' (String s) rest =
129− event : rest
130− where
131− event
132− -- Make sure that special strings are encoded as strings properly.
133− -- See: https://github.com/snoyberg/yaml/issues/31
134− | s `HashSet.member` specialStrings || isNumeric s = EventScalar (encodeUtf8 s) NoTag SingleQuoted Nothing
135− | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing
136−objToEvents' Null rest = EventScalar "null" NullTag PlainNoTag Nothing : rest
137−objToEvents' (Bool True) rest = EventScalar "true" BoolTag PlainNoTag Nothing : rest
138−objToEvents' (Bool False) rest = EventScalar "false" BoolTag PlainNoTag Nothing : rest
139−-- Use aeson's implementation which gets rid of annoying decimal points
140−objToEvents' n@Number{} rest = EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder n) IntTag PlainNoTag Nothing : rest
141−
142−pairToEvents :: Pair -> [Y.Event] -> [Y.Event]
143−pairToEvents (k, v) rest =
144− EventScalar (encodeUtf8 k) StrTag PlainNoTag Nothing
145− : objToEvents' v rest
146−
147−decode :: FromJSON a
148− => ByteString
149− -> Maybe a
150−decode bs = unsafePerformIO
151− $ either (const Nothing) id
152− <$> decodeHelper_ (Y.decode bs)
153−
154−decodeFile :: FromJSON a
155− => FilePath
156− -> IO (Maybe a)
157−decodeFile fp = decodeHelper (Y.decodeFile fp) >>= either throwIO (return . either (const Nothing) id)
158−
159−-- | A version of 'decodeFile' which should not throw runtime exceptions.
160−--
161−-- Since 0.8.4
162−decodeFileEither
163− :: FromJSON a
164− => FilePath
165− -> IO (Either ParseException a)
166−decodeFileEither = decodeHelper_ . Y.decodeFile
167−
168−decodeEither :: FromJSON a => ByteString -> Either String a
169−decodeEither bs = unsafePerformIO
170− $ either (Left . prettyPrintParseException) id
171− <$> decodeHelper (Y.decode bs)
172−
173−-- | More helpful version of 'decodeEither' which returns the 'YamlException'.
174−--
175−-- Since 0.8.3
176−decodeEither' :: FromJSON a => ByteString -> Either ParseException a
177−decodeEither' = either Left (either (Left . AesonException) Right)
178− . unsafePerformIO
179− . decodeHelper
180− . Y.decode
181−
182−array :: [Value] -> Value
183−array = Array . V.fromList
184−
185−parseMonad :: Monad m => (a -> Parser b) -> a -> m b
186−parseMonad p = either fail return . parseEither p
Data/Yaml/Builder.hsdeleted−113
@@ -1,113 +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− , array
11− , string
12− , bool
13− , null
14− , scientific
15− , number
16− , toByteString
17− , writeYamlFile
18− , (.=)
19− ) where
20−
21−import Prelude hiding (null)
22−
23−import Control.Arrow (second)
24−import Control.Monad.Trans.Resource (runResourceT)
25−import Data.Aeson.Encode (encodeToTextBuilder)
26−import Data.Aeson.Types (Value(..))
27−import Data.ByteString (ByteString)
28−import qualified Data.ByteString.Char8 as S8
29−import Data.Conduit
30−import qualified Data.HashSet as HashSet
31−import Data.Scientific (Scientific)
32−import Data.Text (Text)
33−import Data.Text.Encoding (encodeUtf8)
34−import qualified Data.Text.Encoding as TE
35−import qualified Data.Text.Lazy as TL
36−import Data.Text.Lazy.Builder (toLazyText)
37−import System.IO.Unsafe (unsafePerformIO)
38−
39−import Data.Yaml.Internal
40−import Text.Libyaml
41−
42−(.=) :: ToYaml a => Text -> a -> (Text, YamlBuilder)
43−k .= v = (k, toYaml v)
44−
45−newtype YamlBuilder = YamlBuilder { unYamlBuilder :: [Event] -> [Event] }
46−
47−class ToYaml a where
48− toYaml :: a -> YamlBuilder
49−instance ToYaml YamlBuilder where
50− toYaml = id
51−instance ToYaml a => ToYaml [(Text, a)] where
52− toYaml = mapping . map (second toYaml)
53−instance ToYaml a => ToYaml [a] where
54− toYaml = array . map toYaml
55−instance ToYaml Text where
56− toYaml = string
57−instance ToYaml Int where
58− toYaml i = YamlBuilder (EventScalar (S8.pack $ show i) IntTag PlainNoTag Nothing:)
59−
60−mapping :: [(Text, YamlBuilder)] -> YamlBuilder
61−mapping pairs = YamlBuilder $ \rest ->
62− EventMappingStart Nothing : foldr addPair (EventMappingEnd : rest) pairs
63− where
64− addPair (key, YamlBuilder value) after
65− = EventScalar (encodeUtf8 key) StrTag PlainNoTag Nothing
66− : value after
67−
68−array :: [YamlBuilder] -> YamlBuilder
69−array bs =
70− YamlBuilder $ (EventSequenceStart Nothing:) . flip (foldr go) bs . (EventSequenceEnd:)
71− where
72− go (YamlBuilder b) = b
73−
74−string :: Text -> YamlBuilder
75−-- Empty strings need special handling to ensure they get quoted. This avoids:
76−-- https://github.com/snoyberg/yaml/issues/24
77−string "" = YamlBuilder (EventScalar "" NoTag SingleQuoted Nothing :)
78−string s =
79− YamlBuilder (event :)
80− where
81− event
82− -- Make sure that special strings are encoded as strings properly.
83− -- See: https://github.com/snoyberg/yaml/issues/31
84− | s `HashSet.member` specialStrings || isNumeric s = EventScalar (encodeUtf8 s) NoTag SingleQuoted Nothing
85− | otherwise = EventScalar (encodeUtf8 s) StrTag PlainNoTag Nothing
86−
87−-- Use aeson's implementation which gets rid of annoying decimal points
88−scientific :: Scientific -> YamlBuilder
89−scientific n = YamlBuilder (EventScalar (TE.encodeUtf8 $ TL.toStrict $ toLazyText $ encodeToTextBuilder (Number n)) IntTag PlainNoTag Nothing :)
90−
91−{-# DEPRECATED number "Use scientific" #-}
92−number :: Scientific -> YamlBuilder
93−number = scientific
94−
95−bool :: Bool -> YamlBuilder
96−bool True = YamlBuilder (EventScalar "true" BoolTag PlainNoTag Nothing :)
97−bool False = YamlBuilder (EventScalar "false" BoolTag PlainNoTag Nothing :)
98−
99−null :: YamlBuilder
100−null = YamlBuilder (EventScalar "null" NullTag PlainNoTag Nothing :)
101−
102−toEvents :: YamlBuilder -> [Event]
103−toEvents (YamlBuilder front) =
104− EventStreamStart : EventDocumentStart : front [EventDocumentEnd, EventStreamEnd]
105−
106−toSource :: (Monad m, ToYaml a) => a -> Source m Event
107−toSource = mapM_ yield . toEvents . toYaml
108−
109−toByteString :: ToYaml a => a -> ByteString
110−toByteString yb = unsafePerformIO $ runResourceT $ toSource yb $$ encode
111−
112−writeYamlFile :: ToYaml a => FilePath -> a -> IO ()
113−writeYamlFile fp yb = runResourceT $ toSource yb $$ encodeFile fp
Data/Yaml/Internal.hsdeleted−279
@@ -1,279 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE PatternGuards #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−module Data.Yaml.Internal
6− (
7− ParseException(..)
8− , prettyPrintParseException
9− , parse
10− , decodeHelper
11− , decodeHelper_
12− , specialStrings
13− , isNumeric
14− ) where
15−
16−#if !MIN_VERSION_base(4,8,0)
17−import Control.Applicative ((<$>), Applicative(..))
18−#endif
19−import Control.Exception
20−import Control.Exception.Enclosed
21−import Control.Monad (liftM, ap, unless)
22−import Control.Monad.IO.Class (MonadIO, liftIO)
23−import Control.Monad.Trans.Class (MonadTrans, lift)
24−import Control.Monad.Trans.Resource (ResourceT, runResourceT)
25−import Control.Monad.Trans.State
26−import Data.Aeson
27−import Data.Aeson.Types hiding (parse)
28−import qualified Data.Attoparsec.Text as Atto
29−import Data.ByteString (ByteString)
30−import Data.Char (toUpper)
31−import qualified Data.Conduit as C
32−import qualified Data.Conduit.List as CL
33−import qualified Data.HashMap.Strict as M
34−import qualified Data.HashSet as HashSet
35−import qualified Data.Map as Map
36−import Data.Scientific (Scientific)
37−import Data.Text (Text, pack)
38−import qualified Data.Text as T
39−import Data.Text.Encoding (decodeUtf8With)
40−import Data.Text.Encoding.Error (lenientDecode)
41−import Data.Typeable
42−import qualified Data.Vector as V
43−
44−import qualified Text.Libyaml as Y
45−import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile)
46−
47−data ParseException = NonScalarKey
48− | UnknownAlias { _anchorName :: Y.AnchorName }
49− | UnexpectedEvent { _received :: Maybe Event
50− , _expected :: Maybe Event
51− }
52− | InvalidYaml (Maybe YamlException)
53− | AesonException String
54− | OtherParseException SomeException
55− | NonStringKeyAlias Y.AnchorName Value
56− | CyclicIncludes
57− deriving (Show, Typeable)
58−
59−instance Exception ParseException where
60−#if MIN_VERSION_base(4, 8, 0)
61− displayException = prettyPrintParseException
62−#endif
63−
64−-- | Alternative to 'show' to display a 'ParseException' on the screen.
65−-- Instead of displaying the data constructors applied to their arguments,
66−-- a more textual output is returned. For example, instead of printing:
67−--
68−-- > InvalidYaml (Just (YamlParseException {yamlProblem = "did not find expected ',' or '}'", yamlContext = "while parsing a flow mapping", yamlProblemMark = YamlMark {yamlIndex = 42, yamlLine = 2, yamlColumn = 12}})))
69−--
70−-- It looks more pleasant to print:
71−--
72−-- > YAML parse exception at line 2, column 12,
73−-- > while parsing a flow mapping:
74−-- > did not find expected ',' or '}'
75−--
76−-- Since 0.8.11
77−prettyPrintParseException :: ParseException -> String
78−prettyPrintParseException pe = case pe of
79− NonScalarKey -> "Non scalar key"
80− UnknownAlias anchor -> "Unknown alias `" ++ anchor ++ "`"
81− UnexpectedEvent { _expected = mbExpected, _received = mbUnexpected } -> unlines
82− [ "Unexpected event: expected"
83− , " " ++ show mbExpected
84− , "but received"
85− , " " ++ show mbUnexpected
86− ]
87− InvalidYaml mbYamlError -> case mbYamlError of
88− Nothing -> "Unspecified YAML error"
89− Just yamlError -> case yamlError of
90− YamlException s -> "YAML exception:\n" ++ s
91− YamlParseException problem context mark -> unlines
92− [ "YAML parse exception at line " ++ show (yamlLine mark) ++
93− ", column " ++ show (yamlColumn mark) ++ ","
94− -- The context seems to include a leading "while" or similar.
95− , context ++ ":"
96− , problem
97− ]
98− AesonException s -> "Aeson exception:\n" ++ s
99− OtherParseException exc -> "Generic parse exception:\n" ++ show exc
100− NonStringKeyAlias anchor value -> unlines
101− [ "Non-string key alias:"
102− , " Anchor name: " ++ anchor
103− , " Value: " ++ show value
104− ]
105− CyclicIncludes -> "Cyclic includes"
106−
107−newtype PErrorT m a = PErrorT { runPErrorT :: m (Either ParseException a) }
108−instance Monad m => Functor (PErrorT m) where
109− fmap = liftM
110−instance Monad m => Applicative (PErrorT m) where
111− pure = PErrorT . return . Right
112− (<*>) = ap
113−instance Monad m => Monad (PErrorT m) where
114− return = pure
115− (PErrorT m) >>= f = PErrorT $ do
116− e <- m
117− case e of
118− Left e' -> return $ Left e'
119− Right a -> runPErrorT $ f a
120−instance MonadTrans PErrorT where
121− lift = PErrorT . liftM Right
122−instance MonadIO m => MonadIO (PErrorT m) where
123− liftIO = lift . liftIO
124−
125−type Parse = StateT (Map.Map String Value) (ResourceT IO)
126−
127−requireEvent :: Event -> C.Sink Event Parse ()
128−requireEvent e = do
129− f <- CL.head
130− unless (f == Just e) $ liftIO $ throwIO $ UnexpectedEvent f $ Just e
131−
132−parse :: C.Sink Event Parse Value
133−parse = do
134− requireEvent EventStreamStart
135− requireEvent EventDocumentStart
136− res <- parseO
137− requireEvent EventDocumentEnd
138− requireEvent EventStreamEnd
139− return res
140−
141−parseScalar :: ByteString -> Anchor -> Style -> Tag
142− -> C.Sink Event Parse Text
143−parseScalar v a style tag = do
144− let res = decodeUtf8With lenientDecode v
145− case a of
146− Nothing -> return res
147− Just an -> do
148− lift $ modify (Map.insert an $ textToValue style tag res)
149− return res
150−
151−textToValue :: Style -> Tag -> Text -> Value
152−textToValue SingleQuoted _ t = String t
153−textToValue DoubleQuoted _ t = String t
154−textToValue _ StrTag t = String t
155−textToValue Folded _ t = String t
156−textToValue _ _ t
157− | t `elem` ["null", "Null", "NULL", "~", ""] = Null
158− | any (t `isLike`) ["y", "yes", "on", "true"] = Bool True
159− | any (t `isLike`) ["n", "no", "off", "false"] = Bool False
160− | Right x <- textToScientific t = Number x
161− | otherwise = String t
162− where x `isLike` ref = x `elem` [ref, T.toUpper ref, titleCased]
163− where titleCased = toUpper (T.head ref) `T.cons` T.tail ref
164−
165−textToScientific :: Text -> Either String Scientific
166−textToScientific = Atto.parseOnly (Atto.scientific <* Atto.endOfInput)
167−
168−parseO :: C.Sink Event Parse Value
169−parseO = do
170− me <- CL.head
171− case me of
172− Just (EventScalar v tag style a) -> textToValue style tag <$> parseScalar v a style tag
173− Just (EventSequenceStart a) -> parseS a id
174− Just (EventMappingStart a) -> parseM a M.empty
175− Just (EventAlias an) -> do
176− m <- lift get
177− case Map.lookup an m of
178− Nothing -> liftIO $ throwIO $ UnknownAlias an
179− Just v -> return v
180− _ -> liftIO $ throwIO $ UnexpectedEvent me Nothing
181−
182−parseS :: Y.Anchor
183− -> ([Value] -> [Value])
184− -> C.Sink Event Parse Value
185−parseS a front = do
186− me <- CL.peek
187− case me of
188− Just EventSequenceEnd -> do
189− CL.drop 1
190− let res = Array $ V.fromList $ front []
191− case a of
192− Nothing -> return res
193− Just an -> do
194− lift $ modify $ Map.insert an res
195− return res
196− _ -> do
197− o <- parseO
198− parseS a $ front . (:) o
199−
200−parseM :: Y.Anchor
201− -> M.HashMap Text Value
202− -> C.Sink Event Parse Value
203−parseM a front = do
204− me <- CL.peek
205− case me of
206− Just EventMappingEnd -> do
207− CL.drop 1
208− let res = Object front
209− case a of
210− Nothing -> return res
211− Just an -> do
212− lift $ modify $ Map.insert an res
213− return res
214− _ -> do
215− CL.drop 1
216− s <- case me of
217− Just (EventScalar v tag style a') -> parseScalar v a' style tag
218− Just (EventAlias an) -> do
219− m <- lift get
220− case Map.lookup an m of
221− Nothing -> liftIO $ throwIO $ UnknownAlias an
222− Just (String t) -> return t
223− Just v -> liftIO $ throwIO $ NonStringKeyAlias an v
224− _ -> liftIO $ throwIO $ UnexpectedEvent me Nothing
225− o <- parseO
226−
227− let al = M.insert s o front
228− al' = if s == pack "<<"
229− then case o of
230− Object l -> M.union front l
231− Array l -> M.union front $ foldl merge' M.empty $ V.toList l
232− _ -> al
233− else al
234− parseM a al'
235− where merge' al (Object om) = M.union al om
236− merge' al _ = al
237−
238−decodeHelper :: FromJSON a
239− => C.Source Parse Y.Event
240− -> IO (Either ParseException (Either String a))
241−decodeHelper src = do
242− x <- tryAny $ runResourceT $ flip evalStateT Map.empty $ src C.$$ parse
243− case x of
244− Left e
245− | Just pe <- fromException e -> return $ Left pe
246− | Just ye <- fromException e -> return $ Left $ InvalidYaml $ Just (ye :: YamlException)
247− | otherwise -> throwIO e
248− Right y -> return $ Right $ parseEither parseJSON y
249−
250−decodeHelper_ :: FromJSON a
251− => C.Source Parse Event
252− -> IO (Either ParseException a)
253−decodeHelper_ src = do
254− x <- tryAny $ runResourceT $ flip evalStateT Map.empty $ src C.$$ parse
255− return $ case x of
256− Left e
257− | Just pe <- fromException e -> Left pe
258− | Just ye <- fromException e -> Left $ InvalidYaml $ Just (ye :: YamlException)
259− | otherwise -> Left $ OtherParseException e
260− Right y -> either
261− (Left . AesonException)
262− Right
263− (parseEither parseJSON y)
264−
265−-- | Strings which must be escaped so as not to be treated as non-string scalars.
266−specialStrings :: HashSet.HashSet Text
267−specialStrings = HashSet.fromList $ T.words
268− "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 ~"
269−
270−isNumeric :: Text -> Bool
271−isNumeric =
272− T.all isNumeric'
273− where
274− isNumeric' c = ('0' <= c && c <= '9')
275− || c == 'e'
276− || c == 'E'
277− || c == '.'
278− || c == '-'
279− || c == '+'
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
README.md+16−10
@@ -1,17 +1,23 @@
1−## yaml
1+# YAML Haskell Library
22
3−Provides support for parsing and emitting Yaml documents.
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)
44
5−This package includes the [full libyaml C library version 0.1.5 by Kirill Simonov](http://pyyaml.org/wiki/LibYAML) in the package so you don't need to worry about any non-Haskell dependencies.
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.
67
7−The package is broken down into two primary modules. `Data.Yaml` provides a high-level interface based around the JSON datatypes provided by the `aeson` package. `Text.Libyaml` provides a lower-level, streaming interface. For most users, `Data.Yaml` is recommended.
8+## `yaml` Package
89
9−### Examples
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.
1013
11−Usage examples can be found in the `Data.Yaml` documentation or in the [examples](./examples) directory.
14+## `libyaml` Package
1215
13−### Additional modules
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.
1419
15−* `Data.Yaml.Include` supports adding `!include` directives to your YAML files.
16−* `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.
17−* `Data.Yaml.Aeson` is currently a re-export of `Data.Yaml` to explicitly choose to use the aeson-compatible API.
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
exe/json2yaml.hsdeleted−22
@@ -1,22 +0,0 @@
1−import Control.Monad (when)
2−import qualified Data.Aeson as J
3−import qualified Data.ByteString as S
4−import qualified Data.ByteString.Lazy as L
5−import System.Environment (getArgs)
6−
7−import qualified Data.Yaml as Y
8−
9−main :: IO ()
10−main = do
11− args <- getArgs
12− when (length args > 2) $ error "Usage: json2yaml [in] [out]"
13− let (input:output:_) = args ++ repeat "-"
14− mval <- fmap J.decode $
15− case input of
16− "-" -> L.getContents
17− _ -> L.readFile input
18− case mval of
19− Nothing -> error "Invalid input JSON"
20− Just val -> case output of
21− "-" -> S.putStr $ Y.encode (val :: Y.Value)
22− _ -> Y.encodeFile output val
exe/yaml2json.hsdeleted−28
@@ -1,28 +0,0 @@
1−import Prelude hiding (putStr, getContents)
2−
3−import Data.Aeson (encode, Value)
4−import Data.ByteString (getContents)
5−import Data.ByteString.Lazy (putStr)
6−import System.Environment (getArgs)
7−import System.Exit
8−
9−import Data.Yaml (decodeFileEither, decodeEither')
10−
11−helpMessage :: IO ()
12−helpMessage = putStrLn "yaml2json FILE\n use - as FILE to indicate stdin" >> exitFailure
13−
14−showJSON :: Show a => Either a Value -> IO b
15−showJSON ejson =
16− case ejson of
17− Left err -> print err >> exitFailure
18− Right res -> putStr (encode (res :: Value)) >> exitSuccess
19−
20−main :: IO ()
21−main = do
22− args <- getArgs
23− case args of
24− -- strict getContents will read in all of stdin at once
25− (["-"]) -> getContents >>= showJSON . decodeEither'
26− ([f]) -> decodeFileEither f >>= showJSON
27− _ -> helpMessage
28−
libyaml/ChangeLog.mdnew file+27
@@ -0,0 +1,27 @@
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/LICENSE+22−16
@@ -1,19 +1,25 @@
1−Copyright (c) 2006 Kirill Simonov
1+The following license covers this documentation, and the source code, except
2+where otherwise indicated.
23
3−Permission is hereby granted, free of charge, to any person obtaining a copy of
4−this software and associated documentation files (the "Software"), to deal in
5−the Software without restriction, including without limitation the rights to
6−use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7−of the Software, and to permit persons to whom the Software is furnished to do
8−so, subject to the following conditions:
4+Copyright 2008, Michael Snoyman. All rights reserved.
95
10−The above copyright notice and this permission notice shall be included in all
11−copies or substantial portions of the Software.
6+Redistribution and use in source and binary forms, with or without
7+modification, are permitted provided that the following conditions are met:
128
13−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19−SOFTWARE.
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.
libyaml/Makefile+4−9
@@ -1,9 +1,4 @@
1−CC = gcc
2−CFLAGS = -shared
3−OBJECTS = api.o dumper.o emitter.o loader.o parser.o reader.o scanner.o writer.o
4−LIB = libyaml.so
5−LFLAGS = -shared -Wl,-soname,libyaml.so
6−%.o: %.c
7− $(CC) $(CFLAGS) -c -fPIC $<
8−yaml: $(OBJECTS)
9− $(CC) $(LFLAGS) -o $(LIB) $(OBJECTS)
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.mdnew file+3
@@ -0,0 +1,3 @@
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.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
libyaml/api.cdeleted−1403
@@ -1,1403 +0,0 @@
1−
2−#include "yaml_private.h"
3−
4−/*
5− * Get the library version.
6− */
7−
8−/*
9− * added to support _WIN64
10− */
11−#if _WIN64
12−#define STRDUP _strdup
13−#else
14−#define STRDUP strdup
15−#endif
16−
17−YAML_DECLARE(const char *)
18−yaml_get_version_string(void)
19−{
20− return YAML_VERSION_STRING;
21−}
22−
23−/*
24− * Get the library version numbers.
25− */
26−
27−YAML_DECLARE(void)
28−yaml_get_version(int *major, int *minor, int *patch)
29−{
30− *major = YAML_VERSION_MAJOR;
31− *minor = YAML_VERSION_MINOR;
32− *patch = YAML_VERSION_PATCH;
33−}
34−
35−/*
36− * Allocate a dynamic memory block.
37− */
38−
39−YAML_DECLARE(void *)
40−yaml_malloc(size_t size)
41−{
42− return malloc(size ? size : 1);
43−}
44−
45−/*
46− * Reallocate a dynamic memory block.
47− */
48−
49−YAML_DECLARE(void *)
50−yaml_realloc(void *ptr, size_t size)
51−{
52− return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
53−}
54−
55−/*
56− * Free a dynamic memory block.
57− */
58−
59−YAML_DECLARE(void)
60−yaml_free(void *ptr)
61−{
62− if (ptr) free(ptr);
63−}
64−
65−/*
66− * Duplicate a string.
67− */
68−
69−YAML_DECLARE(yaml_char_t *)
70−yaml_strdup(const yaml_char_t *str)
71−{
72− if (!str)
73− return NULL;
74−
75− return (yaml_char_t *) STRDUP((char *)str);
76−}
77−
78−/*
79− * Extend a string.
80− */
81−
82−YAML_DECLARE(int)
83−yaml_string_extend(yaml_char_t **start,
84− yaml_char_t **pointer, yaml_char_t **end)
85−{
86− yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2);
87−
88− if (!new_start) return 0;
89−
90− memset(new_start + (*end - *start), 0, *end - *start);
91−
92− *pointer = new_start + (*pointer - *start);
93− *end = new_start + (*end - *start)*2;
94− *start = new_start;
95−
96− return 1;
97−}
98−
99−/*
100− * Append a string B to a string A.
101− */
102−
103−YAML_DECLARE(int)
104−yaml_string_join(
105− yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
106− yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)
107−{
108− if (*b_start == *b_pointer)
109− return 1;
110−
111− while (*a_end - *a_pointer <= *b_pointer - *b_start) {
112− if (!yaml_string_extend(a_start, a_pointer, a_end))
113− return 0;
114− }
115−
116− memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
117− *a_pointer += *b_pointer - *b_start;
118−
119− return 1;
120−}
121−
122−/*
123− * Extend a stack.
124− */
125−
126−YAML_DECLARE(int)
127−yaml_stack_extend(void **start, void **top, void **end)
128−{
129− void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
130−
131− if (!new_start) return 0;
132−
133− *top = (char *)new_start + ((char *)*top - (char *)*start);
134− *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
135− *start = new_start;
136−
137− return 1;
138−}
139−
140−/*
141− * Extend or move a queue.
142− */
143−
144−YAML_DECLARE(int)
145−yaml_queue_extend(void **start, void **head, void **tail, void **end)
146−{
147− /* Check if we need to resize the queue. */
148−
149− if (*start == *head && *tail == *end) {
150− void *new_start = yaml_realloc(*start,
151− ((char *)*end - (char *)*start)*2);
152−
153− if (!new_start) return 0;
154−
155− *head = (char *)new_start + ((char *)*head - (char *)*start);
156− *tail = (char *)new_start + ((char *)*tail - (char *)*start);
157− *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
158− *start = new_start;
159− }
160−
161− /* Check if we need to move the queue at the beginning of the buffer. */
162−
163− if (*tail == *end) {
164− if (*head != *tail) {
165− memmove(*start, *head, (char *)*tail - (char *)*head);
166− }
167− *tail = (char *)*tail - (char *)*head + (char *)*start;
168− *head = *start;
169− }
170−
171− return 1;
172−}
173−
174−
175−/*
176− * Create a new parser object.
177− */
178−
179−YAML_DECLARE(int)
180−yaml_parser_initialize(yaml_parser_t *parser)
181−{
182− assert(parser); /* Non-NULL parser object expected. */
183−
184− memset(parser, 0, sizeof(yaml_parser_t));
185− if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
186− goto error;
187− if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
188− goto error;
189− if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))
190− goto error;
191− if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))
192− goto error;
193− if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))
194− goto error;
195− if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))
196− goto error;
197− if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))
198− goto error;
199− if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))
200− goto error;
201−
202− return 1;
203−
204−error:
205−
206− BUFFER_DEL(parser, parser->raw_buffer);
207− BUFFER_DEL(parser, parser->buffer);
208− QUEUE_DEL(parser, parser->tokens);
209− STACK_DEL(parser, parser->indents);
210− STACK_DEL(parser, parser->simple_keys);
211− STACK_DEL(parser, parser->states);
212− STACK_DEL(parser, parser->marks);
213− STACK_DEL(parser, parser->tag_directives);
214−
215− return 0;
216−}
217−
218−/*
219− * Destroy a parser object.
220− */
221−
222−YAML_DECLARE(void)
223−yaml_parser_delete(yaml_parser_t *parser)
224−{
225− assert(parser); /* Non-NULL parser object expected. */
226−
227− BUFFER_DEL(parser, parser->raw_buffer);
228− BUFFER_DEL(parser, parser->buffer);
229− while (!QUEUE_EMPTY(parser, parser->tokens)) {
230− yaml_token_delete(&DEQUEUE(parser, parser->tokens));
231− }
232− QUEUE_DEL(parser, parser->tokens);
233− STACK_DEL(parser, parser->indents);
234− STACK_DEL(parser, parser->simple_keys);
235− STACK_DEL(parser, parser->states);
236− STACK_DEL(parser, parser->marks);
237− while (!STACK_EMPTY(parser, parser->tag_directives)) {
238− yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
239− yaml_free(tag_directive.handle);
240− yaml_free(tag_directive.prefix);
241− }
242− STACK_DEL(parser, parser->tag_directives);
243−
244− memset(parser, 0, sizeof(yaml_parser_t));
245−}
246−
247−/*
248− * String read handler.
249− */
250−
251−static int
252−yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
253− size_t *size_read)
254−{
255− yaml_parser_t *parser = data;
256−
257− if (parser->input.string.current == parser->input.string.end) {
258− *size_read = 0;
259− return 1;
260− }
261−
262− if (size > (size_t)(parser->input.string.end
263− - parser->input.string.current)) {
264− size = parser->input.string.end - parser->input.string.current;
265− }
266−
267− memcpy(buffer, parser->input.string.current, size);
268− parser->input.string.current += size;
269− *size_read = size;
270− return 1;
271−}
272−
273−/*
274− * File read handler.
275− */
276−
277−static int
278−yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
279− size_t *size_read)
280−{
281− yaml_parser_t *parser = data;
282−
283− *size_read = fread(buffer, 1, size, parser->input.file);
284− return !ferror(parser->input.file);
285−}
286−
287−/*
288− * Set a string input.
289− */
290−
291−YAML_DECLARE(void)
292−yaml_parser_set_input_string(yaml_parser_t *parser,
293− const unsigned char *input, size_t size)
294−{
295− assert(parser); /* Non-NULL parser object expected. */
296− assert(!parser->read_handler); /* You can set the source only once. */
297− assert(input); /* Non-NULL input string expected. */
298−
299− parser->read_handler = yaml_string_read_handler;
300− parser->read_handler_data = parser;
301−
302− parser->input.string.start = input;
303− parser->input.string.current = input;
304− parser->input.string.end = input+size;
305−}
306−
307−/*
308− * Set a file input.
309− */
310−
311−YAML_DECLARE(void)
312−yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
313−{
314− assert(parser); /* Non-NULL parser object expected. */
315− assert(!parser->read_handler); /* You can set the source only once. */
316− assert(file); /* Non-NULL file object expected. */
317−
318− parser->read_handler = yaml_file_read_handler;
319− parser->read_handler_data = parser;
320−
321− parser->input.file = file;
322−}
323−
324−/*
325− * Set a generic input.
326− */
327−
328−YAML_DECLARE(void)
329−yaml_parser_set_input(yaml_parser_t *parser,
330− yaml_read_handler_t *handler, void *data)
331−{
332− assert(parser); /* Non-NULL parser object expected. */
333− assert(!parser->read_handler); /* You can set the source only once. */
334− assert(handler); /* Non-NULL read handler expected. */
335−
336− parser->read_handler = handler;
337− parser->read_handler_data = data;
338−}
339−
340−/*
341− * Set the source encoding.
342− */
343−
344−YAML_DECLARE(void)
345−yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
346−{
347− assert(parser); /* Non-NULL parser object expected. */
348− assert(!parser->encoding); /* Encoding is already set or detected. */
349−
350− parser->encoding = encoding;
351−}
352−
353−/*
354− * Create a new emitter object.
355− */
356−
357−YAML_DECLARE(int)
358−yaml_emitter_initialize(yaml_emitter_t *emitter)
359−{
360− assert(emitter); /* Non-NULL emitter object expected. */
361−
362− memset(emitter, 0, sizeof(yaml_emitter_t));
363− if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE))
364− goto error;
365− if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE))
366− goto error;
367− if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE))
368− goto error;
369− if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE))
370− goto error;
371− if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE))
372− goto error;
373− if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE))
374− goto error;
375−
376− return 1;
377−
378−error:
379−
380− BUFFER_DEL(emitter, emitter->buffer);
381− BUFFER_DEL(emitter, emitter->raw_buffer);
382− STACK_DEL(emitter, emitter->states);
383− QUEUE_DEL(emitter, emitter->events);
384− STACK_DEL(emitter, emitter->indents);
385− STACK_DEL(emitter, emitter->tag_directives);
386−
387− return 0;
388−}
389−
390−/*
391− * Destroy an emitter object.
392− */
393−
394−YAML_DECLARE(void)
395−yaml_emitter_delete(yaml_emitter_t *emitter)
396−{
397− assert(emitter); /* Non-NULL emitter object expected. */
398−
399− BUFFER_DEL(emitter, emitter->buffer);
400− BUFFER_DEL(emitter, emitter->raw_buffer);
401− STACK_DEL(emitter, emitter->states);
402− while (!QUEUE_EMPTY(emitter, emitter->events)) {
403− yaml_event_delete(&DEQUEUE(emitter, emitter->events));
404− }
405− QUEUE_DEL(emitter, emitter->events);
406− STACK_DEL(emitter, emitter->indents);
407− while (!STACK_EMPTY(empty, emitter->tag_directives)) {
408− yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives);
409− yaml_free(tag_directive.handle);
410− yaml_free(tag_directive.prefix);
411− }
412− STACK_DEL(emitter, emitter->tag_directives);
413− yaml_free(emitter->anchors);
414−
415− memset(emitter, 0, sizeof(yaml_emitter_t));
416−}
417−
418−/*
419− * String write handler.
420− */
421−
422−static int
423−yaml_string_write_handler(void *data, unsigned char *buffer, size_t size)
424−{
425− yaml_emitter_t *emitter = data;
426−
427− if (emitter->output.string.size + *emitter->output.string.size_written
428− < size) {
429− memcpy(emitter->output.string.buffer
430− + *emitter->output.string.size_written,
431− buffer,
432− emitter->output.string.size
433− - *emitter->output.string.size_written);
434− *emitter->output.string.size_written = emitter->output.string.size;
435− return 0;
436− }
437−
438− memcpy(emitter->output.string.buffer
439− + *emitter->output.string.size_written, buffer, size);
440− *emitter->output.string.size_written += size;
441− return 1;
442−}
443−
444−/*
445− * File write handler.
446− */
447−
448−static int
449−yaml_file_write_handler(void *data, unsigned char *buffer, size_t size)
450−{
451− yaml_emitter_t *emitter = data;
452−
453− return (fwrite(buffer, 1, size, emitter->output.file) == size);
454−}
455−/*
456− * Set a string output.
457− */
458−
459−YAML_DECLARE(void)
460−yaml_emitter_set_output_string(yaml_emitter_t *emitter,
461− unsigned char *output, size_t size, size_t *size_written)
462−{
463− assert(emitter); /* Non-NULL emitter object expected. */
464− assert(!emitter->write_handler); /* You can set the output only once. */
465− assert(output); /* Non-NULL output string expected. */
466−
467− emitter->write_handler = yaml_string_write_handler;
468− emitter->write_handler_data = emitter;
469−
470− emitter->output.string.buffer = output;
471− emitter->output.string.size = size;
472− emitter->output.string.size_written = size_written;
473− *size_written = 0;
474−}
475−
476−/*
477− * Set a file output.
478− */
479−
480−YAML_DECLARE(void)
481−yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file)
482−{
483− assert(emitter); /* Non-NULL emitter object expected. */
484− assert(!emitter->write_handler); /* You can set the output only once. */
485− assert(file); /* Non-NULL file object expected. */
486−
487− emitter->write_handler = yaml_file_write_handler;
488− emitter->write_handler_data = emitter;
489−
490− emitter->output.file = file;
491−}
492−
493−/*
494− * Set a generic output handler.
495− */
496−
497−YAML_DECLARE(void)
498−yaml_emitter_set_output(yaml_emitter_t *emitter,
499− yaml_write_handler_t *handler, void *data)
500−{
501− assert(emitter); /* Non-NULL emitter object expected. */
502− assert(!emitter->write_handler); /* You can set the output only once. */
503− assert(handler); /* Non-NULL handler object expected. */
504−
505− emitter->write_handler = handler;
506− emitter->write_handler_data = data;
507−}
508−
509−/*
510− * Set the output encoding.
511− */
512−
513−YAML_DECLARE(void)
514−yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding)
515−{
516− assert(emitter); /* Non-NULL emitter object expected. */
517− assert(!emitter->encoding); /* You can set encoding only once. */
518−
519− emitter->encoding = encoding;
520−}
521−
522−/*
523− * Set the canonical output style.
524− */
525−
526−YAML_DECLARE(void)
527−yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical)
528−{
529− assert(emitter); /* Non-NULL emitter object expected. */
530−
531− emitter->canonical = (canonical != 0);
532−}
533−
534−/*
535− * Set the indentation increment.
536− */
537−
538−YAML_DECLARE(void)
539−yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent)
540−{
541− assert(emitter); /* Non-NULL emitter object expected. */
542−
543− emitter->best_indent = (1 < indent && indent < 10) ? indent : 2;
544−}
545−
546−/*
547− * Set the preferred line width.
548− */
549−
550−YAML_DECLARE(void)
551−yaml_emitter_set_width(yaml_emitter_t *emitter, int width)
552−{
553− assert(emitter); /* Non-NULL emitter object expected. */
554−
555− emitter->best_width = (width >= 0) ? width : -1;
556−}
557−
558−/*
559− * Set if unescaped non-ASCII characters are allowed.
560− */
561−
562−YAML_DECLARE(void)
563−yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode)
564−{
565− assert(emitter); /* Non-NULL emitter object expected. */
566−
567− emitter->unicode = (unicode != 0);
568−}
569−
570−/*
571− * Set the preferred line break character.
572− */
573−
574−YAML_DECLARE(void)
575−yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break)
576−{
577− assert(emitter); /* Non-NULL emitter object expected. */
578−
579− emitter->line_break = line_break;
580−}
581−
582−/*
583− * Destroy a token object.
584− */
585−
586−YAML_DECLARE(void)
587−yaml_token_delete(yaml_token_t *token)
588−{
589− assert(token); /* Non-NULL token object expected. */
590−
591− switch (token->type)
592− {
593− case YAML_TAG_DIRECTIVE_TOKEN:
594− yaml_free(token->data.tag_directive.handle);
595− yaml_free(token->data.tag_directive.prefix);
596− break;
597−
598− case YAML_ALIAS_TOKEN:
599− yaml_free(token->data.alias.value);
600− break;
601−
602− case YAML_ANCHOR_TOKEN:
603− yaml_free(token->data.anchor.value);
604− break;
605−
606− case YAML_TAG_TOKEN:
607− yaml_free(token->data.tag.handle);
608− yaml_free(token->data.tag.suffix);
609− break;
610−
611− case YAML_SCALAR_TOKEN:
612− yaml_free(token->data.scalar.value);
613− break;
614−
615− default:
616− break;
617− }
618−
619− memset(token, 0, sizeof(yaml_token_t));
620−}
621−
622−/*
623− * Check if a string is a valid UTF-8 sequence.
624− *
625− * Check 'reader.c' for more details on UTF-8 encoding.
626− */
627−
628−static int
629−yaml_check_utf8(yaml_char_t *start, size_t length)
630−{
631− yaml_char_t *end = start+length;
632− yaml_char_t *pointer = start;
633−
634− while (pointer < end) {
635− unsigned char octet;
636− unsigned int width;
637− unsigned int value;
638− size_t k;
639−
640− octet = pointer[0];
641− width = (octet & 0x80) == 0x00 ? 1 :
642− (octet & 0xE0) == 0xC0 ? 2 :
643− (octet & 0xF0) == 0xE0 ? 3 :
644− (octet & 0xF8) == 0xF0 ? 4 : 0;
645− value = (octet & 0x80) == 0x00 ? octet & 0x7F :
646− (octet & 0xE0) == 0xC0 ? octet & 0x1F :
647− (octet & 0xF0) == 0xE0 ? octet & 0x0F :
648− (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
649− if (!width) return 0;
650− if (pointer+width > end) return 0;
651− for (k = 1; k < width; k ++) {
652− octet = pointer[k];
653− if ((octet & 0xC0) != 0x80) return 0;
654− value = (value << 6) + (octet & 0x3F);
655− }
656− if (!((width == 1) ||
657− (width == 2 && value >= 0x80) ||
658− (width == 3 && value >= 0x800) ||
659− (width == 4 && value >= 0x10000))) return 0;
660−
661− pointer += width;
662− }
663−
664− return 1;
665−}
666−
667−/*
668− * Create STREAM-START.
669− */
670−
671−YAML_DECLARE(int)
672−yaml_stream_start_event_initialize(yaml_event_t *event,
673− yaml_encoding_t encoding)
674−{
675− yaml_mark_t mark = { 0, 0, 0 };
676−
677− assert(event); /* Non-NULL event object is expected. */
678−
679− STREAM_START_EVENT_INIT(*event, encoding, mark, mark);
680−
681− return 1;
682−}
683−
684−/*
685− * Create STREAM-END.
686− */
687−
688−YAML_DECLARE(int)
689−yaml_stream_end_event_initialize(yaml_event_t *event)
690−{
691− yaml_mark_t mark = { 0, 0, 0 };
692−
693− assert(event); /* Non-NULL event object is expected. */
694−
695− STREAM_END_EVENT_INIT(*event, mark, mark);
696−
697− return 1;
698−}
699−
700−/*
701− * Create DOCUMENT-START.
702− */
703−
704−YAML_DECLARE(int)
705−yaml_document_start_event_initialize(yaml_event_t *event,
706− yaml_version_directive_t *version_directive,
707− yaml_tag_directive_t *tag_directives_start,
708− yaml_tag_directive_t *tag_directives_end,
709− int implicit)
710−{
711− struct {
712− yaml_error_type_t error;
713− } context;
714− yaml_mark_t mark = { 0, 0, 0 };
715− yaml_version_directive_t *version_directive_copy = NULL;
716− struct {
717− yaml_tag_directive_t *start;
718− yaml_tag_directive_t *end;
719− yaml_tag_directive_t *top;
720− } tag_directives_copy = { NULL, NULL, NULL };
721− yaml_tag_directive_t value = { NULL, NULL };
722−
723− assert(event); /* Non-NULL event object is expected. */
724− assert((tag_directives_start && tag_directives_end) ||
725− (tag_directives_start == tag_directives_end));
726− /* Valid tag directives are expected. */
727−
728− if (version_directive) {
729− version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
730− if (!version_directive_copy) goto error;
731− version_directive_copy->major = version_directive->major;
732− version_directive_copy->minor = version_directive->minor;
733− }
734−
735− if (tag_directives_start != tag_directives_end) {
736− yaml_tag_directive_t *tag_directive;
737− if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
738− goto error;
739− for (tag_directive = tag_directives_start;
740− tag_directive != tag_directives_end; tag_directive ++) {
741− assert(tag_directive->handle);
742− assert(tag_directive->prefix);
743− if (!yaml_check_utf8(tag_directive->handle,
744− strlen((char *)tag_directive->handle)))
745− goto error;
746− if (!yaml_check_utf8(tag_directive->prefix,
747− strlen((char *)tag_directive->prefix)))
748− goto error;
749− value.handle = yaml_strdup(tag_directive->handle);
750− value.prefix = yaml_strdup(tag_directive->prefix);
751− if (!value.handle || !value.prefix) goto error;
752− if (!PUSH(&context, tag_directives_copy, value))
753− goto error;
754− value.handle = NULL;
755− value.prefix = NULL;
756− }
757− }
758−
759− DOCUMENT_START_EVENT_INIT(*event, version_directive_copy,
760− tag_directives_copy.start, tag_directives_copy.top,
761− implicit, mark, mark);
762−
763− return 1;
764−
765−error:
766− yaml_free(version_directive_copy);
767− while (!STACK_EMPTY(context, tag_directives_copy)) {
768− yaml_tag_directive_t value = POP(context, tag_directives_copy);
769− yaml_free(value.handle);
770− yaml_free(value.prefix);
771− }
772− STACK_DEL(context, tag_directives_copy);
773− yaml_free(value.handle);
774− yaml_free(value.prefix);
775−
776− return 0;
777−}
778−
779−/*
780− * Create DOCUMENT-END.
781− */
782−
783−YAML_DECLARE(int)
784−yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
785−{
786− yaml_mark_t mark = { 0, 0, 0 };
787−
788− assert(event); /* Non-NULL emitter object is expected. */
789−
790− DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark);
791−
792− return 1;
793−}
794−
795−/*
796− * Create ALIAS.
797− */
798−
799−YAML_DECLARE(int)
800−yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
801−{
802− yaml_mark_t mark = { 0, 0, 0 };
803− yaml_char_t *anchor_copy = NULL;
804−
805− assert(event); /* Non-NULL event object is expected. */
806− assert(anchor); /* Non-NULL anchor is expected. */
807−
808− if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0;
809−
810− anchor_copy = yaml_strdup(anchor);
811− if (!anchor_copy)
812− return 0;
813−
814− ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark);
815−
816− return 1;
817−}
818−
819−/*
820− * Create SCALAR.
821− */
822−
823−YAML_DECLARE(int)
824−yaml_scalar_event_initialize(yaml_event_t *event,
825− yaml_char_t *anchor, yaml_char_t *tag,
826− yaml_char_t *value, int length,
827− int plain_implicit, int quoted_implicit,
828− yaml_scalar_style_t style)
829−{
830− yaml_mark_t mark = { 0, 0, 0 };
831− yaml_char_t *anchor_copy = NULL;
832− yaml_char_t *tag_copy = NULL;
833− yaml_char_t *value_copy = NULL;
834−
835− assert(event); /* Non-NULL event object is expected. */
836− /* following line added for Haskell yaml library */
837− if (!value && !length) value = "";
838− assert(value); /* Non-NULL anchor is expected. */
839−
840− if (anchor) {
841− if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
842− anchor_copy = yaml_strdup(anchor);
843− if (!anchor_copy) goto error;
844− }
845−
846− if (tag) {
847− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
848− tag_copy = yaml_strdup(tag);
849− if (!tag_copy) goto error;
850− }
851−
852− if (length < 0) {
853− length = strlen((char *)value);
854− }
855−
856− if (!yaml_check_utf8(value, length)) goto error;
857− value_copy = yaml_malloc(length+1);
858− if (!value_copy) goto error;
859− memcpy(value_copy, value, length);
860− value_copy[length] = '\0';
861−
862− SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length,
863− plain_implicit, quoted_implicit, style, mark, mark);
864−
865− return 1;
866−
867−error:
868− yaml_free(anchor_copy);
869− yaml_free(tag_copy);
870− yaml_free(value_copy);
871−
872− return 0;
873−}
874−
875−/*
876− * Create SEQUENCE-START.
877− */
878−
879−YAML_DECLARE(int)
880−yaml_sequence_start_event_initialize(yaml_event_t *event,
881− yaml_char_t *anchor, yaml_char_t *tag, int implicit,
882− yaml_sequence_style_t style)
883−{
884− yaml_mark_t mark = { 0, 0, 0 };
885− yaml_char_t *anchor_copy = NULL;
886− yaml_char_t *tag_copy = NULL;
887−
888− assert(event); /* Non-NULL event object is expected. */
889−
890− if (anchor) {
891− if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
892− anchor_copy = yaml_strdup(anchor);
893− if (!anchor_copy) goto error;
894− }
895−
896− if (tag) {
897− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
898− tag_copy = yaml_strdup(tag);
899− if (!tag_copy) goto error;
900− }
901−
902− SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy,
903− implicit, style, mark, mark);
904−
905− return 1;
906−
907−error:
908− yaml_free(anchor_copy);
909− yaml_free(tag_copy);
910−
911− return 0;
912−}
913−
914−/*
915− * Create SEQUENCE-END.
916− */
917−
918−YAML_DECLARE(int)
919−yaml_sequence_end_event_initialize(yaml_event_t *event)
920−{
921− yaml_mark_t mark = { 0, 0, 0 };
922−
923− assert(event); /* Non-NULL event object is expected. */
924−
925− SEQUENCE_END_EVENT_INIT(*event, mark, mark);
926−
927− return 1;
928−}
929−
930−/*
931− * Create MAPPING-START.
932− */
933−
934−YAML_DECLARE(int)
935−yaml_mapping_start_event_initialize(yaml_event_t *event,
936− yaml_char_t *anchor, yaml_char_t *tag, int implicit,
937− yaml_mapping_style_t style)
938−{
939− yaml_mark_t mark = { 0, 0, 0 };
940− yaml_char_t *anchor_copy = NULL;
941− yaml_char_t *tag_copy = NULL;
942−
943− assert(event); /* Non-NULL event object is expected. */
944−
945− if (anchor) {
946− if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error;
947− anchor_copy = yaml_strdup(anchor);
948− if (!anchor_copy) goto error;
949− }
950−
951− if (tag) {
952− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
953− tag_copy = yaml_strdup(tag);
954− if (!tag_copy) goto error;
955− }
956−
957− MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy,
958− implicit, style, mark, mark);
959−
960− return 1;
961−
962−error:
963− yaml_free(anchor_copy);
964− yaml_free(tag_copy);
965−
966− return 0;
967−}
968−
969−/*
970− * Create MAPPING-END.
971− */
972−
973−YAML_DECLARE(int)
974−yaml_mapping_end_event_initialize(yaml_event_t *event)
975−{
976− yaml_mark_t mark = { 0, 0, 0 };
977−
978− assert(event); /* Non-NULL event object is expected. */
979−
980− MAPPING_END_EVENT_INIT(*event, mark, mark);
981−
982− return 1;
983−}
984−
985−/*
986− * Destroy an event object.
987− */
988−
989−YAML_DECLARE(void)
990−yaml_event_delete(yaml_event_t *event)
991−{
992− yaml_tag_directive_t *tag_directive;
993−
994− assert(event); /* Non-NULL event object expected. */
995−
996− switch (event->type)
997− {
998− case YAML_DOCUMENT_START_EVENT:
999− yaml_free(event->data.document_start.version_directive);
1000− for (tag_directive = event->data.document_start.tag_directives.start;
1001− tag_directive != event->data.document_start.tag_directives.end;
1002− tag_directive++) {
1003− yaml_free(tag_directive->handle);
1004− yaml_free(tag_directive->prefix);
1005− }
1006− yaml_free(event->data.document_start.tag_directives.start);
1007− break;
1008−
1009− case YAML_ALIAS_EVENT:
1010− yaml_free(event->data.alias.anchor);
1011− break;
1012−
1013− case YAML_SCALAR_EVENT:
1014− yaml_free(event->data.scalar.anchor);
1015− yaml_free(event->data.scalar.tag);
1016− yaml_free(event->data.scalar.value);
1017− break;
1018−
1019− case YAML_SEQUENCE_START_EVENT:
1020− yaml_free(event->data.sequence_start.anchor);
1021− yaml_free(event->data.sequence_start.tag);
1022− break;
1023−
1024− case YAML_MAPPING_START_EVENT:
1025− yaml_free(event->data.mapping_start.anchor);
1026− yaml_free(event->data.mapping_start.tag);
1027− break;
1028−
1029− default:
1030− break;
1031− }
1032−
1033− memset(event, 0, sizeof(yaml_event_t));
1034−}
1035−
1036−/*
1037− * Create a document object.
1038− */
1039−
1040−YAML_DECLARE(int)
1041−yaml_document_initialize(yaml_document_t *document,
1042− yaml_version_directive_t *version_directive,
1043− yaml_tag_directive_t *tag_directives_start,
1044− yaml_tag_directive_t *tag_directives_end,
1045− int start_implicit, int end_implicit)
1046−{
1047− struct {
1048− yaml_error_type_t error;
1049− } context;
1050− struct {
1051− yaml_node_t *start;
1052− yaml_node_t *end;
1053− yaml_node_t *top;
1054− } nodes = { NULL, NULL, NULL };
1055− yaml_version_directive_t *version_directive_copy = NULL;
1056− struct {
1057− yaml_tag_directive_t *start;
1058− yaml_tag_directive_t *end;
1059− yaml_tag_directive_t *top;
1060− } tag_directives_copy = { NULL, NULL, NULL };
1061− yaml_tag_directive_t value = { NULL, NULL };
1062− yaml_mark_t mark = { 0, 0, 0 };
1063−
1064− assert(document); /* Non-NULL document object is expected. */
1065− assert((tag_directives_start && tag_directives_end) ||
1066− (tag_directives_start == tag_directives_end));
1067− /* Valid tag directives are expected. */
1068−
1069− if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;
1070−
1071− if (version_directive) {
1072− version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));
1073− if (!version_directive_copy) goto error;
1074− version_directive_copy->major = version_directive->major;
1075− version_directive_copy->minor = version_directive->minor;
1076− }
1077−
1078− if (tag_directives_start != tag_directives_end) {
1079− yaml_tag_directive_t *tag_directive;
1080− if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
1081− goto error;
1082− for (tag_directive = tag_directives_start;
1083− tag_directive != tag_directives_end; tag_directive ++) {
1084− assert(tag_directive->handle);
1085− assert(tag_directive->prefix);
1086− if (!yaml_check_utf8(tag_directive->handle,
1087− strlen((char *)tag_directive->handle)))
1088− goto error;
1089− if (!yaml_check_utf8(tag_directive->prefix,
1090− strlen((char *)tag_directive->prefix)))
1091− goto error;
1092− value.handle = yaml_strdup(tag_directive->handle);
1093− value.prefix = yaml_strdup(tag_directive->prefix);
1094− if (!value.handle || !value.prefix) goto error;
1095− if (!PUSH(&context, tag_directives_copy, value))
1096− goto error;
1097− value.handle = NULL;
1098− value.prefix = NULL;
1099− }
1100− }
1101−
1102− DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
1103− tag_directives_copy.start, tag_directives_copy.top,
1104− start_implicit, end_implicit, mark, mark);
1105−
1106− return 1;
1107−
1108−error:
1109− STACK_DEL(&context, nodes);
1110− yaml_free(version_directive_copy);
1111− while (!STACK_EMPTY(&context, tag_directives_copy)) {
1112− yaml_tag_directive_t value = POP(&context, tag_directives_copy);
1113− yaml_free(value.handle);
1114− yaml_free(value.prefix);
1115− }
1116− STACK_DEL(&context, tag_directives_copy);
1117− yaml_free(value.handle);
1118− yaml_free(value.prefix);
1119−
1120− return 0;
1121−}
1122−
1123−/*
1124− * Destroy a document object.
1125− */
1126−
1127−YAML_DECLARE(void)
1128−yaml_document_delete(yaml_document_t *document)
1129−{
1130− struct {
1131− yaml_error_type_t error;
1132− } context;
1133− yaml_tag_directive_t *tag_directive;
1134−
1135− context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */
1136−
1137− assert(document); /* Non-NULL document object is expected. */
1138−
1139− while (!STACK_EMPTY(&context, document->nodes)) {
1140− yaml_node_t node = POP(&context, document->nodes);
1141− yaml_free(node.tag);
1142− switch (node.type) {
1143− case YAML_SCALAR_NODE:
1144− yaml_free(node.data.scalar.value);
1145− break;
1146− case YAML_SEQUENCE_NODE:
1147− STACK_DEL(&context, node.data.sequence.items);
1148− break;
1149− case YAML_MAPPING_NODE:
1150− STACK_DEL(&context, node.data.mapping.pairs);
1151− break;
1152− default:
1153− assert(0); /* Should not happen. */
1154− }
1155− }
1156− STACK_DEL(&context, document->nodes);
1157−
1158− yaml_free(document->version_directive);
1159− for (tag_directive = document->tag_directives.start;
1160− tag_directive != document->tag_directives.end;
1161− tag_directive++) {
1162− yaml_free(tag_directive->handle);
1163− yaml_free(tag_directive->prefix);
1164− }
1165− yaml_free(document->tag_directives.start);
1166−
1167− memset(document, 0, sizeof(yaml_document_t));
1168−}
1169−
1170−/**
1171− * Get a document node.
1172− */
1173−
1174−YAML_DECLARE(yaml_node_t *)
1175−yaml_document_get_node(yaml_document_t *document, int index)
1176−{
1177− assert(document); /* Non-NULL document object is expected. */
1178−
1179− if (index > 0 && document->nodes.start + index <= document->nodes.top) {
1180− return document->nodes.start + index - 1;
1181− }
1182− return NULL;
1183−}
1184−
1185−/**
1186− * Get the root object.
1187− */
1188−
1189−YAML_DECLARE(yaml_node_t *)
1190−yaml_document_get_root_node(yaml_document_t *document)
1191−{
1192− assert(document); /* Non-NULL document object is expected. */
1193−
1194− if (document->nodes.top != document->nodes.start) {
1195− return document->nodes.start;
1196− }
1197− return NULL;
1198−}
1199−
1200−/*
1201− * Add a scalar node to a document.
1202− */
1203−
1204−YAML_DECLARE(int)
1205−yaml_document_add_scalar(yaml_document_t *document,
1206− yaml_char_t *tag, yaml_char_t *value, int length,
1207− yaml_scalar_style_t style)
1208−{
1209− struct {
1210− yaml_error_type_t error;
1211− } context;
1212− yaml_mark_t mark = { 0, 0, 0 };
1213− yaml_char_t *tag_copy = NULL;
1214− yaml_char_t *value_copy = NULL;
1215− yaml_node_t node;
1216−
1217− assert(document); /* Non-NULL document object is expected. */
1218− assert(value); /* Non-NULL value is expected. */
1219−
1220− if (!tag) {
1221− tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG;
1222− }
1223−
1224− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1225− tag_copy = yaml_strdup(tag);
1226− if (!tag_copy) goto error;
1227−
1228− if (length < 0) {
1229− length = strlen((char *)value);
1230− }
1231−
1232− if (!yaml_check_utf8(value, length)) goto error;
1233− value_copy = yaml_malloc(length+1);
1234− if (!value_copy) goto error;
1235− memcpy(value_copy, value, length);
1236− value_copy[length] = '\0';
1237−
1238− SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark);
1239− if (!PUSH(&context, document->nodes, node)) goto error;
1240−
1241− return document->nodes.top - document->nodes.start;
1242−
1243−error:
1244− yaml_free(tag_copy);
1245− yaml_free(value_copy);
1246−
1247− return 0;
1248−}
1249−
1250−/*
1251− * Add a sequence node to a document.
1252− */
1253−
1254−YAML_DECLARE(int)
1255−yaml_document_add_sequence(yaml_document_t *document,
1256− yaml_char_t *tag, yaml_sequence_style_t style)
1257−{
1258− struct {
1259− yaml_error_type_t error;
1260− } context;
1261− yaml_mark_t mark = { 0, 0, 0 };
1262− yaml_char_t *tag_copy = NULL;
1263− struct {
1264− yaml_node_item_t *start;
1265− yaml_node_item_t *end;
1266− yaml_node_item_t *top;
1267− } items = { NULL, NULL, NULL };
1268− yaml_node_t node;
1269−
1270− assert(document); /* Non-NULL document object is expected. */
1271−
1272− if (!tag) {
1273− tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG;
1274− }
1275−
1276− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1277− tag_copy = yaml_strdup(tag);
1278− if (!tag_copy) goto error;
1279−
1280− if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;
1281−
1282− SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
1283− style, mark, mark);
1284− if (!PUSH(&context, document->nodes, node)) goto error;
1285−
1286− return document->nodes.top - document->nodes.start;
1287−
1288−error:
1289− STACK_DEL(&context, items);
1290− yaml_free(tag_copy);
1291−
1292− return 0;
1293−}
1294−
1295−/*
1296− * Add a mapping node to a document.
1297− */
1298−
1299−YAML_DECLARE(int)
1300−yaml_document_add_mapping(yaml_document_t *document,
1301− yaml_char_t *tag, yaml_mapping_style_t style)
1302−{
1303− struct {
1304− yaml_error_type_t error;
1305− } context;
1306− yaml_mark_t mark = { 0, 0, 0 };
1307− yaml_char_t *tag_copy = NULL;
1308− struct {
1309− yaml_node_pair_t *start;
1310− yaml_node_pair_t *end;
1311− yaml_node_pair_t *top;
1312− } pairs = { NULL, NULL, NULL };
1313− yaml_node_t node;
1314−
1315− assert(document); /* Non-NULL document object is expected. */
1316−
1317− if (!tag) {
1318− tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG;
1319− }
1320−
1321− if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error;
1322− tag_copy = yaml_strdup(tag);
1323− if (!tag_copy) goto error;
1324−
1325− if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;
1326−
1327− MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
1328− style, mark, mark);
1329− if (!PUSH(&context, document->nodes, node)) goto error;
1330−
1331− return document->nodes.top - document->nodes.start;
1332−
1333−error:
1334− STACK_DEL(&context, pairs);
1335− yaml_free(tag_copy);
1336−
1337− return 0;
1338−}
1339−
1340−/*
1341− * Append an item to a sequence node.
1342− */
1343−
1344−YAML_DECLARE(int)
1345−yaml_document_append_sequence_item(yaml_document_t *document,
1346− int sequence, int item)
1347−{
1348− struct {
1349− yaml_error_type_t error;
1350− } context;
1351−
1352− assert(document); /* Non-NULL document is required. */
1353− assert(sequence > 0
1354− && document->nodes.start + sequence <= document->nodes.top);
1355− /* Valid sequence id is required. */
1356− assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE);
1357− /* A sequence node is required. */
1358− assert(item > 0 && document->nodes.start + item <= document->nodes.top);
1359− /* Valid item id is required. */
1360−
1361− if (!PUSH(&context,
1362− document->nodes.start[sequence-1].data.sequence.items, item))
1363− return 0;
1364−
1365− return 1;
1366−}
1367−
1368−/*
1369− * Append a pair of a key and a value to a mapping node.
1370− */
1371−
1372−YAML_DECLARE(int)
1373−yaml_document_append_mapping_pair(yaml_document_t *document,
1374− int mapping, int key, int value)
1375−{
1376− struct {
1377− yaml_error_type_t error;
1378− } context;
1379−
1380− yaml_node_pair_t pair;
1381−
1382− assert(document); /* Non-NULL document is required. */
1383− assert(mapping > 0
1384− && document->nodes.start + mapping <= document->nodes.top);
1385− /* Valid mapping id is required. */
1386− assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE);
1387− /* A mapping node is required. */
1388− assert(key > 0 && document->nodes.start + key <= document->nodes.top);
1389− /* Valid key id is required. */
1390− assert(value > 0 && document->nodes.start + value <= document->nodes.top);
1391− /* Valid value id is required. */
1392−
1393− pair.key = key;
1394− pair.value = value;
1395−
1396− if (!PUSH(&context,
1397− document->nodes.start[mapping-1].data.mapping.pairs, pair))
1398− return 0;
1399−
1400− return 1;
1401−}
1402−
1403−
c/helper.c → libyaml/c/helper.crenamed+58−23
@@ -13,10 +13,10 @@ int buffer_append(void *ext, unsigned char *str, size_t size)
1313{
1414 buffer_t *b = ext;
1515 int new_size, new_used;
16− char *tmp;
16+ unsigned char *tmp;
1717
1818 new_used = b->used + size;
19− for (new_size = b->size || 8; new_size < new_used; new_size *= 2);
19+ for (new_size = b->size ? b->size : 8; new_size < new_used; new_size *= 2);
2020
2121 if (new_size != b->size) {
2222 tmp = realloc(b->buff, new_size);
@@ -46,32 +46,22 @@ void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b)
4646 yaml_emitter_set_output(e, buffer_append, b);
4747}
4848
49−unsigned char const * get_parser_error_problem(yaml_parser_t *p)
49+char const * get_parser_error_problem(yaml_parser_t *p)
5050{
5151 return p->problem;
5252}
5353
54−unsigned char const * get_parser_error_context(yaml_parser_t *p)
54+char const * get_parser_error_context(yaml_parser_t *p)
5555{
5656 return p->context;
5757}
5858
59−unsigned int get_parser_error_index(yaml_parser_t *p)
59+const yaml_mark_t * get_parser_error_mark(yaml_parser_t *p)
6060{
61− return p->problem_mark.index;
61+ return &p->problem_mark;
6262}
6363
64−unsigned int get_parser_error_line(yaml_parser_t *p)
65−{
66− return p->problem_mark.line;
67−}
68−
69−unsigned int get_parser_error_column(yaml_parser_t *p)
70−{
71− return p->problem_mark.column;
72−}
73−
74−unsigned char const * get_emitter_error(yaml_emitter_t *e)
64+char const * get_emitter_error(yaml_emitter_t *e)
7565{
7666 return e->problem;
7767}
@@ -104,15 +94,10 @@ unsigned long get_scalar_length(yaml_event_t *e)
10494unsigned char * get_scalar_tag(yaml_event_t *e)
10595{
10696 unsigned char *s = e->data.scalar.tag;
107− if (!s) s = "";
97+ if (!s) s = (unsigned char *) "";
10898 return s;
10999}
110100
111−unsigned long get_scalar_tag_len(yaml_event_t *e)
112−{
113− return strlen(get_scalar_tag(e));
114−}
115−
116101int get_scalar_style(yaml_event_t *e)
117102{
118103 return e->data.scalar.style;
@@ -128,21 +113,71 @@ unsigned char * get_sequence_start_anchor(yaml_event_t *e)
128113 return e->data.sequence_start.anchor;
129114}
130115
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+
131128unsigned char * get_mapping_start_anchor(yaml_event_t *e)
132129{
133130 return e->data.mapping_start.anchor;
134131}
135132
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+
136145unsigned char * get_alias_anchor(yaml_event_t *e)
137146{
138147 return e->data.alias.anchor;
139148}
140149
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+
141175int yaml_parser_set_input_filename(yaml_parser_t *parser, const char *filename)
142176{
143177 FILE *in = fopen(filename, "r");
144178 if (!in) return 0;
145179 yaml_parser_set_input_file(parser, in);
180+ return 1;
146181}
147182
148183int fclose_helper(FILE *file)
libyaml/dumper.cdeleted−394
@@ -1,394 +0,0 @@
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−
libyaml/emitter.cdeleted−2329
@@ -1,2329 +0,0 @@
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_mapping(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;
1353− yaml_string_t prefix;
1354− size_t handle_length;
1355− size_t prefix_length;
1356−
1357− handle_length = strlen((char *)tag_directive.handle);
1358− prefix_length = strlen((char *)tag_directive.prefix);
1359− STRING_ASSIGN(handle, tag_directive.handle, handle_length);
1360− STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length);
1361−
1362− if (handle.start == handle.end) {
1363− return yaml_emitter_set_emitter_error(emitter,
1364− "tag handle must not be empty");
1365− }
1366−
1367− if (handle.start[0] != '!') {
1368− return yaml_emitter_set_emitter_error(emitter,
1369− "tag handle must start with '!'");
1370− }
1371−
1372− if (handle.end[-1] != '!') {
1373− return yaml_emitter_set_emitter_error(emitter,
1374− "tag handle must end with '!'");
1375− }
1376−
1377− handle.pointer ++;
1378−
1379− while (handle.pointer < handle.end-1) {
1380− if (!IS_ALPHA(handle)) {
1381− return yaml_emitter_set_emitter_error(emitter,
1382− "tag handle must contain alphanumerical characters only");
1383− }
1384− MOVE(handle);
1385− }
1386−
1387− if (prefix.start == prefix.end) {
1388− return yaml_emitter_set_emitter_error(emitter,
1389− "tag prefix must not be empty");
1390− }
1391−
1392− return 1;
1393−}
1394−
1395−/*
1396− * Check if an anchor is valid.
1397− */
1398−
1399−static int
1400−yaml_emitter_analyze_anchor(yaml_emitter_t *emitter,
1401− yaml_char_t *anchor, int alias)
1402−{
1403− size_t anchor_length;
1404− yaml_string_t string;
1405−
1406− anchor_length = strlen((char *)anchor);
1407− STRING_ASSIGN(string, anchor, anchor_length);
1408−
1409− if (string.start == string.end) {
1410− return yaml_emitter_set_emitter_error(emitter, alias ?
1411− "alias value must not be empty" :
1412− "anchor value must not be empty");
1413− }
1414−
1415− while (string.pointer != string.end) {
1416− if (!IS_ALPHA(string)) {
1417− return yaml_emitter_set_emitter_error(emitter, alias ?
1418− "alias value must contain alphanumerical characters only" :
1419− "anchor value must contain alphanumerical characters only");
1420− }
1421− MOVE(string);
1422− }
1423−
1424− emitter->anchor_data.anchor = string.start;
1425− emitter->anchor_data.anchor_length = string.end - string.start;
1426− emitter->anchor_data.alias = alias;
1427−
1428− return 1;
1429−}
1430−
1431−/*
1432− * Check if a tag is valid.
1433− */
1434−
1435−static int
1436−yaml_emitter_analyze_tag(yaml_emitter_t *emitter,
1437− yaml_char_t *tag)
1438−{
1439− size_t tag_length;
1440− yaml_string_t string;
1441− yaml_tag_directive_t *tag_directive;
1442−
1443− tag_length = strlen((char *)tag);
1444− STRING_ASSIGN(string, tag, tag_length);
1445−
1446− if (string.start == string.end) {
1447− return yaml_emitter_set_emitter_error(emitter,
1448− "tag value must not be empty");
1449− }
1450−
1451− for (tag_directive = emitter->tag_directives.start;
1452− tag_directive != emitter->tag_directives.top; tag_directive ++) {
1453− size_t prefix_length = strlen((char *)tag_directive->prefix);
1454− if (prefix_length < (size_t)(string.end - string.start)
1455− && strncmp((char *)tag_directive->prefix, (char *)string.start,
1456− prefix_length) == 0)
1457− {
1458− emitter->tag_data.handle = tag_directive->handle;
1459− emitter->tag_data.handle_length =
1460− strlen((char *)tag_directive->handle);
1461− emitter->tag_data.suffix = string.start + prefix_length;
1462− emitter->tag_data.suffix_length =
1463− (string.end - string.start) - prefix_length;
1464− return 1;
1465− }
1466− }
1467−
1468− emitter->tag_data.suffix = string.start;
1469− emitter->tag_data.suffix_length = string.end - string.start;
1470−
1471− return 1;
1472−}
1473−
1474−/*
1475− * Check if a scalar is valid.
1476− */
1477−
1478−static int
1479−yaml_emitter_analyze_scalar(yaml_emitter_t *emitter,
1480− yaml_char_t *value, size_t length)
1481−{
1482− yaml_string_t string;
1483−
1484− int block_indicators = 0;
1485− int flow_indicators = 0;
1486− int line_breaks = 0;
1487− int special_characters = 0;
1488−
1489− int leading_space = 0;
1490− int leading_break = 0;
1491− int trailing_space = 0;
1492− int trailing_break = 0;
1493− int break_space = 0;
1494− int space_break = 0;
1495−
1496− int preceeded_by_whitespace = 0;
1497− int followed_by_whitespace = 0;
1498− int previous_space = 0;
1499− int previous_break = 0;
1500−
1501− STRING_ASSIGN(string, value, length);
1502−
1503− emitter->scalar_data.value = value;
1504− emitter->scalar_data.length = length;
1505−
1506− if (string.start == string.end)
1507− {
1508− emitter->scalar_data.multiline = 0;
1509− emitter->scalar_data.flow_plain_allowed = 0;
1510− emitter->scalar_data.block_plain_allowed = 1;
1511− emitter->scalar_data.single_quoted_allowed = 1;
1512− emitter->scalar_data.block_allowed = 0;
1513−
1514− return 1;
1515− }
1516−
1517− if ((CHECK_AT(string, '-', 0)
1518− && CHECK_AT(string, '-', 1)
1519− && CHECK_AT(string, '-', 2))
1520− || (CHECK_AT(string, '.', 0)
1521− && CHECK_AT(string, '.', 1)
1522− && CHECK_AT(string, '.', 2))) {
1523− block_indicators = 1;
1524− flow_indicators = 1;
1525− }
1526−
1527− preceeded_by_whitespace = 1;
1528− followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
1529−
1530− while (string.pointer != string.end)
1531− {
1532− if (string.start == string.pointer)
1533− {
1534− if (CHECK(string, '#') || CHECK(string, ',')
1535− || CHECK(string, '[') || CHECK(string, ']')
1536− || CHECK(string, '{') || CHECK(string, '}')
1537− || CHECK(string, '&') || CHECK(string, '*')
1538− || CHECK(string, '!') || CHECK(string, '|')
1539− || CHECK(string, '>') || CHECK(string, '\'')
1540− || CHECK(string, '"') || CHECK(string, '%')
1541− || CHECK(string, '@') || CHECK(string, '`')) {
1542− flow_indicators = 1;
1543− block_indicators = 1;
1544− }
1545−
1546− if (CHECK(string, '?') || CHECK(string, ':')) {
1547− flow_indicators = 1;
1548− if (followed_by_whitespace) {
1549− block_indicators = 1;
1550− }
1551− }
1552−
1553− if (CHECK(string, '-') && followed_by_whitespace) {
1554− flow_indicators = 1;
1555− block_indicators = 1;
1556− }
1557− }
1558− else
1559− {
1560− if (CHECK(string, ',') || CHECK(string, '?')
1561− || CHECK(string, '[') || CHECK(string, ']')
1562− || CHECK(string, '{') || CHECK(string, '}')) {
1563− flow_indicators = 1;
1564− }
1565−
1566− if (CHECK(string, ':')) {
1567− flow_indicators = 1;
1568− if (followed_by_whitespace) {
1569− block_indicators = 1;
1570− }
1571− }
1572−
1573− if (CHECK(string, '#') && preceeded_by_whitespace) {
1574− flow_indicators = 1;
1575− block_indicators = 1;
1576− }
1577− }
1578−
1579− if (!IS_PRINTABLE(string)
1580− || (!IS_ASCII(string) && !emitter->unicode)) {
1581− special_characters = 1;
1582− }
1583−
1584− if (IS_BREAK(string)) {
1585− line_breaks = 1;
1586− }
1587−
1588− if (IS_SPACE(string))
1589− {
1590− if (string.start == string.pointer) {
1591− leading_space = 1;
1592− }
1593− if (string.pointer+WIDTH(string) == string.end) {
1594− trailing_space = 1;
1595− }
1596− if (previous_break) {
1597− break_space = 1;
1598− }
1599− previous_space = 1;
1600− previous_break = 0;
1601− }
1602− else if (IS_BREAK(string))
1603− {
1604− if (string.start == string.pointer) {
1605− leading_break = 1;
1606− }
1607− if (string.pointer+WIDTH(string) == string.end) {
1608− trailing_break = 1;
1609− }
1610− if (previous_space) {
1611− space_break = 1;
1612− }
1613− previous_space = 0;
1614− previous_break = 1;
1615− }
1616− else
1617− {
1618− previous_space = 0;
1619− previous_break = 0;
1620− }
1621−
1622− preceeded_by_whitespace = IS_BLANKZ(string);
1623− MOVE(string);
1624− if (string.pointer != string.end) {
1625− followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string));
1626− }
1627− }
1628−
1629− emitter->scalar_data.multiline = line_breaks;
1630−
1631− emitter->scalar_data.flow_plain_allowed = 1;
1632− emitter->scalar_data.block_plain_allowed = 1;
1633− emitter->scalar_data.single_quoted_allowed = 1;
1634− emitter->scalar_data.block_allowed = 1;
1635−
1636− if (leading_space || leading_break || trailing_space || trailing_break) {
1637− emitter->scalar_data.flow_plain_allowed = 0;
1638− emitter->scalar_data.block_plain_allowed = 0;
1639− }
1640−
1641− if (trailing_space) {
1642− emitter->scalar_data.block_allowed = 0;
1643− }
1644−
1645− if (break_space) {
1646− emitter->scalar_data.flow_plain_allowed = 0;
1647− emitter->scalar_data.block_plain_allowed = 0;
1648− emitter->scalar_data.single_quoted_allowed = 0;
1649− }
1650−
1651− if (space_break || special_characters) {
1652− emitter->scalar_data.flow_plain_allowed = 0;
1653− emitter->scalar_data.block_plain_allowed = 0;
1654− emitter->scalar_data.single_quoted_allowed = 0;
1655− emitter->scalar_data.block_allowed = 0;
1656− }
1657−
1658− if (line_breaks) {
1659− emitter->scalar_data.flow_plain_allowed = 0;
1660− emitter->scalar_data.block_plain_allowed = 0;
1661− }
1662−
1663− if (flow_indicators) {
1664− emitter->scalar_data.flow_plain_allowed = 0;
1665− }
1666−
1667− if (block_indicators) {
1668− emitter->scalar_data.block_plain_allowed = 0;
1669− }
1670−
1671− return 1;
1672−}
1673−
1674−/*
1675− * Check if the event data is valid.
1676− */
1677−
1678−static int
1679−yaml_emitter_analyze_event(yaml_emitter_t *emitter,
1680− yaml_event_t *event)
1681−{
1682− emitter->anchor_data.anchor = NULL;
1683− emitter->anchor_data.anchor_length = 0;
1684− emitter->tag_data.handle = NULL;
1685− emitter->tag_data.handle_length = 0;
1686− emitter->tag_data.suffix = NULL;
1687− emitter->tag_data.suffix_length = 0;
1688− emitter->scalar_data.value = NULL;
1689− emitter->scalar_data.length = 0;
1690−
1691− switch (event->type)
1692− {
1693− case YAML_ALIAS_EVENT:
1694− if (!yaml_emitter_analyze_anchor(emitter,
1695− event->data.alias.anchor, 1))
1696− return 0;
1697− return 1;
1698−
1699− case YAML_SCALAR_EVENT:
1700− if (event->data.scalar.anchor) {
1701− if (!yaml_emitter_analyze_anchor(emitter,
1702− event->data.scalar.anchor, 0))
1703− return 0;
1704− }
1705− if (event->data.scalar.tag && (emitter->canonical ||
1706− (!event->data.scalar.plain_implicit
1707− && !event->data.scalar.quoted_implicit))) {
1708− if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag))
1709− return 0;
1710− }
1711− if (!yaml_emitter_analyze_scalar(emitter,
1712− event->data.scalar.value, event->data.scalar.length))
1713− return 0;
1714− return 1;
1715−
1716− case YAML_SEQUENCE_START_EVENT:
1717− if (event->data.sequence_start.anchor) {
1718− if (!yaml_emitter_analyze_anchor(emitter,
1719− event->data.sequence_start.anchor, 0))
1720− return 0;
1721− }
1722− if (event->data.sequence_start.tag && (emitter->canonical ||
1723− !event->data.sequence_start.implicit)) {
1724− if (!yaml_emitter_analyze_tag(emitter,
1725− event->data.sequence_start.tag))
1726− return 0;
1727− }
1728− return 1;
1729−
1730− case YAML_MAPPING_START_EVENT:
1731− if (event->data.mapping_start.anchor) {
1732− if (!yaml_emitter_analyze_anchor(emitter,
1733− event->data.mapping_start.anchor, 0))
1734− return 0;
1735− }
1736− if (event->data.mapping_start.tag && (emitter->canonical ||
1737− !event->data.mapping_start.implicit)) {
1738− if (!yaml_emitter_analyze_tag(emitter,
1739− event->data.mapping_start.tag))
1740− return 0;
1741− }
1742− return 1;
1743−
1744− default:
1745− return 1;
1746− }
1747−}
1748−
1749−/*
1750− * Write the BOM character.
1751− */
1752−
1753−static int
1754−yaml_emitter_write_bom(yaml_emitter_t *emitter)
1755−{
1756− if (!FLUSH(emitter)) return 0;
1757−
1758− *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF';
1759− *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB';
1760− *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF';
1761−
1762− return 1;
1763−}
1764−
1765−static int
1766−yaml_emitter_write_indent(yaml_emitter_t *emitter)
1767−{
1768− int indent = (emitter->indent >= 0) ? emitter->indent : 0;
1769−
1770− if (!emitter->indention || emitter->column > indent
1771− || (emitter->column == indent && !emitter->whitespace)) {
1772− if (!PUT_BREAK(emitter)) return 0;
1773− }
1774−
1775− while (emitter->column < indent) {
1776− if (!PUT(emitter, ' ')) return 0;
1777− }
1778−
1779− emitter->whitespace = 1;
1780− emitter->indention = 1;
1781−
1782− return 1;
1783−}
1784−
1785−static int
1786−yaml_emitter_write_indicator(yaml_emitter_t *emitter,
1787− char *indicator, int need_whitespace,
1788− int is_whitespace, int is_indention)
1789−{
1790− size_t indicator_length;
1791− yaml_string_t string;
1792−
1793− indicator_length = strlen(indicator);
1794− STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length);
1795−
1796− if (need_whitespace && !emitter->whitespace) {
1797− if (!PUT(emitter, ' ')) return 0;
1798− }
1799−
1800− while (string.pointer != string.end) {
1801− if (!WRITE(emitter, string)) return 0;
1802− }
1803−
1804− emitter->whitespace = is_whitespace;
1805− emitter->indention = (emitter->indention && is_indention);
1806− emitter->open_ended = 0;
1807−
1808− return 1;
1809−}
1810−
1811−static int
1812−yaml_emitter_write_anchor(yaml_emitter_t *emitter,
1813− yaml_char_t *value, size_t length)
1814−{
1815− yaml_string_t string;
1816− STRING_ASSIGN(string, value, length);
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_handle(yaml_emitter_t *emitter,
1830− yaml_char_t *value, size_t length)
1831−{
1832− yaml_string_t string;
1833− STRING_ASSIGN(string, value, length);
1834−
1835− if (!emitter->whitespace) {
1836− if (!PUT(emitter, ' ')) return 0;
1837− }
1838−
1839− while (string.pointer != string.end) {
1840− if (!WRITE(emitter, string)) return 0;
1841− }
1842−
1843− emitter->whitespace = 0;
1844− emitter->indention = 0;
1845−
1846− return 1;
1847−}
1848−
1849−static int
1850−yaml_emitter_write_tag_content(yaml_emitter_t *emitter,
1851− yaml_char_t *value, size_t length,
1852− int need_whitespace)
1853−{
1854− yaml_string_t string;
1855− STRING_ASSIGN(string, value, length);
1856−
1857− if (need_whitespace && !emitter->whitespace) {
1858− if (!PUT(emitter, ' ')) return 0;
1859− }
1860−
1861− while (string.pointer != string.end) {
1862− if (IS_ALPHA(string)
1863− || CHECK(string, ';') || CHECK(string, '/')
1864− || CHECK(string, '?') || CHECK(string, ':')
1865− || CHECK(string, '@') || CHECK(string, '&')
1866− || CHECK(string, '=') || CHECK(string, '+')
1867− || CHECK(string, '$') || CHECK(string, ',')
1868− || CHECK(string, '_') || CHECK(string, '.')
1869− || CHECK(string, '~') || CHECK(string, '*')
1870− || CHECK(string, '\'') || CHECK(string, '(')
1871− || CHECK(string, ')') || CHECK(string, '[')
1872− || CHECK(string, ']')) {
1873− if (!WRITE(emitter, string)) return 0;
1874− }
1875− else {
1876− int width = WIDTH(string);
1877− unsigned int value;
1878− while (width --) {
1879− value = *(string.pointer++);
1880− if (!PUT(emitter, '%')) return 0;
1881− if (!PUT(emitter, (value >> 4)
1882− + ((value >> 4) < 10 ? '0' : 'A' - 10)))
1883− return 0;
1884− if (!PUT(emitter, (value & 0x0F)
1885− + ((value & 0x0F) < 10 ? '0' : 'A' - 10)))
1886− return 0;
1887− }
1888− }
1889− }
1890−
1891− emitter->whitespace = 0;
1892− emitter->indention = 0;
1893−
1894− return 1;
1895−}
1896−
1897−static int
1898−yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
1899− yaml_char_t *value, size_t length, int allow_breaks)
1900−{
1901− yaml_string_t string;
1902− int spaces = 0;
1903− int breaks = 0;
1904−
1905− STRING_ASSIGN(string, value, length);
1906−
1907− if (!emitter->whitespace) {
1908− if (!PUT(emitter, ' ')) return 0;
1909− }
1910−
1911− while (string.pointer != string.end)
1912− {
1913− if (IS_SPACE(string))
1914− {
1915− if (allow_breaks && !spaces
1916− && emitter->column > emitter->best_width
1917− && !IS_SPACE_AT(string, 1)) {
1918− if (!yaml_emitter_write_indent(emitter)) return 0;
1919− MOVE(string);
1920− }
1921− else {
1922− if (!WRITE(emitter, string)) return 0;
1923− }
1924− spaces = 1;
1925− }
1926− else if (IS_BREAK(string))
1927− {
1928− if (!breaks && CHECK(string, '\n')) {
1929− if (!PUT_BREAK(emitter)) return 0;
1930− }
1931− if (!WRITE_BREAK(emitter, string)) return 0;
1932− emitter->indention = 1;
1933− breaks = 1;
1934− }
1935− else
1936− {
1937− if (breaks) {
1938− if (!yaml_emitter_write_indent(emitter)) return 0;
1939− }
1940− if (!WRITE(emitter, string)) return 0;
1941− emitter->indention = 0;
1942− spaces = 0;
1943− breaks = 0;
1944− }
1945− }
1946−
1947− emitter->whitespace = 0;
1948− emitter->indention = 0;
1949− if (emitter->root_context)
1950− {
1951− emitter->open_ended = 1;
1952− }
1953−
1954− return 1;
1955−}
1956−
1957−static int
1958−yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
1959− yaml_char_t *value, size_t length, int allow_breaks)
1960−{
1961− yaml_string_t string;
1962− int spaces = 0;
1963− int breaks = 0;
1964−
1965− STRING_ASSIGN(string, value, length);
1966−
1967− if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0))
1968− return 0;
1969−
1970− while (string.pointer != string.end)
1971− {
1972− if (IS_SPACE(string))
1973− {
1974− if (allow_breaks && !spaces
1975− && emitter->column > emitter->best_width
1976− && string.pointer != string.start
1977− && string.pointer != string.end - 1
1978− && !IS_SPACE_AT(string, 1)) {
1979− if (!yaml_emitter_write_indent(emitter)) return 0;
1980− MOVE(string);
1981− }
1982− else {
1983− if (!WRITE(emitter, string)) return 0;
1984− }
1985− spaces = 1;
1986− }
1987− else if (IS_BREAK(string))
1988− {
1989− if (!breaks && CHECK(string, '\n')) {
1990− if (!PUT_BREAK(emitter)) return 0;
1991− }
1992− if (!WRITE_BREAK(emitter, string)) return 0;
1993− emitter->indention = 1;
1994− breaks = 1;
1995− }
1996− else
1997− {
1998− if (breaks) {
1999− if (!yaml_emitter_write_indent(emitter)) return 0;
2000− }
2001− if (CHECK(string, '\'')) {
2002− if (!PUT(emitter, '\'')) return 0;
2003− }
2004− if (!WRITE(emitter, string)) return 0;
2005− emitter->indention = 0;
2006− spaces = 0;
2007− breaks = 0;
2008− }
2009− }
2010−
2011− if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
2012− return 0;
2013−
2014− emitter->whitespace = 0;
2015− emitter->indention = 0;
2016−
2017− return 1;
2018−}
2019−
2020−static int
2021−yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter,
2022− yaml_char_t *value, size_t length, int allow_breaks)
2023−{
2024− yaml_string_t string;
2025− int spaces = 0;
2026−
2027− STRING_ASSIGN(string, value, length);
2028−
2029− if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0))
2030− return 0;
2031−
2032− while (string.pointer != string.end)
2033− {
2034− if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string))
2035− || IS_BOM(string) || IS_BREAK(string)
2036− || CHECK(string, '"') || CHECK(string, '\\'))
2037− {
2038− unsigned char octet;
2039− unsigned int width;
2040− unsigned int value;
2041− int k;
2042−
2043− octet = string.pointer[0];
2044− width = (octet & 0x80) == 0x00 ? 1 :
2045− (octet & 0xE0) == 0xC0 ? 2 :
2046− (octet & 0xF0) == 0xE0 ? 3 :
2047− (octet & 0xF8) == 0xF0 ? 4 : 0;
2048− value = (octet & 0x80) == 0x00 ? octet & 0x7F :
2049− (octet & 0xE0) == 0xC0 ? octet & 0x1F :
2050− (octet & 0xF0) == 0xE0 ? octet & 0x0F :
2051− (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
2052− for (k = 1; k < (int)width; k ++) {
2053− octet = string.pointer[k];
2054− value = (value << 6) + (octet & 0x3F);
2055− }
2056− string.pointer += width;
2057−
2058− if (!PUT(emitter, '\\')) return 0;
2059−
2060− switch (value)
2061− {
2062− case 0x00:
2063− if (!PUT(emitter, '0')) return 0;
2064− break;
2065−
2066− case 0x07:
2067− if (!PUT(emitter, 'a')) return 0;
2068− break;
2069−
2070− case 0x08:
2071− if (!PUT(emitter, 'b')) return 0;
2072− break;
2073−
2074− case 0x09:
2075− if (!PUT(emitter, 't')) return 0;
2076− break;
2077−
2078− case 0x0A:
2079− if (!PUT(emitter, 'n')) return 0;
2080− break;
2081−
2082− case 0x0B:
2083− if (!PUT(emitter, 'v')) return 0;
2084− break;
2085−
2086− case 0x0C:
2087− if (!PUT(emitter, 'f')) return 0;
2088− break;
2089−
2090− case 0x0D:
2091− if (!PUT(emitter, 'r')) return 0;
2092− break;
2093−
2094− case 0x1B:
2095− if (!PUT(emitter, 'e')) return 0;
2096− break;
2097−
2098− case 0x22:
2099− if (!PUT(emitter, '\"')) return 0;
2100− break;
2101−
2102− case 0x5C:
2103− if (!PUT(emitter, '\\')) return 0;
2104− break;
2105−
2106− case 0x85:
2107− if (!PUT(emitter, 'N')) return 0;
2108− break;
2109−
2110− case 0xA0:
2111− if (!PUT(emitter, '_')) return 0;
2112− break;
2113−
2114− case 0x2028:
2115− if (!PUT(emitter, 'L')) return 0;
2116− break;
2117−
2118− case 0x2029:
2119− if (!PUT(emitter, 'P')) return 0;
2120− break;
2121−
2122− default:
2123− if (value <= 0xFF) {
2124− if (!PUT(emitter, 'x')) return 0;
2125− width = 2;
2126− }
2127− else if (value <= 0xFFFF) {
2128− if (!PUT(emitter, 'u')) return 0;
2129− width = 4;
2130− }
2131− else {
2132− if (!PUT(emitter, 'U')) return 0;
2133− width = 8;
2134− }
2135− for (k = (width-1)*4; k >= 0; k -= 4) {
2136− int digit = (value >> k) & 0x0F;
2137− if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10)))
2138− return 0;
2139− }
2140− }
2141− spaces = 0;
2142− }
2143− else if (IS_SPACE(string))
2144− {
2145− if (allow_breaks && !spaces
2146− && emitter->column > emitter->best_width
2147− && string.pointer != string.start
2148− && string.pointer != string.end - 1) {
2149− if (!yaml_emitter_write_indent(emitter)) return 0;
2150− if (IS_SPACE_AT(string, 1)) {
2151− if (!PUT(emitter, '\\')) return 0;
2152− }
2153− MOVE(string);
2154− }
2155− else {
2156− if (!WRITE(emitter, string)) return 0;
2157− }
2158− spaces = 1;
2159− }
2160− else
2161− {
2162− if (!WRITE(emitter, string)) return 0;
2163− spaces = 0;
2164− }
2165− }
2166−
2167− if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0))
2168− return 0;
2169−
2170− emitter->whitespace = 0;
2171− emitter->indention = 0;
2172−
2173− return 1;
2174−}
2175−
2176−static int
2177−yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
2178− yaml_string_t string)
2179−{
2180− char indent_hint[2];
2181− char *chomp_hint = NULL;
2182−
2183− if (IS_SPACE(string) || IS_BREAK(string))
2184− {
2185− indent_hint[0] = '0' + (char)emitter->best_indent;
2186− indent_hint[1] = '\0';
2187− if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0))
2188− return 0;
2189− }
2190−
2191− emitter->open_ended = 0;
2192−
2193− string.pointer = string.end;
2194− if (string.start == string.pointer)
2195− {
2196− chomp_hint = "-";
2197− }
2198− else
2199− {
2200− do {
2201− string.pointer --;
2202− } while ((*string.pointer & 0xC0) == 0x80);
2203− if (!IS_BREAK(string))
2204− {
2205− chomp_hint = "-";
2206− }
2207− else if (string.start == string.pointer)
2208− {
2209− chomp_hint = "+";
2210− emitter->open_ended = 1;
2211− }
2212− else
2213− {
2214− do {
2215− string.pointer --;
2216− } while ((*string.pointer & 0xC0) == 0x80);
2217− if (IS_BREAK(string))
2218− {
2219− chomp_hint = "+";
2220− emitter->open_ended = 1;
2221− }
2222− }
2223− }
2224−
2225− if (chomp_hint)
2226− {
2227− if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0))
2228− return 0;
2229− }
2230−
2231− return 1;
2232−}
2233−
2234−static int
2235−yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter,
2236− yaml_char_t *value, size_t length)
2237−{
2238− yaml_string_t string;
2239− int breaks = 1;
2240−
2241− STRING_ASSIGN(string, value, length);
2242−
2243− if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0))
2244− return 0;
2245− if (!yaml_emitter_write_block_scalar_hints(emitter, string))
2246− return 0;
2247− if (!PUT_BREAK(emitter)) return 0;
2248− emitter->indention = 1;
2249− emitter->whitespace = 1;
2250−
2251− while (string.pointer != string.end)
2252− {
2253− if (IS_BREAK(string))
2254− {
2255− if (!WRITE_BREAK(emitter, string)) return 0;
2256− emitter->indention = 1;
2257− breaks = 1;
2258− }
2259− else
2260− {
2261− if (breaks) {
2262− if (!yaml_emitter_write_indent(emitter)) return 0;
2263− }
2264− if (!WRITE(emitter, string)) return 0;
2265− emitter->indention = 0;
2266− breaks = 0;
2267− }
2268− }
2269−
2270− return 1;
2271−}
2272−
2273−static int
2274−yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter,
2275− yaml_char_t *value, size_t length)
2276−{
2277− yaml_string_t string;
2278− int breaks = 1;
2279− int leading_spaces = 1;
2280−
2281− STRING_ASSIGN(string, value, length);
2282−
2283− if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0))
2284− return 0;
2285− if (!yaml_emitter_write_block_scalar_hints(emitter, string))
2286− return 0;
2287− if (!PUT_BREAK(emitter)) return 0;
2288− emitter->indention = 1;
2289− emitter->whitespace = 1;
2290−
2291− while (string.pointer != string.end)
2292− {
2293− if (IS_BREAK(string))
2294− {
2295− if (!breaks && !leading_spaces && CHECK(string, '\n')) {
2296− int k = 0;
2297− while (IS_BREAK_AT(string, k)) {
2298− k += WIDTH_AT(string, k);
2299− }
2300− if (!IS_BLANKZ_AT(string, k)) {
2301− if (!PUT_BREAK(emitter)) return 0;
2302− }
2303− }
2304− if (!WRITE_BREAK(emitter, string)) return 0;
2305− emitter->indention = 1;
2306− breaks = 1;
2307− }
2308− else
2309− {
2310− if (breaks) {
2311− if (!yaml_emitter_write_indent(emitter)) return 0;
2312− leading_spaces = IS_BLANK(string);
2313− }
2314− if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1)
2315− && emitter->column > emitter->best_width) {
2316− if (!yaml_emitter_write_indent(emitter)) return 0;
2317− MOVE(string);
2318− }
2319− else {
2320− if (!WRITE(emitter, string)) return 0;
2321− }
2322− emitter->indention = 0;
2323− breaks = 0;
2324− }
2325− }
2326−
2327− return 1;
2328−}
2329−
c/helper.h → libyaml/include/helper.hrenamed+7−4
@@ -14,11 +14,11 @@ unsigned int get_buffer_used(buffer_t *b);
1414
1515void my_emitter_set_output(yaml_emitter_t *e, buffer_t *b);
1616
17−unsigned char const * get_parser_error_problem(yaml_parser_t *p);
18−unsigned char const * get_parser_error_context(yaml_parser_t *p);
17+char const * get_parser_error_problem(yaml_parser_t *p);
18+char const * get_parser_error_context(yaml_parser_t *p);
1919unsigned int get_parser_error_offset(yaml_parser_t *p);
2020
21−unsigned char const * get_emitter_error(yaml_emitter_t *e);
21+char const * get_emitter_error(yaml_emitter_t *e);
2222
2323int simple_document_start(yaml_event_t *e);
2424
@@ -28,9 +28,12 @@ unsigned char * get_scalar_value(yaml_event_t *e);
2828unsigned long get_scalar_length(yaml_event_t *e);
2929
3030unsigned char * get_scalar_tag(yaml_event_t *e);
31−unsigned long get_scalar_tag_len(yaml_event_t *e);
31+unsigned char * get_sequence_start_tag(yaml_event_t *e);
32+unsigned char * get_mapping_start_tag(yaml_event_t *e);
3233
3334int 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);
3437
3538unsigned char * get_scalar_anchor(yaml_event_t *e);
3639unsigned char * get_sequence_start_anchor(yaml_event_t *e);
libyaml/libyaml.cabalnew file+68
@@ -0,0 +1,68 @@
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/loader.cdeleted−444
@@ -1,444 +0,0 @@
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;
229− yaml_alias_data_t *alias_data;
230−
231− if (!anchor) return 1;
232−
233− data.anchor = anchor;
234− data.index = index;
235− data.mark = parser->document->nodes.start[index-1].start_mark;
236−
237− for (alias_data = parser->aliases.start;
238− alias_data != parser->aliases.top; alias_data ++) {
239− if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
240− yaml_free(anchor);
241− return yaml_parser_set_composer_error_context(parser,
242− "found duplicate anchor; first occurence",
243− alias_data->mark, "second occurence", data.mark);
244− }
245− }
246−
247− if (!PUSH(parser, parser->aliases, data)) {
248− yaml_free(anchor);
249− return 0;
250− }
251−
252− return 1;
253−}
254−
255−/*
256− * Compose a node corresponding to an alias.
257− */
258−
259−static int
260−yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
261−{
262− yaml_char_t *anchor = first_event->data.alias.anchor;
263− yaml_alias_data_t *alias_data;
264−
265− for (alias_data = parser->aliases.start;
266− alias_data != parser->aliases.top; alias_data ++) {
267− if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
268− yaml_free(anchor);
269− return alias_data->index;
270− }
271− }
272−
273− yaml_free(anchor);
274− return yaml_parser_set_composer_error(parser, "found undefined alias",
275− first_event->start_mark);
276−}
277−
278−/*
279− * Compose a scalar node.
280− */
281−
282−static int
283−yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
284−{
285− yaml_node_t node;
286− int index;
287− yaml_char_t *tag = first_event->data.scalar.tag;
288−
289− if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
290−
291− if (!tag || strcmp((char *)tag, "!") == 0) {
292− yaml_free(tag);
293− tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG);
294− if (!tag) goto error;
295− }
296−
297− SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
298− first_event->data.scalar.length, first_event->data.scalar.style,
299− first_event->start_mark, first_event->end_mark);
300−
301− if (!PUSH(parser, parser->document->nodes, node)) goto error;
302−
303− index = parser->document->nodes.top - parser->document->nodes.start;
304−
305− if (!yaml_parser_register_anchor(parser, index,
306− first_event->data.scalar.anchor)) return 0;
307−
308− return index;
309−
310−error:
311− yaml_free(tag);
312− yaml_free(first_event->data.scalar.anchor);
313− yaml_free(first_event->data.scalar.value);
314− return 0;
315−}
316−
317−/*
318− * Compose a sequence node.
319− */
320−
321−static int
322−yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
323−{
324− yaml_event_t event;
325− yaml_node_t node;
326− struct {
327− yaml_node_item_t *start;
328− yaml_node_item_t *end;
329− yaml_node_item_t *top;
330− } items = { NULL, NULL, NULL };
331− int index, item_index;
332− yaml_char_t *tag = first_event->data.sequence_start.tag;
333−
334− if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
335−
336− if (!tag || strcmp((char *)tag, "!") == 0) {
337− yaml_free(tag);
338− tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG);
339− if (!tag) goto error;
340− }
341−
342− if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;
343−
344− SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
345− first_event->data.sequence_start.style,
346− first_event->start_mark, first_event->end_mark);
347−
348− if (!PUSH(parser, parser->document->nodes, node)) goto error;
349−
350− index = parser->document->nodes.top - parser->document->nodes.start;
351−
352− if (!yaml_parser_register_anchor(parser, index,
353− first_event->data.sequence_start.anchor)) return 0;
354−
355− if (!yaml_parser_parse(parser, &event)) return 0;
356−
357− while (event.type != YAML_SEQUENCE_END_EVENT) {
358− if (!STACK_LIMIT(parser,
359− parser->document->nodes.start[index-1].data.sequence.items,
360− INT_MAX-1)) return 0;
361− item_index = yaml_parser_load_node(parser, &event);
362− if (!item_index) return 0;
363− if (!PUSH(parser,
364− parser->document->nodes.start[index-1].data.sequence.items,
365− item_index)) return 0;
366− if (!yaml_parser_parse(parser, &event)) return 0;
367− }
368−
369− parser->document->nodes.start[index-1].end_mark = event.end_mark;
370−
371− return index;
372−
373−error:
374− yaml_free(tag);
375− yaml_free(first_event->data.sequence_start.anchor);
376− return 0;
377−}
378−
379−/*
380− * Compose a mapping node.
381− */
382−
383−static int
384−yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
385−{
386− yaml_event_t event;
387− yaml_node_t node;
388− struct {
389− yaml_node_pair_t *start;
390− yaml_node_pair_t *end;
391− yaml_node_pair_t *top;
392− } pairs = { NULL, NULL, NULL };
393− int index;
394− yaml_node_pair_t pair;
395− yaml_char_t *tag = first_event->data.mapping_start.tag;
396−
397− if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
398−
399− if (!tag || strcmp((char *)tag, "!") == 0) {
400− yaml_free(tag);
401− tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG);
402− if (!tag) goto error;
403− }
404−
405− if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;
406−
407− MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
408− first_event->data.mapping_start.style,
409− first_event->start_mark, first_event->end_mark);
410−
411− if (!PUSH(parser, parser->document->nodes, node)) goto error;
412−
413− index = parser->document->nodes.top - parser->document->nodes.start;
414−
415− if (!yaml_parser_register_anchor(parser, index,
416− first_event->data.mapping_start.anchor)) return 0;
417−
418− if (!yaml_parser_parse(parser, &event)) return 0;
419−
420− while (event.type != YAML_MAPPING_END_EVENT) {
421− if (!STACK_LIMIT(parser,
422− parser->document->nodes.start[index-1].data.mapping.pairs,
423− INT_MAX-1)) return 0;
424− pair.key = yaml_parser_load_node(parser, &event);
425− if (!pair.key) return 0;
426− if (!yaml_parser_parse(parser, &event)) return 0;
427− pair.value = yaml_parser_load_node(parser, &event);
428− if (!pair.value) return 0;
429− if (!PUSH(parser,
430− parser->document->nodes.start[index-1].data.mapping.pairs,
431− pair)) return 0;
432− if (!yaml_parser_parse(parser, &event)) return 0;
433− }
434−
435− parser->document->nodes.start[index-1].end_mark = event.end_mark;
436−
437− return index;
438−
439−error:
440− yaml_free(tag);
441− yaml_free(first_event->data.mapping_start.anchor);
442− return 0;
443−}
444−
libyaml/package.yamlnew file+53
@@ -0,0 +1,53 @@
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/parser.cdeleted−1374
@@ -1,1374 +0,0 @@
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− value.handle = token->data.tag_directive.handle;
1285− value.prefix = 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−
libyaml/reader.cdeleted−469
@@ -1,469 +0,0 @@
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− int first = 1;
145−
146− assert(parser->read_handler); /* Read handler must be set. */
147−
148− /* If the EOF flag is set and the raw buffer is empty, do nothing. */
149−
150− if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
151− return 1;
152−
153− /* Return if the buffer contains enough characters. */
154−
155− if (parser->unread >= length)
156− return 1;
157−
158− /* Determine the input encoding if it is not known yet. */
159−
160− if (!parser->encoding) {
161− if (!yaml_parser_determine_encoding(parser))
162− return 0;
163− }
164−
165− /* Move the unread characters to the beginning of the buffer. */
166−
167− if (parser->buffer.start < parser->buffer.pointer
168− && parser->buffer.pointer < parser->buffer.last) {
169− size_t size = parser->buffer.last - parser->buffer.pointer;
170− memmove(parser->buffer.start, parser->buffer.pointer, size);
171− parser->buffer.pointer = parser->buffer.start;
172− parser->buffer.last = parser->buffer.start + size;
173− }
174− else if (parser->buffer.pointer == parser->buffer.last) {
175− parser->buffer.pointer = parser->buffer.start;
176− parser->buffer.last = parser->buffer.start;
177− }
178−
179− /* Fill the buffer until it has enough characters. */
180−
181− while (parser->unread < length)
182− {
183− /* Fill the raw buffer if necessary. */
184−
185− if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) {
186− if (!yaml_parser_update_raw_buffer(parser)) return 0;
187− }
188− first = 0;
189−
190− /* Decode the raw buffer. */
191−
192− while (parser->raw_buffer.pointer != parser->raw_buffer.last)
193− {
194− unsigned int value = 0, value2 = 0;
195− int incomplete = 0;
196− unsigned char octet;
197− unsigned int width = 0;
198− int low, high;
199− size_t k;
200− size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
201−
202− /* Decode the next character. */
203−
204− switch (parser->encoding)
205− {
206− case YAML_UTF8_ENCODING:
207−
208− /*
209− * Decode a UTF-8 character. Check RFC 3629
210− * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
211− *
212− * The following table (taken from the RFC) is used for
213− * decoding.
214− *
215− * Char. number range | UTF-8 octet sequence
216− * (hexadecimal) | (binary)
217− * --------------------+------------------------------------
218− * 0000 0000-0000 007F | 0xxxxxxx
219− * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
220− * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
221− * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
222− *
223− * Additionally, the characters in the range 0xD800-0xDFFF
224− * are prohibited as they are reserved for use with UTF-16
225− * surrogate pairs.
226− */
227−
228− /* Determine the length of the UTF-8 sequence. */
229−
230− octet = parser->raw_buffer.pointer[0];
231− width = (octet & 0x80) == 0x00 ? 1 :
232− (octet & 0xE0) == 0xC0 ? 2 :
233− (octet & 0xF0) == 0xE0 ? 3 :
234− (octet & 0xF8) == 0xF0 ? 4 : 0;
235−
236− /* Check if the leading octet is valid. */
237−
238− if (!width)
239− return yaml_parser_set_reader_error(parser,
240− "invalid leading UTF-8 octet",
241− parser->offset, octet);
242−
243− /* Check if the raw buffer contains an incomplete character. */
244−
245− if (width > raw_unread) {
246− if (parser->eof) {
247− return yaml_parser_set_reader_error(parser,
248− "incomplete UTF-8 octet sequence",
249− parser->offset, -1);
250− }
251− incomplete = 1;
252− break;
253− }
254−
255− /* Decode the leading octet. */
256−
257− value = (octet & 0x80) == 0x00 ? octet & 0x7F :
258− (octet & 0xE0) == 0xC0 ? octet & 0x1F :
259− (octet & 0xF0) == 0xE0 ? octet & 0x0F :
260− (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
261−
262− /* Check and decode the trailing octets. */
263−
264− for (k = 1; k < width; k ++)
265− {
266− octet = parser->raw_buffer.pointer[k];
267−
268− /* Check if the octet is valid. */
269−
270− if ((octet & 0xC0) != 0x80)
271− return yaml_parser_set_reader_error(parser,
272− "invalid trailing UTF-8 octet",
273− parser->offset+k, octet);
274−
275− /* Decode the octet. */
276−
277− value = (value << 6) + (octet & 0x3F);
278− }
279−
280− /* Check the length of the sequence against the value. */
281−
282− if (!((width == 1) ||
283− (width == 2 && value >= 0x80) ||
284− (width == 3 && value >= 0x800) ||
285− (width == 4 && value >= 0x10000)))
286− return yaml_parser_set_reader_error(parser,
287− "invalid length of a UTF-8 sequence",
288− parser->offset, -1);
289−
290− /* Check the range of the value. */
291−
292− if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
293− return yaml_parser_set_reader_error(parser,
294− "invalid Unicode character",
295− parser->offset, value);
296−
297− break;
298−
299− case YAML_UTF16LE_ENCODING:
300− case YAML_UTF16BE_ENCODING:
301−
302− low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
303− high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
304−
305− /*
306− * The UTF-16 encoding is not as simple as one might
307− * naively think. Check RFC 2781
308− * (http://www.ietf.org/rfc/rfc2781.txt).
309− *
310− * Normally, two subsequent bytes describe a Unicode
311− * character. However a special technique (called a
312− * surrogate pair) is used for specifying character
313− * values larger than 0xFFFF.
314− *
315− * A surrogate pair consists of two pseudo-characters:
316− * high surrogate area (0xD800-0xDBFF)
317− * low surrogate area (0xDC00-0xDFFF)
318− *
319− * The following formulas are used for decoding
320− * and encoding characters using surrogate pairs:
321− *
322− * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
323− * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
324− * W1 = 110110yyyyyyyyyy
325− * W2 = 110111xxxxxxxxxx
326− *
327− * where U is the character value, W1 is the high surrogate
328− * area, W2 is the low surrogate area.
329− */
330−
331− /* Check for incomplete UTF-16 character. */
332−
333− if (raw_unread < 2) {
334− if (parser->eof) {
335− return yaml_parser_set_reader_error(parser,
336− "incomplete UTF-16 character",
337− parser->offset, -1);
338− }
339− incomplete = 1;
340− break;
341− }
342−
343− /* Get the character. */
344−
345− value = parser->raw_buffer.pointer[low]
346− + (parser->raw_buffer.pointer[high] << 8);
347−
348− /* Check for unexpected low surrogate area. */
349−
350− if ((value & 0xFC00) == 0xDC00)
351− return yaml_parser_set_reader_error(parser,
352− "unexpected low surrogate area",
353− parser->offset, value);
354−
355− /* Check for a high surrogate area. */
356−
357− if ((value & 0xFC00) == 0xD800) {
358−
359− width = 4;
360−
361− /* Check for incomplete surrogate pair. */
362−
363− if (raw_unread < 4) {
364− if (parser->eof) {
365− return yaml_parser_set_reader_error(parser,
366− "incomplete UTF-16 surrogate pair",
367− parser->offset, -1);
368− }
369− incomplete = 1;
370− break;
371− }
372−
373− /* Get the next character. */
374−
375− value2 = parser->raw_buffer.pointer[low+2]
376− + (parser->raw_buffer.pointer[high+2] << 8);
377−
378− /* Check for a low surrogate area. */
379−
380− if ((value2 & 0xFC00) != 0xDC00)
381− return yaml_parser_set_reader_error(parser,
382− "expected low surrogate area",
383− parser->offset+2, value2);
384−
385− /* Generate the value of the surrogate pair. */
386−
387− value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
388− }
389−
390− else {
391− width = 2;
392− }
393−
394− break;
395−
396− default:
397− assert(1); /* Impossible. */
398− }
399−
400− /* Check if the raw buffer contains enough bytes to form a character. */
401−
402− if (incomplete) break;
403−
404− /*
405− * Check if the character is in the allowed range:
406− * #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
407− * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
408− * | [#x10000-#x10FFFF] (32 bit)
409− */
410−
411− if (! (value == 0x09 || value == 0x0A || value == 0x0D
412− || (value >= 0x20 && value <= 0x7E)
413− || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
414− || (value >= 0xE000 && value <= 0xFFFD)
415− || (value >= 0x10000 && value <= 0x10FFFF)))
416− return yaml_parser_set_reader_error(parser,
417− "control characters are not allowed",
418− parser->offset, value);
419−
420− /* Move the raw pointers. */
421−
422− parser->raw_buffer.pointer += width;
423− parser->offset += width;
424−
425− /* Finally put the character into the buffer. */
426−
427− /* 0000 0000-0000 007F -> 0xxxxxxx */
428− if (value <= 0x7F) {
429− *(parser->buffer.last++) = value;
430− }
431− /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
432− else if (value <= 0x7FF) {
433− *(parser->buffer.last++) = 0xC0 + (value >> 6);
434− *(parser->buffer.last++) = 0x80 + (value & 0x3F);
435− }
436− /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
437− else if (value <= 0xFFFF) {
438− *(parser->buffer.last++) = 0xE0 + (value >> 12);
439− *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
440− *(parser->buffer.last++) = 0x80 + (value & 0x3F);
441− }
442− /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
443− else {
444− *(parser->buffer.last++) = 0xF0 + (value >> 18);
445− *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
446− *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
447− *(parser->buffer.last++) = 0x80 + (value & 0x3F);
448− }
449−
450− parser->unread ++;
451− }
452−
453− /* On EOF, put NUL into the buffer and return. */
454−
455− if (parser->eof) {
456− *(parser->buffer.last++) = '\0';
457− parser->unread ++;
458− return 1;
459− }
460−
461− }
462−
463− if (parser->offset >= PTRDIFF_MAX)
464− return yaml_parser_set_reader_error(parser, "input is too long",
465− PTRDIFF_MAX, -1);
466−
467− return 1;
468−}
469−
libyaml/scanner.cdeleted−3580
@@ -1,3580 +0,0 @@
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, ptrdiff_t column,
619− ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark);
620−
621−static int
622−yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t 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 == (ptrdiff_t)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;
1122− simple_key.possible = 1;
1123− simple_key.required = required;
1124− simple_key.token_number =
1125− parser->tokens_parsed + (parser->tokens.tail - parser->tokens.head);
1126− simple_key.mark = parser->mark;
1127−
1128− if (!yaml_parser_remove_simple_key(parser)) return 0;
1129−
1130− *(parser->simple_keys.top-1) = simple_key;
1131− }
1132−
1133− return 1;
1134−}
1135−
1136−/*
1137− * Remove a potential simple key at the current flow level.
1138− */
1139−
1140−static int
1141−yaml_parser_remove_simple_key(yaml_parser_t *parser)
1142−{
1143− yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
1144−
1145− if (simple_key->possible)
1146− {
1147− /* If the key is required, it is an error. */
1148−
1149− if (simple_key->required) {
1150− return yaml_parser_set_scanner_error(parser,
1151− "while scanning a simple key", simple_key->mark,
1152− "could not find expected ':'");
1153− }
1154− }
1155−
1156− /* Remove the key from the stack. */
1157−
1158− simple_key->possible = 0;
1159−
1160− return 1;
1161−}
1162−
1163−/*
1164− * Increase the flow level and resize the simple key list if needed.
1165− */
1166−
1167−static int
1168−yaml_parser_increase_flow_level(yaml_parser_t *parser)
1169−{
1170− yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } };
1171−
1172− /* Reset the simple key on the next level. */
1173−
1174− if (!PUSH(parser, parser->simple_keys, empty_simple_key))
1175− return 0;
1176−
1177− /* Increase the flow level. */
1178−
1179− if (parser->flow_level == INT_MAX) {
1180− parser->error = YAML_MEMORY_ERROR;
1181− return 0;
1182− }
1183−
1184− parser->flow_level++;
1185−
1186− return 1;
1187−}
1188−
1189−/*
1190− * Decrease the flow level.
1191− */
1192−
1193−static int
1194−yaml_parser_decrease_flow_level(yaml_parser_t *parser)
1195−{
1196− yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */
1197−
1198− if (parser->flow_level) {
1199− parser->flow_level --;
1200− dummy_key = POP(parser, parser->simple_keys);
1201− }
1202−
1203− return 1;
1204−}
1205−
1206−/*
1207− * Push the current indentation level to the stack and set the new level
1208− * the current column is greater than the indentation level. In this case,
1209− * append or insert the specified token into the token queue.
1210− *
1211− */
1212−
1213−static int
1214−yaml_parser_roll_indent(yaml_parser_t *parser, ptrdiff_t column,
1215− ptrdiff_t number, yaml_token_type_t type, yaml_mark_t mark)
1216−{
1217− yaml_token_t token;
1218−
1219− /* In the flow context, do nothing. */
1220−
1221− if (parser->flow_level)
1222− return 1;
1223−
1224− if (parser->indent < column)
1225− {
1226− /*
1227− * Push the current indentation level to the stack and set the new
1228− * indentation level.
1229− */
1230−
1231− if (!PUSH(parser, parser->indents, parser->indent))
1232− return 0;
1233−
1234− if (column > INT_MAX) {
1235− parser->error = YAML_MEMORY_ERROR;
1236− return 0;
1237− }
1238−
1239− parser->indent = column;
1240−
1241− /* Create a token and insert it into the queue. */
1242−
1243− TOKEN_INIT(token, type, mark, mark);
1244−
1245− if (number == -1) {
1246− if (!ENQUEUE(parser, parser->tokens, token))
1247− return 0;
1248− }
1249− else {
1250− if (!QUEUE_INSERT(parser,
1251− parser->tokens, number - parser->tokens_parsed, token))
1252− return 0;
1253− }
1254− }
1255−
1256− return 1;
1257−}
1258−
1259−/*
1260− * Pop indentation levels from the indents stack until the current level
1261− * becomes less or equal to the column. For each intendation level, append
1262− * the BLOCK-END token.
1263− */
1264−
1265−
1266−static int
1267−yaml_parser_unroll_indent(yaml_parser_t *parser, ptrdiff_t column)
1268−{
1269− yaml_token_t token;
1270−
1271− /* In the flow context, do nothing. */
1272−
1273− if (parser->flow_level)
1274− return 1;
1275−
1276− /* Loop through the intendation levels in the stack. */
1277−
1278− while (parser->indent > column)
1279− {
1280− /* Create a token and append it to the queue. */
1281−
1282− TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark);
1283−
1284− if (!ENQUEUE(parser, parser->tokens, token))
1285− return 0;
1286−
1287− /* Pop the indentation level. */
1288−
1289− parser->indent = POP(parser, parser->indents);
1290− }
1291−
1292− return 1;
1293−}
1294−
1295−/*
1296− * Initialize the scanner and produce the STREAM-START token.
1297− */
1298−
1299−static int
1300−yaml_parser_fetch_stream_start(yaml_parser_t *parser)
1301−{
1302− yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } };
1303− yaml_token_t token;
1304−
1305− /* Set the initial indentation. */
1306−
1307− parser->indent = -1;
1308−
1309− /* Initialize the simple key stack. */
1310−
1311− if (!PUSH(parser, parser->simple_keys, simple_key))
1312− return 0;
1313−
1314− /* A simple key is allowed at the beginning of the stream. */
1315−
1316− parser->simple_key_allowed = 1;
1317−
1318− /* We have started. */
1319−
1320− parser->stream_start_produced = 1;
1321−
1322− /* Create the STREAM-START token and append it to the queue. */
1323−
1324− STREAM_START_TOKEN_INIT(token, parser->encoding,
1325− parser->mark, parser->mark);
1326−
1327− if (!ENQUEUE(parser, parser->tokens, token))
1328− return 0;
1329−
1330− return 1;
1331−}
1332−
1333−/*
1334− * Produce the STREAM-END token and shut down the scanner.
1335− */
1336−
1337−static int
1338−yaml_parser_fetch_stream_end(yaml_parser_t *parser)
1339−{
1340− yaml_token_t token;
1341−
1342− /* Force new line. */
1343−
1344− if (parser->mark.column != 0) {
1345− parser->mark.column = 0;
1346− parser->mark.line ++;
1347− }
1348−
1349− /* Reset the indentation level. */
1350−
1351− if (!yaml_parser_unroll_indent(parser, -1))
1352− return 0;
1353−
1354− /* Reset simple keys. */
1355−
1356− if (!yaml_parser_remove_simple_key(parser))
1357− return 0;
1358−
1359− parser->simple_key_allowed = 0;
1360−
1361− /* Create the STREAM-END token and append it to the queue. */
1362−
1363− STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark);
1364−
1365− if (!ENQUEUE(parser, parser->tokens, token))
1366− return 0;
1367−
1368− return 1;
1369−}
1370−
1371−/*
1372− * Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
1373− */
1374−
1375−static int
1376−yaml_parser_fetch_directive(yaml_parser_t *parser)
1377−{
1378− yaml_token_t token;
1379−
1380− /* Reset the indentation level. */
1381−
1382− if (!yaml_parser_unroll_indent(parser, -1))
1383− return 0;
1384−
1385− /* Reset simple keys. */
1386−
1387− if (!yaml_parser_remove_simple_key(parser))
1388− return 0;
1389−
1390− parser->simple_key_allowed = 0;
1391−
1392− /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
1393−
1394− if (!yaml_parser_scan_directive(parser, &token))
1395− return 0;
1396−
1397− /* Append the token to the queue. */
1398−
1399− if (!ENQUEUE(parser, parser->tokens, token)) {
1400− yaml_token_delete(&token);
1401− return 0;
1402− }
1403−
1404− return 1;
1405−}
1406−
1407−/*
1408− * Produce the DOCUMENT-START or DOCUMENT-END token.
1409− */
1410−
1411−static int
1412−yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
1413− yaml_token_type_t type)
1414−{
1415− yaml_mark_t start_mark, end_mark;
1416− yaml_token_t token;
1417−
1418− /* Reset the indentation level. */
1419−
1420− if (!yaml_parser_unroll_indent(parser, -1))
1421− return 0;
1422−
1423− /* Reset simple keys. */
1424−
1425− if (!yaml_parser_remove_simple_key(parser))
1426− return 0;
1427−
1428− parser->simple_key_allowed = 0;
1429−
1430− /* Consume the token. */
1431−
1432− start_mark = parser->mark;
1433−
1434− SKIP(parser);
1435− SKIP(parser);
1436− SKIP(parser);
1437−
1438− end_mark = parser->mark;
1439−
1440− /* Create the DOCUMENT-START or DOCUMENT-END token. */
1441−
1442− TOKEN_INIT(token, type, start_mark, end_mark);
1443−
1444− /* Append the token to the queue. */
1445−
1446− if (!ENQUEUE(parser, parser->tokens, token))
1447− return 0;
1448−
1449− return 1;
1450−}
1451−
1452−/*
1453− * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1454− */
1455−
1456−static int
1457−yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
1458− yaml_token_type_t type)
1459−{
1460− yaml_mark_t start_mark, end_mark;
1461− yaml_token_t token;
1462−
1463− /* The indicators '[' and '{' may start a simple key. */
1464−
1465− if (!yaml_parser_save_simple_key(parser))
1466− return 0;
1467−
1468− /* Increase the flow level. */
1469−
1470− if (!yaml_parser_increase_flow_level(parser))
1471− return 0;
1472−
1473− /* A simple key may follow the indicators '[' and '{'. */
1474−
1475− parser->simple_key_allowed = 1;
1476−
1477− /* Consume the token. */
1478−
1479− start_mark = parser->mark;
1480− SKIP(parser);
1481− end_mark = parser->mark;
1482−
1483− /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
1484−
1485− TOKEN_INIT(token, type, start_mark, end_mark);
1486−
1487− /* Append the token to the queue. */
1488−
1489− if (!ENQUEUE(parser, parser->tokens, token))
1490− return 0;
1491−
1492− return 1;
1493−}
1494−
1495−/*
1496− * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1497− */
1498−
1499−static int
1500−yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
1501− yaml_token_type_t type)
1502−{
1503− yaml_mark_t start_mark, end_mark;
1504− yaml_token_t token;
1505−
1506− /* Reset any potential simple key on the current flow level. */
1507−
1508− if (!yaml_parser_remove_simple_key(parser))
1509− return 0;
1510−
1511− /* Decrease the flow level. */
1512−
1513− if (!yaml_parser_decrease_flow_level(parser))
1514− return 0;
1515−
1516− /* No simple keys after the indicators ']' and '}'. */
1517−
1518− parser->simple_key_allowed = 0;
1519−
1520− /* Consume the token. */
1521−
1522− start_mark = parser->mark;
1523− SKIP(parser);
1524− end_mark = parser->mark;
1525−
1526− /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
1527−
1528− TOKEN_INIT(token, type, start_mark, end_mark);
1529−
1530− /* Append the token to the queue. */
1531−
1532− if (!ENQUEUE(parser, parser->tokens, token))
1533− return 0;
1534−
1535− return 1;
1536−}
1537−
1538−/*
1539− * Produce the FLOW-ENTRY token.
1540− */
1541−
1542−static int
1543−yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
1544−{
1545− yaml_mark_t start_mark, end_mark;
1546− yaml_token_t token;
1547−
1548− /* Reset any potential simple keys on the current flow level. */
1549−
1550− if (!yaml_parser_remove_simple_key(parser))
1551− return 0;
1552−
1553− /* Simple keys are allowed after ','. */
1554−
1555− parser->simple_key_allowed = 1;
1556−
1557− /* Consume the token. */
1558−
1559− start_mark = parser->mark;
1560− SKIP(parser);
1561− end_mark = parser->mark;
1562−
1563− /* Create the FLOW-ENTRY token and append it to the queue. */
1564−
1565− TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
1566−
1567− if (!ENQUEUE(parser, parser->tokens, token))
1568− return 0;
1569−
1570− return 1;
1571−}
1572−
1573−/*
1574− * Produce the BLOCK-ENTRY token.
1575− */
1576−
1577−static int
1578−yaml_parser_fetch_block_entry(yaml_parser_t *parser)
1579−{
1580− yaml_mark_t start_mark, end_mark;
1581− yaml_token_t token;
1582−
1583− /* Check if the scanner is in the block context. */
1584−
1585− if (!parser->flow_level)
1586− {
1587− /* Check if we are allowed to start a new entry. */
1588−
1589− if (!parser->simple_key_allowed) {
1590− return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1591− "block sequence entries are not allowed in this context");
1592− }
1593−
1594− /* Add the BLOCK-SEQUENCE-START token if needed. */
1595−
1596− if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1597− YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark))
1598− return 0;
1599− }
1600− else
1601− {
1602− /*
1603− * It is an error for the '-' indicator to occur in the flow context,
1604− * but we let the Parser detect and report about it because the Parser
1605− * is able to point to the context.
1606− */
1607− }
1608−
1609− /* Reset any potential simple keys on the current flow level. */
1610−
1611− if (!yaml_parser_remove_simple_key(parser))
1612− return 0;
1613−
1614− /* Simple keys are allowed after '-'. */
1615−
1616− parser->simple_key_allowed = 1;
1617−
1618− /* Consume the token. */
1619−
1620− start_mark = parser->mark;
1621− SKIP(parser);
1622− end_mark = parser->mark;
1623−
1624− /* Create the BLOCK-ENTRY token and append it to the queue. */
1625−
1626− TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
1627−
1628− if (!ENQUEUE(parser, parser->tokens, token))
1629− return 0;
1630−
1631− return 1;
1632−}
1633−
1634−/*
1635− * Produce the KEY token.
1636− */
1637−
1638−static int
1639−yaml_parser_fetch_key(yaml_parser_t *parser)
1640−{
1641− yaml_mark_t start_mark, end_mark;
1642− yaml_token_t token;
1643−
1644− /* In the block context, additional checks are required. */
1645−
1646− if (!parser->flow_level)
1647− {
1648− /* Check if we are allowed to start a new key (not nessesary simple). */
1649−
1650− if (!parser->simple_key_allowed) {
1651− return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1652− "mapping keys are not allowed in this context");
1653− }
1654−
1655− /* Add the BLOCK-MAPPING-START token if needed. */
1656−
1657− if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1658− YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
1659− return 0;
1660− }
1661−
1662− /* Reset any potential simple keys on the current flow level. */
1663−
1664− if (!yaml_parser_remove_simple_key(parser))
1665− return 0;
1666−
1667− /* Simple keys are allowed after '?' in the block context. */
1668−
1669− parser->simple_key_allowed = (!parser->flow_level);
1670−
1671− /* Consume the token. */
1672−
1673− start_mark = parser->mark;
1674− SKIP(parser);
1675− end_mark = parser->mark;
1676−
1677− /* Create the KEY token and append it to the queue. */
1678−
1679− TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark);
1680−
1681− if (!ENQUEUE(parser, parser->tokens, token))
1682− return 0;
1683−
1684− return 1;
1685−}
1686−
1687−/*
1688− * Produce the VALUE token.
1689− */
1690−
1691−static int
1692−yaml_parser_fetch_value(yaml_parser_t *parser)
1693−{
1694− yaml_mark_t start_mark, end_mark;
1695− yaml_token_t token;
1696− yaml_simple_key_t *simple_key = parser->simple_keys.top-1;
1697−
1698− /* Have we found a simple key? */
1699−
1700− if (simple_key->possible)
1701− {
1702−
1703− /* Create the KEY token and insert it into the queue. */
1704−
1705− TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
1706−
1707− if (!QUEUE_INSERT(parser, parser->tokens,
1708− simple_key->token_number - parser->tokens_parsed, token))
1709− return 0;
1710−
1711− /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
1712−
1713− if (!yaml_parser_roll_indent(parser, simple_key->mark.column,
1714− simple_key->token_number,
1715− YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
1716− return 0;
1717−
1718− /* Remove the simple key. */
1719−
1720− simple_key->possible = 0;
1721−
1722− /* A simple key cannot follow another simple key. */
1723−
1724− parser->simple_key_allowed = 0;
1725− }
1726− else
1727− {
1728− /* The ':' indicator follows a complex key. */
1729−
1730− /* In the block context, extra checks are required. */
1731−
1732− if (!parser->flow_level)
1733− {
1734− /* Check if we are allowed to start a complex value. */
1735−
1736− if (!parser->simple_key_allowed) {
1737− return yaml_parser_set_scanner_error(parser, NULL, parser->mark,
1738− "mapping values are not allowed in this context");
1739− }
1740−
1741− /* Add the BLOCK-MAPPING-START token if needed. */
1742−
1743− if (!yaml_parser_roll_indent(parser, parser->mark.column, -1,
1744− YAML_BLOCK_MAPPING_START_TOKEN, parser->mark))
1745− return 0;
1746− }
1747−
1748− /* Simple keys after ':' are allowed in the block context. */
1749−
1750− parser->simple_key_allowed = (!parser->flow_level);
1751− }
1752−
1753− /* Consume the token. */
1754−
1755− start_mark = parser->mark;
1756− SKIP(parser);
1757− end_mark = parser->mark;
1758−
1759− /* Create the VALUE token and append it to the queue. */
1760−
1761− TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark);
1762−
1763− if (!ENQUEUE(parser, parser->tokens, token))
1764− return 0;
1765−
1766− return 1;
1767−}
1768−
1769−/*
1770− * Produce the ALIAS or ANCHOR token.
1771− */
1772−
1773−static int
1774−yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
1775−{
1776− yaml_token_t token;
1777−
1778− /* An anchor or an alias could be a simple key. */
1779−
1780− if (!yaml_parser_save_simple_key(parser))
1781− return 0;
1782−
1783− /* A simple key cannot follow an anchor or an alias. */
1784−
1785− parser->simple_key_allowed = 0;
1786−
1787− /* Create the ALIAS or ANCHOR token and append it to the queue. */
1788−
1789− if (!yaml_parser_scan_anchor(parser, &token, type))
1790− return 0;
1791−
1792− if (!ENQUEUE(parser, parser->tokens, token)) {
1793− yaml_token_delete(&token);
1794− return 0;
1795− }
1796− return 1;
1797−}
1798−
1799−/*
1800− * Produce the TAG token.
1801− */
1802−
1803−static int
1804−yaml_parser_fetch_tag(yaml_parser_t *parser)
1805−{
1806− yaml_token_t token;
1807−
1808− /* A tag could be a simple key. */
1809−
1810− if (!yaml_parser_save_simple_key(parser))
1811− return 0;
1812−
1813− /* A simple key cannot follow a tag. */
1814−
1815− parser->simple_key_allowed = 0;
1816−
1817− /* Create the TAG token and append it to the queue. */
1818−
1819− if (!yaml_parser_scan_tag(parser, &token))
1820− return 0;
1821−
1822− if (!ENQUEUE(parser, parser->tokens, token)) {
1823− yaml_token_delete(&token);
1824− return 0;
1825− }
1826−
1827− return 1;
1828−}
1829−
1830−/*
1831− * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
1832− */
1833−
1834−static int
1835−yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
1836−{
1837− yaml_token_t token;
1838−
1839− /* Remove any potential simple keys. */
1840−
1841− if (!yaml_parser_remove_simple_key(parser))
1842− return 0;
1843−
1844− /* A simple key may follow a block scalar. */
1845−
1846− parser->simple_key_allowed = 1;
1847−
1848− /* Create the SCALAR token and append it to the queue. */
1849−
1850− if (!yaml_parser_scan_block_scalar(parser, &token, literal))
1851− return 0;
1852−
1853− if (!ENQUEUE(parser, parser->tokens, token)) {
1854− yaml_token_delete(&token);
1855− return 0;
1856− }
1857−
1858− return 1;
1859−}
1860−
1861−/*
1862− * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
1863− */
1864−
1865−static int
1866−yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
1867−{
1868− yaml_token_t token;
1869−
1870− /* A plain scalar could be a simple key. */
1871−
1872− if (!yaml_parser_save_simple_key(parser))
1873− return 0;
1874−
1875− /* A simple key cannot follow a flow scalar. */
1876−
1877− parser->simple_key_allowed = 0;
1878−
1879− /* Create the SCALAR token and append it to the queue. */
1880−
1881− if (!yaml_parser_scan_flow_scalar(parser, &token, single))
1882− return 0;
1883−
1884− if (!ENQUEUE(parser, parser->tokens, token)) {
1885− yaml_token_delete(&token);
1886− return 0;
1887− }
1888−
1889− return 1;
1890−}
1891−
1892−/*
1893− * Produce the SCALAR(...,plain) token.
1894− */
1895−
1896−static int
1897−yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
1898−{
1899− yaml_token_t token;
1900−
1901− /* A plain scalar could be a simple key. */
1902−
1903− if (!yaml_parser_save_simple_key(parser))
1904− return 0;
1905−
1906− /* A simple key cannot follow a flow scalar. */
1907−
1908− parser->simple_key_allowed = 0;
1909−
1910− /* Create the SCALAR token and append it to the queue. */
1911−
1912− if (!yaml_parser_scan_plain_scalar(parser, &token))
1913− return 0;
1914−
1915− if (!ENQUEUE(parser, parser->tokens, token)) {
1916− yaml_token_delete(&token);
1917− return 0;
1918− }
1919−
1920− return 1;
1921−}
1922−
1923−/*
1924− * Eat whitespaces and comments until the next token is found.
1925− */
1926−
1927−static int
1928−yaml_parser_scan_to_next_token(yaml_parser_t *parser)
1929−{
1930− /* Until the next token is not found. */
1931−
1932− while (1)
1933− {
1934− /* Allow the BOM mark to start a line. */
1935−
1936− if (!CACHE(parser, 1)) return 0;
1937−
1938− if (parser->mark.column == 0 && IS_BOM(parser->buffer))
1939− SKIP(parser);
1940−
1941− /*
1942− * Eat whitespaces.
1943− *
1944− * Tabs are allowed:
1945− *
1946− * - in the flow context;
1947− * - in the block context, but not at the beginning of the line or
1948− * after '-', '?', or ':' (complex value).
1949− */
1950−
1951− if (!CACHE(parser, 1)) return 0;
1952−
1953− while (CHECK(parser->buffer,' ') ||
1954− ((parser->flow_level || !parser->simple_key_allowed) &&
1955− CHECK(parser->buffer, '\t'))) {
1956− SKIP(parser);
1957− if (!CACHE(parser, 1)) return 0;
1958− }
1959−
1960− /* Eat a comment until a line break. */
1961−
1962− if (CHECK(parser->buffer, '#')) {
1963− while (!IS_BREAKZ(parser->buffer)) {
1964− SKIP(parser);
1965− if (!CACHE(parser, 1)) return 0;
1966− }
1967− }
1968−
1969− /* If it is a line break, eat it. */
1970−
1971− if (IS_BREAK(parser->buffer))
1972− {
1973− if (!CACHE(parser, 2)) return 0;
1974− SKIP_LINE(parser);
1975−
1976− /* In the block context, a new line may start a simple key. */
1977−
1978− if (!parser->flow_level) {
1979− parser->simple_key_allowed = 1;
1980− }
1981− }
1982− else
1983− {
1984− /* We have found a token. */
1985−
1986− break;
1987− }
1988− }
1989−
1990− return 1;
1991−}
1992−
1993−/*
1994− * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
1995− *
1996− * Scope:
1997− * %YAML 1.1 # a comment \n
1998− * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1999− * %TAG !yaml! tag:yaml.org,2002: \n
2000− * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2001− */
2002−
2003−int
2004−yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token)
2005−{
2006− yaml_mark_t start_mark, end_mark;
2007− yaml_char_t *name = NULL;
2008− int major, minor;
2009− yaml_char_t *handle = NULL, *prefix = NULL;
2010−
2011− /* Eat '%'. */
2012−
2013− start_mark = parser->mark;
2014−
2015− SKIP(parser);
2016−
2017− /* Scan the directive name. */
2018−
2019− if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
2020− goto error;
2021−
2022− /* Is it a YAML directive? */
2023−
2024− if (strcmp((char *)name, "YAML") == 0)
2025− {
2026− /* Scan the VERSION directive value. */
2027−
2028− if (!yaml_parser_scan_version_directive_value(parser, start_mark,
2029− &major, &minor))
2030− goto error;
2031−
2032− end_mark = parser->mark;
2033−
2034− /* Create a VERSION-DIRECTIVE token. */
2035−
2036− VERSION_DIRECTIVE_TOKEN_INIT(*token, major, minor,
2037− start_mark, end_mark);
2038− }
2039−
2040− /* Is it a TAG directive? */
2041−
2042− else if (strcmp((char *)name, "TAG") == 0)
2043− {
2044− /* Scan the TAG directive value. */
2045−
2046− if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
2047− &handle, &prefix))
2048− goto error;
2049−
2050− end_mark = parser->mark;
2051−
2052− /* Create a TAG-DIRECTIVE token. */
2053−
2054− TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix,
2055− start_mark, end_mark);
2056− }
2057−
2058− /* Unknown directive. */
2059−
2060− else
2061− {
2062− yaml_parser_set_scanner_error(parser, "while scanning a directive",
2063− start_mark, "found uknown directive name");
2064− goto error;
2065− }
2066−
2067− /* Eat the rest of the line including any comments. */
2068−
2069− if (!CACHE(parser, 1)) goto error;
2070−
2071− while (IS_BLANK(parser->buffer)) {
2072− SKIP(parser);
2073− if (!CACHE(parser, 1)) goto error;
2074− }
2075−
2076− if (CHECK(parser->buffer, '#')) {
2077− while (!IS_BREAKZ(parser->buffer)) {
2078− SKIP(parser);
2079− if (!CACHE(parser, 1)) goto error;
2080− }
2081− }
2082−
2083− /* Check if we are at the end of the line. */
2084−
2085− if (!IS_BREAKZ(parser->buffer)) {
2086− yaml_parser_set_scanner_error(parser, "while scanning a directive",
2087− start_mark, "did not find expected comment or line break");
2088− goto error;
2089− }
2090−
2091− /* Eat a line break. */
2092−
2093− if (IS_BREAK(parser->buffer)) {
2094− if (!CACHE(parser, 2)) goto error;
2095− SKIP_LINE(parser);
2096− }
2097−
2098− yaml_free(name);
2099−
2100− return 1;
2101−
2102−error:
2103− yaml_free(prefix);
2104− yaml_free(handle);
2105− yaml_free(name);
2106− return 0;
2107−}
2108−
2109−/*
2110− * Scan the directive name.
2111− *
2112− * Scope:
2113− * %YAML 1.1 # a comment \n
2114− * ^^^^
2115− * %TAG !yaml! tag:yaml.org,2002: \n
2116− * ^^^
2117− */
2118−
2119−static int
2120−yaml_parser_scan_directive_name(yaml_parser_t *parser,
2121− yaml_mark_t start_mark, yaml_char_t **name)
2122−{
2123− yaml_string_t string = NULL_STRING;
2124−
2125− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2126−
2127− /* Consume the directive name. */
2128−
2129− if (!CACHE(parser, 1)) goto error;
2130−
2131− while (IS_ALPHA(parser->buffer))
2132− {
2133− if (!READ(parser, string)) goto error;
2134− if (!CACHE(parser, 1)) goto error;
2135− }
2136−
2137− /* Check if the name is empty. */
2138−
2139− if (string.start == string.pointer) {
2140− yaml_parser_set_scanner_error(parser, "while scanning a directive",
2141− start_mark, "could not find expected directive name");
2142− goto error;
2143− }
2144−
2145− /* Check for an blank character after the name. */
2146−
2147− if (!IS_BLANKZ(parser->buffer)) {
2148− yaml_parser_set_scanner_error(parser, "while scanning a directive",
2149− start_mark, "found unexpected non-alphabetical character");
2150− goto error;
2151− }
2152−
2153− *name = string.start;
2154−
2155− return 1;
2156−
2157−error:
2158− STRING_DEL(parser, string);
2159− return 0;
2160−}
2161−
2162−/*
2163− * Scan the value of VERSION-DIRECTIVE.
2164− *
2165− * Scope:
2166− * %YAML 1.1 # a comment \n
2167− * ^^^^^^
2168− */
2169−
2170−static int
2171−yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
2172− yaml_mark_t start_mark, int *major, int *minor)
2173−{
2174− /* Eat whitespaces. */
2175−
2176− if (!CACHE(parser, 1)) return 0;
2177−
2178− while (IS_BLANK(parser->buffer)) {
2179− SKIP(parser);
2180− if (!CACHE(parser, 1)) return 0;
2181− }
2182−
2183− /* Consume the major version number. */
2184−
2185− if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
2186− return 0;
2187−
2188− /* Eat '.'. */
2189−
2190− if (!CHECK(parser->buffer, '.')) {
2191− return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2192− start_mark, "did not find expected digit or '.' character");
2193− }
2194−
2195− SKIP(parser);
2196−
2197− /* Consume the minor version number. */
2198−
2199− if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
2200− return 0;
2201−
2202− return 1;
2203−}
2204−
2205−#define MAX_NUMBER_LENGTH 9
2206−
2207−/*
2208− * Scan the version number of VERSION-DIRECTIVE.
2209− *
2210− * Scope:
2211− * %YAML 1.1 # a comment \n
2212− * ^
2213− * %YAML 1.1 # a comment \n
2214− * ^
2215− */
2216−
2217−static int
2218−yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
2219− yaml_mark_t start_mark, int *number)
2220−{
2221− int value = 0;
2222− size_t length = 0;
2223−
2224− /* Repeat while the next character is digit. */
2225−
2226− if (!CACHE(parser, 1)) return 0;
2227−
2228− while (IS_DIGIT(parser->buffer))
2229− {
2230− /* Check if the number is too long. */
2231−
2232− if (++length > MAX_NUMBER_LENGTH) {
2233− return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2234− start_mark, "found extremely long version number");
2235− }
2236−
2237− value = value*10 + AS_DIGIT(parser->buffer);
2238−
2239− SKIP(parser);
2240−
2241− if (!CACHE(parser, 1)) return 0;
2242− }
2243−
2244− /* Check if the number was present. */
2245−
2246− if (!length) {
2247− return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2248− start_mark, "did not find expected version number");
2249− }
2250−
2251− *number = value;
2252−
2253− return 1;
2254−}
2255−
2256−/*
2257− * Scan the value of a TAG-DIRECTIVE token.
2258− *
2259− * Scope:
2260− * %TAG !yaml! tag:yaml.org,2002: \n
2261− * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2262− */
2263−
2264−static int
2265−yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
2266− yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
2267−{
2268− yaml_char_t *handle_value = NULL;
2269− yaml_char_t *prefix_value = NULL;
2270−
2271− /* Eat whitespaces. */
2272−
2273− if (!CACHE(parser, 1)) goto error;
2274−
2275− while (IS_BLANK(parser->buffer)) {
2276− SKIP(parser);
2277− if (!CACHE(parser, 1)) goto error;
2278− }
2279−
2280− /* Scan a handle. */
2281−
2282− if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
2283− goto error;
2284−
2285− /* Expect a whitespace. */
2286−
2287− if (!CACHE(parser, 1)) goto error;
2288−
2289− if (!IS_BLANK(parser->buffer)) {
2290− yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2291− start_mark, "did not find expected whitespace");
2292− goto error;
2293− }
2294−
2295− /* Eat whitespaces. */
2296−
2297− while (IS_BLANK(parser->buffer)) {
2298− SKIP(parser);
2299− if (!CACHE(parser, 1)) goto error;
2300− }
2301−
2302− /* Scan a prefix. */
2303−
2304− if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
2305− goto error;
2306−
2307− /* Expect a whitespace or line break. */
2308−
2309− if (!CACHE(parser, 1)) goto error;
2310−
2311− if (!IS_BLANKZ(parser->buffer)) {
2312− yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2313− start_mark, "did not find expected whitespace or line break");
2314− goto error;
2315− }
2316−
2317− *handle = handle_value;
2318− *prefix = prefix_value;
2319−
2320− return 1;
2321−
2322−error:
2323− yaml_free(handle_value);
2324− yaml_free(prefix_value);
2325− return 0;
2326−}
2327−
2328−static int
2329−yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token,
2330− yaml_token_type_t type)
2331−{
2332− int length = 0;
2333− yaml_mark_t start_mark, end_mark;
2334− yaml_string_t string = NULL_STRING;
2335−
2336− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2337−
2338− /* Eat the indicator character. */
2339−
2340− start_mark = parser->mark;
2341−
2342− SKIP(parser);
2343−
2344− /* Consume the value. */
2345−
2346− if (!CACHE(parser, 1)) goto error;
2347−
2348− while (IS_ALPHA(parser->buffer)) {
2349− if (!READ(parser, string)) goto error;
2350− if (!CACHE(parser, 1)) goto error;
2351− length ++;
2352− }
2353−
2354− end_mark = parser->mark;
2355−
2356− /*
2357− * Check if length of the anchor is greater than 0 and it is followed by
2358− * a whitespace character or one of the indicators:
2359− *
2360− * '?', ':', ',', ']', '}', '%', '@', '`'.
2361− */
2362−
2363− if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?')
2364− || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',')
2365− || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}')
2366− || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@')
2367− || CHECK(parser->buffer, '`'))) {
2368− yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
2369− "while scanning an anchor" : "while scanning an alias", start_mark,
2370− "did not find expected alphabetic or numeric character");
2371− goto error;
2372− }
2373−
2374− /* Create a token. */
2375−
2376− if (type == YAML_ANCHOR_TOKEN) {
2377− ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark);
2378− }
2379− else {
2380− ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark);
2381− }
2382−
2383− return 1;
2384−
2385−error:
2386− STRING_DEL(parser, string);
2387− return 0;
2388−}
2389−
2390−/*
2391− * Scan a TAG token.
2392− */
2393−
2394−static int
2395−yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
2396−{
2397− yaml_char_t *handle = NULL;
2398− yaml_char_t *suffix = NULL;
2399− yaml_mark_t start_mark, end_mark;
2400−
2401− start_mark = parser->mark;
2402−
2403− /* Check if the tag is in the canonical form. */
2404−
2405− if (!CACHE(parser, 2)) goto error;
2406−
2407− if (CHECK_AT(parser->buffer, '<', 1))
2408− {
2409− /* Set the handle to '' */
2410−
2411− handle = yaml_malloc(1);
2412− if (!handle) goto error;
2413− handle[0] = '\0';
2414−
2415− /* Eat '!<' */
2416−
2417− SKIP(parser);
2418− SKIP(parser);
2419−
2420− /* Consume the tag value. */
2421−
2422− if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2423− goto error;
2424−
2425− /* Check for '>' and eat it. */
2426−
2427− if (!CHECK(parser->buffer, '>')) {
2428− yaml_parser_set_scanner_error(parser, "while scanning a tag",
2429− start_mark, "did not find the expected '>'");
2430− goto error;
2431− }
2432−
2433− SKIP(parser);
2434− }
2435− else
2436− {
2437− /* The tag has either the '!suffix' or the '!handle!suffix' form. */
2438−
2439− /* First, try to scan a handle. */
2440−
2441− if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
2442− goto error;
2443−
2444− /* Check if it is, indeed, handle. */
2445−
2446− if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
2447− {
2448− /* Scan the suffix now. */
2449−
2450− if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2451− goto error;
2452− }
2453− else
2454− {
2455− /* It wasn't a handle after all. Scan the rest of the tag. */
2456−
2457− if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
2458− goto error;
2459−
2460− /* Set the handle to '!'. */
2461−
2462− yaml_free(handle);
2463− handle = yaml_malloc(2);
2464− if (!handle) goto error;
2465− handle[0] = '!';
2466− handle[1] = '\0';
2467−
2468− /*
2469− * A special case: the '!' tag. Set the handle to '' and the
2470− * suffix to '!'.
2471− */
2472−
2473− if (suffix[0] == '\0') {
2474− yaml_char_t *tmp = handle;
2475− handle = suffix;
2476− suffix = tmp;
2477− }
2478− }
2479− }
2480−
2481− /* Check the character which ends the tag. */
2482−
2483− if (!CACHE(parser, 1)) goto error;
2484−
2485− if (!IS_BLANKZ(parser->buffer)) {
2486− yaml_parser_set_scanner_error(parser, "while scanning a tag",
2487− start_mark, "did not find expected whitespace or line break");
2488− goto error;
2489− }
2490−
2491− end_mark = parser->mark;
2492−
2493− /* Create a token. */
2494−
2495− TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark);
2496−
2497− return 1;
2498−
2499−error:
2500− yaml_free(handle);
2501− yaml_free(suffix);
2502− return 0;
2503−}
2504−
2505−/*
2506− * Scan a tag handle.
2507− */
2508−
2509−static int
2510−yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
2511− yaml_mark_t start_mark, yaml_char_t **handle)
2512−{
2513− yaml_string_t string = NULL_STRING;
2514−
2515− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2516−
2517− /* Check the initial '!' character. */
2518−
2519− if (!CACHE(parser, 1)) goto error;
2520−
2521− if (!CHECK(parser->buffer, '!')) {
2522− yaml_parser_set_scanner_error(parser, directive ?
2523− "while scanning a tag directive" : "while scanning a tag",
2524− start_mark, "did not find expected '!'");
2525− goto error;
2526− }
2527−
2528− /* Copy the '!' character. */
2529−
2530− if (!READ(parser, string)) goto error;
2531−
2532− /* Copy all subsequent alphabetical and numerical characters. */
2533−
2534− if (!CACHE(parser, 1)) goto error;
2535−
2536− while (IS_ALPHA(parser->buffer))
2537− {
2538− if (!READ(parser, string)) goto error;
2539− if (!CACHE(parser, 1)) goto error;
2540− }
2541−
2542− /* Check if the trailing character is '!' and copy it. */
2543−
2544− if (CHECK(parser->buffer, '!'))
2545− {
2546− if (!READ(parser, string)) goto error;
2547− }
2548− else
2549− {
2550− /*
2551− * It's either the '!' tag or not really a tag handle. If it's a %TAG
2552− * directive, it's an error. If it's a tag token, it must be a part of
2553− * URI.
2554− */
2555−
2556− if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) {
2557− yaml_parser_set_scanner_error(parser, "while parsing a tag directive",
2558− start_mark, "did not find expected '!'");
2559− goto error;
2560− }
2561− }
2562−
2563− *handle = string.start;
2564−
2565− return 1;
2566−
2567−error:
2568− STRING_DEL(parser, string);
2569− return 0;
2570−}
2571−
2572−/*
2573− * Scan a tag.
2574− */
2575−
2576−static int
2577−yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
2578− yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
2579−{
2580− size_t length = head ? strlen((char *)head) : 0;
2581− yaml_string_t string = NULL_STRING;
2582−
2583− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2584−
2585− /* Resize the string to include the head. */
2586−
2587− while ((size_t)(string.end - string.start) <= length) {
2588− if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) {
2589− parser->error = YAML_MEMORY_ERROR;
2590− goto error;
2591− }
2592− }
2593−
2594− /*
2595− * Copy the head if needed.
2596− *
2597− * Note that we don't copy the leading '!' character.
2598− */
2599−
2600− if (length > 1) {
2601− memcpy(string.start, head+1, length-1);
2602− string.pointer += length-1;
2603− }
2604−
2605− /* Scan the tag. */
2606−
2607− if (!CACHE(parser, 1)) goto error;
2608−
2609− /*
2610− * The set of characters that may appear in URI is as follows:
2611− *
2612− * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
2613− * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
2614− * '%'.
2615− */
2616−
2617− while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';')
2618− || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?')
2619− || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@')
2620− || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=')
2621− || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$')
2622− || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.')
2623− || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~')
2624− || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'')
2625− || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')')
2626− || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']')
2627− || CHECK(parser->buffer, '%'))
2628− {
2629− /* Check if it is a URI-escape sequence. */
2630−
2631− if (CHECK(parser->buffer, '%')) {
2632− if (!yaml_parser_scan_uri_escapes(parser,
2633− directive, start_mark, &string)) goto error;
2634− }
2635− else {
2636− if (!READ(parser, string)) goto error;
2637− }
2638−
2639− length ++;
2640− if (!CACHE(parser, 1)) goto error;
2641− }
2642−
2643− /* Check if the tag is non-empty. */
2644−
2645− if (!length) {
2646− if (!STRING_EXTEND(parser, string))
2647− goto error;
2648−
2649− yaml_parser_set_scanner_error(parser, directive ?
2650− "while parsing a %TAG directive" : "while parsing a tag",
2651− start_mark, "did not find expected tag URI");
2652− goto error;
2653− }
2654−
2655− *uri = string.start;
2656−
2657− return 1;
2658−
2659−error:
2660− STRING_DEL(parser, string);
2661− return 0;
2662−}
2663−
2664−/*
2665− * Decode an URI-escape sequence corresponding to a single UTF-8 character.
2666− */
2667−
2668−static int
2669−yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
2670− yaml_mark_t start_mark, yaml_string_t *string)
2671−{
2672− int width = 0;
2673−
2674− /* Decode the required number of characters. */
2675−
2676− do {
2677−
2678− unsigned char octet = 0;
2679−
2680− /* Check for a URI-escaped octet. */
2681−
2682− if (!CACHE(parser, 3)) return 0;
2683−
2684− if (!(CHECK(parser->buffer, '%')
2685− && IS_HEX_AT(parser->buffer, 1)
2686− && IS_HEX_AT(parser->buffer, 2))) {
2687− return yaml_parser_set_scanner_error(parser, directive ?
2688− "while parsing a %TAG directive" : "while parsing a tag",
2689− start_mark, "did not find URI escaped octet");
2690− }
2691−
2692− /* Get the octet. */
2693−
2694− octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2);
2695−
2696− /* If it is the leading octet, determine the length of the UTF-8 sequence. */
2697−
2698− if (!width)
2699− {
2700− width = (octet & 0x80) == 0x00 ? 1 :
2701− (octet & 0xE0) == 0xC0 ? 2 :
2702− (octet & 0xF0) == 0xE0 ? 3 :
2703− (octet & 0xF8) == 0xF0 ? 4 : 0;
2704− if (!width) {
2705− return yaml_parser_set_scanner_error(parser, directive ?
2706− "while parsing a %TAG directive" : "while parsing a tag",
2707− start_mark, "found an incorrect leading UTF-8 octet");
2708− }
2709− }
2710− else
2711− {
2712− /* Check if the trailing octet is correct. */
2713−
2714− if ((octet & 0xC0) != 0x80) {
2715− return yaml_parser_set_scanner_error(parser, directive ?
2716− "while parsing a %TAG directive" : "while parsing a tag",
2717− start_mark, "found an incorrect trailing UTF-8 octet");
2718− }
2719− }
2720−
2721− /* Copy the octet and move the pointers. */
2722−
2723− *(string->pointer++) = octet;
2724− SKIP(parser);
2725− SKIP(parser);
2726− SKIP(parser);
2727−
2728− } while (--width);
2729−
2730− return 1;
2731−}
2732−
2733−/*
2734− * Scan a block scalar.
2735− */
2736−
2737−static int
2738−yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
2739− int literal)
2740−{
2741− yaml_mark_t start_mark;
2742− yaml_mark_t end_mark;
2743− yaml_string_t string = NULL_STRING;
2744− yaml_string_t leading_break = NULL_STRING;
2745− yaml_string_t trailing_breaks = NULL_STRING;
2746− int chomping = 0;
2747− int increment = 0;
2748− int indent = 0;
2749− int leading_blank = 0;
2750− int trailing_blank = 0;
2751−
2752− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
2753− if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
2754− if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
2755−
2756− /* Eat the indicator '|' or '>'. */
2757−
2758− start_mark = parser->mark;
2759−
2760− SKIP(parser);
2761−
2762− /* Scan the additional block scalar indicators. */
2763−
2764− if (!CACHE(parser, 1)) goto error;
2765−
2766− /* Check for a chomping indicator. */
2767−
2768− if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-'))
2769− {
2770− /* Set the chomping method and eat the indicator. */
2771−
2772− chomping = CHECK(parser->buffer, '+') ? +1 : -1;
2773−
2774− SKIP(parser);
2775−
2776− /* Check for an indentation indicator. */
2777−
2778− if (!CACHE(parser, 1)) goto error;
2779−
2780− if (IS_DIGIT(parser->buffer))
2781− {
2782− /* Check that the intendation is greater than 0. */
2783−
2784− if (CHECK(parser->buffer, '0')) {
2785− yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2786− start_mark, "found an intendation indicator equal to 0");
2787− goto error;
2788− }
2789−
2790− /* Get the intendation level and eat the indicator. */
2791−
2792− increment = AS_DIGIT(parser->buffer);
2793−
2794− SKIP(parser);
2795− }
2796− }
2797−
2798− /* Do the same as above, but in the opposite order. */
2799−
2800− else if (IS_DIGIT(parser->buffer))
2801− {
2802− if (CHECK(parser->buffer, '0')) {
2803− yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2804− start_mark, "found an intendation indicator equal to 0");
2805− goto error;
2806− }
2807−
2808− increment = AS_DIGIT(parser->buffer);
2809−
2810− SKIP(parser);
2811−
2812− if (!CACHE(parser, 1)) goto error;
2813−
2814− if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) {
2815− chomping = CHECK(parser->buffer, '+') ? +1 : -1;
2816−
2817− SKIP(parser);
2818− }
2819− }
2820−
2821− /* Eat whitespaces and comments to the end of the line. */
2822−
2823− if (!CACHE(parser, 1)) goto error;
2824−
2825− while (IS_BLANK(parser->buffer)) {
2826− SKIP(parser);
2827− if (!CACHE(parser, 1)) goto error;
2828− }
2829−
2830− if (CHECK(parser->buffer, '#')) {
2831− while (!IS_BREAKZ(parser->buffer)) {
2832− SKIP(parser);
2833− if (!CACHE(parser, 1)) goto error;
2834− }
2835− }
2836−
2837− /* Check if we are at the end of the line. */
2838−
2839− if (!IS_BREAKZ(parser->buffer)) {
2840− yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2841− start_mark, "did not find expected comment or line break");
2842− goto error;
2843− }
2844−
2845− /* Eat a line break. */
2846−
2847− if (IS_BREAK(parser->buffer)) {
2848− if (!CACHE(parser, 2)) goto error;
2849− SKIP_LINE(parser);
2850− }
2851−
2852− end_mark = parser->mark;
2853−
2854− /* Set the intendation level if it was specified. */
2855−
2856− if (increment) {
2857− indent = parser->indent >= 0 ? parser->indent+increment : increment;
2858− }
2859−
2860− /* Scan the leading line breaks and determine the indentation level if needed. */
2861−
2862− if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks,
2863− start_mark, &end_mark)) goto error;
2864−
2865− /* Scan the block scalar content. */
2866−
2867− if (!CACHE(parser, 1)) goto error;
2868−
2869− while ((int)parser->mark.column == indent && !IS_Z(parser->buffer))
2870− {
2871− /*
2872− * We are at the beginning of a non-empty line.
2873− */
2874−
2875− /* Is it a trailing whitespace? */
2876−
2877− trailing_blank = IS_BLANK(parser->buffer);
2878−
2879− /* Check if we need to fold the leading line break. */
2880−
2881− if (!literal && (*leading_break.start == '\n')
2882− && !leading_blank && !trailing_blank)
2883− {
2884− /* Do we need to join the lines by space? */
2885−
2886− if (*trailing_breaks.start == '\0') {
2887− if (!STRING_EXTEND(parser, string)) goto error;
2888− *(string.pointer ++) = ' ';
2889− }
2890−
2891− CLEAR(parser, leading_break);
2892− }
2893− else {
2894− if (!JOIN(parser, string, leading_break)) goto error;
2895− CLEAR(parser, leading_break);
2896− }
2897−
2898− /* Append the remaining line breaks. */
2899−
2900− if (!JOIN(parser, string, trailing_breaks)) goto error;
2901− CLEAR(parser, trailing_breaks);
2902−
2903− /* Is it a leading whitespace? */
2904−
2905− leading_blank = IS_BLANK(parser->buffer);
2906−
2907− /* Consume the current line. */
2908−
2909− while (!IS_BREAKZ(parser->buffer)) {
2910− if (!READ(parser, string)) goto error;
2911− if (!CACHE(parser, 1)) goto error;
2912− }
2913−
2914− /* Consume the line break. */
2915−
2916− if (!CACHE(parser, 2)) goto error;
2917−
2918− if (!READ_LINE(parser, leading_break)) goto error;
2919−
2920− /* Eat the following intendation spaces and line breaks. */
2921−
2922− if (!yaml_parser_scan_block_scalar_breaks(parser,
2923− &indent, &trailing_breaks, start_mark, &end_mark)) goto error;
2924− }
2925−
2926− /* Chomp the tail. */
2927−
2928− if (chomping != -1) {
2929− if (!JOIN(parser, string, leading_break)) goto error;
2930− }
2931− if (chomping == 1) {
2932− if (!JOIN(parser, string, trailing_breaks)) goto error;
2933− }
2934−
2935− /* Create a token. */
2936−
2937− SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
2938− literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE,
2939− start_mark, end_mark);
2940−
2941− STRING_DEL(parser, leading_break);
2942− STRING_DEL(parser, trailing_breaks);
2943−
2944− return 1;
2945−
2946−error:
2947− STRING_DEL(parser, string);
2948− STRING_DEL(parser, leading_break);
2949− STRING_DEL(parser, trailing_breaks);
2950−
2951− return 0;
2952−}
2953−
2954−/*
2955− * Scan intendation spaces and line breaks for a block scalar. Determine the
2956− * intendation level if needed.
2957− */
2958−
2959−static int
2960−yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser,
2961− int *indent, yaml_string_t *breaks,
2962− yaml_mark_t start_mark, yaml_mark_t *end_mark)
2963−{
2964− int max_indent = 0;
2965−
2966− *end_mark = parser->mark;
2967−
2968− /* Eat the intendation spaces and line breaks. */
2969−
2970− while (1)
2971− {
2972− /* Eat the intendation spaces. */
2973−
2974− if (!CACHE(parser, 1)) return 0;
2975−
2976− while ((!*indent || (int)parser->mark.column < *indent)
2977− && IS_SPACE(parser->buffer)) {
2978− SKIP(parser);
2979− if (!CACHE(parser, 1)) return 0;
2980− }
2981−
2982− if ((int)parser->mark.column > max_indent)
2983− max_indent = (int)parser->mark.column;
2984−
2985− /* Check for a tab character messing the intendation. */
2986−
2987− if ((!*indent || (int)parser->mark.column < *indent)
2988− && IS_TAB(parser->buffer)) {
2989− return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
2990− start_mark, "found a tab character where an intendation space is expected");
2991− }
2992−
2993− /* Have we found a non-empty line? */
2994−
2995− if (!IS_BREAK(parser->buffer)) break;
2996−
2997− /* Consume the line break. */
2998−
2999− if (!CACHE(parser, 2)) return 0;
3000− if (!READ_LINE(parser, *breaks)) return 0;
3001− *end_mark = parser->mark;
3002− }
3003−
3004− /* Determine the indentation level if needed. */
3005−
3006− if (!*indent) {
3007− *indent = max_indent;
3008− if (*indent < parser->indent + 1)
3009− *indent = parser->indent + 1;
3010− if (*indent < 1)
3011− *indent = 1;
3012− }
3013−
3014− return 1;
3015−}
3016−
3017−/*
3018− * Scan a quoted scalar.
3019− */
3020−
3021−static int
3022−yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
3023− int single)
3024−{
3025− yaml_mark_t start_mark;
3026− yaml_mark_t end_mark;
3027− yaml_string_t string = NULL_STRING;
3028− yaml_string_t leading_break = NULL_STRING;
3029− yaml_string_t trailing_breaks = NULL_STRING;
3030− yaml_string_t whitespaces = NULL_STRING;
3031− int leading_blanks;
3032−
3033− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
3034− if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
3035− if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
3036− if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
3037−
3038− /* Eat the left quote. */
3039−
3040− start_mark = parser->mark;
3041−
3042− SKIP(parser);
3043−
3044− /* Consume the content of the quoted scalar. */
3045−
3046− while (1)
3047− {
3048− /* Check that there are no document indicators at the beginning of the line. */
3049−
3050− if (!CACHE(parser, 4)) goto error;
3051−
3052− if (parser->mark.column == 0 &&
3053− ((CHECK_AT(parser->buffer, '-', 0) &&
3054− CHECK_AT(parser->buffer, '-', 1) &&
3055− CHECK_AT(parser->buffer, '-', 2)) ||
3056− (CHECK_AT(parser->buffer, '.', 0) &&
3057− CHECK_AT(parser->buffer, '.', 1) &&
3058− CHECK_AT(parser->buffer, '.', 2))) &&
3059− IS_BLANKZ_AT(parser->buffer, 3))
3060− {
3061− yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3062− start_mark, "found unexpected document indicator");
3063− goto error;
3064− }
3065−
3066− /* Check for EOF. */
3067−
3068− if (IS_Z(parser->buffer)) {
3069− yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
3070− start_mark, "found unexpected end of stream");
3071− goto error;
3072− }
3073−
3074− /* Consume non-blank characters. */
3075−
3076− if (!CACHE(parser, 2)) goto error;
3077−
3078− leading_blanks = 0;
3079−
3080− while (!IS_BLANKZ(parser->buffer))
3081− {
3082− /* Check for an escaped single quote. */
3083−
3084− if (single && CHECK_AT(parser->buffer, '\'', 0)
3085− && CHECK_AT(parser->buffer, '\'', 1))
3086− {
3087− if (!STRING_EXTEND(parser, string)) goto error;
3088− *(string.pointer++) = '\'';
3089− SKIP(parser);
3090− SKIP(parser);
3091− }
3092−
3093− /* Check for the right quote. */
3094−
3095− else if (CHECK(parser->buffer, single ? '\'' : '"'))
3096− {
3097− break;
3098− }
3099−
3100− /* Check for an escaped line break. */
3101−
3102− else if (!single && CHECK(parser->buffer, '\\')
3103− && IS_BREAK_AT(parser->buffer, 1))
3104− {
3105− if (!CACHE(parser, 3)) goto error;
3106− SKIP(parser);
3107− SKIP_LINE(parser);
3108− leading_blanks = 1;
3109− break;
3110− }
3111−
3112− /* Check for an escape sequence. */
3113−
3114− else if (!single && CHECK(parser->buffer, '\\'))
3115− {
3116− size_t code_length = 0;
3117−
3118− if (!STRING_EXTEND(parser, string)) goto error;
3119−
3120− /* Check the escape character. */
3121−
3122− switch (parser->buffer.pointer[1])
3123− {
3124− case '0':
3125− *(string.pointer++) = '\0';
3126− break;
3127−
3128− case 'a':
3129− *(string.pointer++) = '\x07';
3130− break;
3131−
3132− case 'b':
3133− *(string.pointer++) = '\x08';
3134− break;
3135−
3136− case 't':
3137− case '\t':
3138− *(string.pointer++) = '\x09';
3139− break;
3140−
3141− case 'n':
3142− *(string.pointer++) = '\x0A';
3143− break;
3144−
3145− case 'v':
3146− *(string.pointer++) = '\x0B';
3147− break;
3148−
3149− case 'f':
3150− *(string.pointer++) = '\x0C';
3151− break;
3152−
3153− case 'r':
3154− *(string.pointer++) = '\x0D';
3155− break;
3156−
3157− case 'e':
3158− *(string.pointer++) = '\x1B';
3159− break;
3160−
3161− case ' ':
3162− *(string.pointer++) = '\x20';
3163− break;
3164−
3165− case '"':
3166− *(string.pointer++) = '"';
3167− break;
3168−
3169− case '\'':
3170− *(string.pointer++) = '\'';
3171− break;
3172−
3173− case '\\':
3174− *(string.pointer++) = '\\';
3175− break;
3176−
3177− case 'N': /* NEL (#x85) */
3178− *(string.pointer++) = '\xC2';
3179− *(string.pointer++) = '\x85';
3180− break;
3181−
3182− case '_': /* #xA0 */
3183− *(string.pointer++) = '\xC2';
3184− *(string.pointer++) = '\xA0';
3185− break;
3186−
3187− case 'L': /* LS (#x2028) */
3188− *(string.pointer++) = '\xE2';
3189− *(string.pointer++) = '\x80';
3190− *(string.pointer++) = '\xA8';
3191− break;
3192−
3193− case 'P': /* PS (#x2029) */
3194− *(string.pointer++) = '\xE2';
3195− *(string.pointer++) = '\x80';
3196− *(string.pointer++) = '\xA9';
3197− break;
3198−
3199− case 'x':
3200− code_length = 2;
3201− break;
3202−
3203− case 'u':
3204− code_length = 4;
3205− break;
3206−
3207− case 'U':
3208− code_length = 8;
3209− break;
3210−
3211− default:
3212− yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3213− start_mark, "found unknown escape character");
3214− goto error;
3215− }
3216−
3217− SKIP(parser);
3218− SKIP(parser);
3219−
3220− /* Consume an arbitrary escape code. */
3221−
3222− if (code_length)
3223− {
3224− unsigned int value = 0;
3225− size_t k;
3226−
3227− /* Scan the character value. */
3228−
3229− if (!CACHE(parser, code_length)) goto error;
3230−
3231− for (k = 0; k < code_length; k ++) {
3232− if (!IS_HEX_AT(parser->buffer, k)) {
3233− yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3234− start_mark, "did not find expected hexdecimal number");
3235− goto error;
3236− }
3237− value = (value << 4) + AS_HEX_AT(parser->buffer, k);
3238− }
3239−
3240− /* Check the value and write the character. */
3241−
3242− if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
3243− yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
3244− start_mark, "found invalid Unicode character escape code");
3245− goto error;
3246− }
3247−
3248− if (value <= 0x7F) {
3249− *(string.pointer++) = value;
3250− }
3251− else if (value <= 0x7FF) {
3252− *(string.pointer++) = 0xC0 + (value >> 6);
3253− *(string.pointer++) = 0x80 + (value & 0x3F);
3254− }
3255− else if (value <= 0xFFFF) {
3256− *(string.pointer++) = 0xE0 + (value >> 12);
3257− *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3258− *(string.pointer++) = 0x80 + (value & 0x3F);
3259− }
3260− else {
3261− *(string.pointer++) = 0xF0 + (value >> 18);
3262− *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F);
3263− *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F);
3264− *(string.pointer++) = 0x80 + (value & 0x3F);
3265− }
3266−
3267− /* Advance the pointer. */
3268−
3269− for (k = 0; k < code_length; k ++) {
3270− SKIP(parser);
3271− }
3272− }
3273− }
3274−
3275− else
3276− {
3277− /* It is a non-escaped non-blank character. */
3278−
3279− if (!READ(parser, string)) goto error;
3280− }
3281−
3282− if (!CACHE(parser, 2)) goto error;
3283− }
3284−
3285− /* Check if we are at the end of the scalar. */
3286−
3287− if (CHECK(parser->buffer, single ? '\'' : '"'))
3288− break;
3289−
3290− /* Consume blank characters. */
3291−
3292− if (!CACHE(parser, 1)) goto error;
3293−
3294− while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
3295− {
3296− if (IS_BLANK(parser->buffer))
3297− {
3298− /* Consume a space or a tab character. */
3299−
3300− if (!leading_blanks) {
3301− if (!READ(parser, whitespaces)) goto error;
3302− }
3303− else {
3304− SKIP(parser);
3305− }
3306− }
3307− else
3308− {
3309− if (!CACHE(parser, 2)) goto error;
3310−
3311− /* Check if it is a first line break. */
3312−
3313− if (!leading_blanks)
3314− {
3315− CLEAR(parser, whitespaces);
3316− if (!READ_LINE(parser, leading_break)) goto error;
3317− leading_blanks = 1;
3318− }
3319− else
3320− {
3321− if (!READ_LINE(parser, trailing_breaks)) goto error;
3322− }
3323− }
3324− if (!CACHE(parser, 1)) goto error;
3325− }
3326−
3327− /* Join the whitespaces or fold line breaks. */
3328−
3329− if (leading_blanks)
3330− {
3331− /* Do we need to fold line breaks? */
3332−
3333− if (leading_break.start[0] == '\n') {
3334− if (trailing_breaks.start[0] == '\0') {
3335− if (!STRING_EXTEND(parser, string)) goto error;
3336− *(string.pointer++) = ' ';
3337− }
3338− else {
3339− if (!JOIN(parser, string, trailing_breaks)) goto error;
3340− CLEAR(parser, trailing_breaks);
3341− }
3342− CLEAR(parser, leading_break);
3343− }
3344− else {
3345− if (!JOIN(parser, string, leading_break)) goto error;
3346− if (!JOIN(parser, string, trailing_breaks)) goto error;
3347− CLEAR(parser, leading_break);
3348− CLEAR(parser, trailing_breaks);
3349− }
3350− }
3351− else
3352− {
3353− if (!JOIN(parser, string, whitespaces)) goto error;
3354− CLEAR(parser, whitespaces);
3355− }
3356− }
3357−
3358− /* Eat the right quote. */
3359−
3360− SKIP(parser);
3361−
3362− end_mark = parser->mark;
3363−
3364− /* Create a token. */
3365−
3366− SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
3367− single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE,
3368− start_mark, end_mark);
3369−
3370− STRING_DEL(parser, leading_break);
3371− STRING_DEL(parser, trailing_breaks);
3372− STRING_DEL(parser, whitespaces);
3373−
3374− return 1;
3375−
3376−error:
3377− STRING_DEL(parser, string);
3378− STRING_DEL(parser, leading_break);
3379− STRING_DEL(parser, trailing_breaks);
3380− STRING_DEL(parser, whitespaces);
3381−
3382− return 0;
3383−}
3384−
3385−/*
3386− * Scan a plain scalar.
3387− */
3388−
3389−static int
3390−yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
3391−{
3392− yaml_mark_t start_mark;
3393− yaml_mark_t end_mark;
3394− yaml_string_t string = NULL_STRING;
3395− yaml_string_t leading_break = NULL_STRING;
3396− yaml_string_t trailing_breaks = NULL_STRING;
3397− yaml_string_t whitespaces = NULL_STRING;
3398− int leading_blanks = 0;
3399− int indent = parser->indent+1;
3400−
3401− if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error;
3402− if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error;
3403− if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error;
3404− if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error;
3405−
3406− start_mark = end_mark = parser->mark;
3407−
3408− /* Consume the content of the plain scalar. */
3409−
3410− while (1)
3411− {
3412− /* Check for a document indicator. */
3413−
3414− if (!CACHE(parser, 4)) goto error;
3415−
3416− if (parser->mark.column == 0 &&
3417− ((CHECK_AT(parser->buffer, '-', 0) &&
3418− CHECK_AT(parser->buffer, '-', 1) &&
3419− CHECK_AT(parser->buffer, '-', 2)) ||
3420− (CHECK_AT(parser->buffer, '.', 0) &&
3421− CHECK_AT(parser->buffer, '.', 1) &&
3422− CHECK_AT(parser->buffer, '.', 2))) &&
3423− IS_BLANKZ_AT(parser->buffer, 3)) break;
3424−
3425− /* Check for a comment. */
3426−
3427− if (CHECK(parser->buffer, '#'))
3428− break;
3429−
3430− /* Consume non-blank characters. */
3431−
3432− while (!IS_BLANKZ(parser->buffer))
3433− {
3434− /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */
3435−
3436− if (parser->flow_level
3437− && CHECK(parser->buffer, ':')
3438− && !IS_BLANKZ_AT(parser->buffer, 1)) {
3439− yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
3440− start_mark, "found unexpected ':'");
3441− goto error;
3442− }
3443−
3444− /* Check for indicators that may end a plain scalar. */
3445−
3446− if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1))
3447− || (parser->flow_level &&
3448− (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':')
3449− || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[')
3450− || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
3451− || CHECK(parser->buffer, '}'))))
3452− break;
3453−
3454− /* Check if we need to join whitespaces and breaks. */
3455−
3456− if (leading_blanks || whitespaces.start != whitespaces.pointer)
3457− {
3458− if (leading_blanks)
3459− {
3460− /* Do we need to fold line breaks? */
3461−
3462− if (leading_break.start[0] == '\n') {
3463− if (trailing_breaks.start[0] == '\0') {
3464− if (!STRING_EXTEND(parser, string)) goto error;
3465− *(string.pointer++) = ' ';
3466− }
3467− else {
3468− if (!JOIN(parser, string, trailing_breaks)) goto error;
3469− CLEAR(parser, trailing_breaks);
3470− }
3471− CLEAR(parser, leading_break);
3472− }
3473− else {
3474− if (!JOIN(parser, string, leading_break)) goto error;
3475− if (!JOIN(parser, string, trailing_breaks)) goto error;
3476− CLEAR(parser, leading_break);
3477− CLEAR(parser, trailing_breaks);
3478− }
3479−
3480− leading_blanks = 0;
3481− }
3482− else
3483− {
3484− if (!JOIN(parser, string, whitespaces)) goto error;
3485− CLEAR(parser, whitespaces);
3486− }
3487− }
3488−
3489− /* Copy the character. */
3490−
3491− if (!READ(parser, string)) goto error;
3492−
3493− end_mark = parser->mark;
3494−
3495− if (!CACHE(parser, 2)) goto error;
3496− }
3497−
3498− /* Is it the end? */
3499−
3500− if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)))
3501− break;
3502−
3503− /* Consume blank characters. */
3504−
3505− if (!CACHE(parser, 1)) goto error;
3506−
3507− while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))
3508− {
3509− if (IS_BLANK(parser->buffer))
3510− {
3511− /* Check for tab character that abuse intendation. */
3512−
3513− if (leading_blanks && (int)parser->mark.column < indent
3514− && IS_TAB(parser->buffer)) {
3515− yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
3516− start_mark, "found a tab character that violate intendation");
3517− goto error;
3518− }
3519−
3520− /* Consume a space or a tab character. */
3521−
3522− if (!leading_blanks) {
3523− if (!READ(parser, whitespaces)) goto error;
3524− }
3525− else {
3526− SKIP(parser);
3527− }
3528− }
3529− else
3530− {
3531− if (!CACHE(parser, 2)) goto error;
3532−
3533− /* Check if it is a first line break. */
3534−
3535− if (!leading_blanks)
3536− {
3537− CLEAR(parser, whitespaces);
3538− if (!READ_LINE(parser, leading_break)) goto error;
3539− leading_blanks = 1;
3540− }
3541− else
3542− {
3543− if (!READ_LINE(parser, trailing_breaks)) goto error;
3544− }
3545− }
3546− if (!CACHE(parser, 1)) goto error;
3547− }
3548−
3549− /* Check intendation level. */
3550−
3551− if (!parser->flow_level && (int)parser->mark.column < indent)
3552− break;
3553− }
3554−
3555− /* Create a token. */
3556−
3557− SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start,
3558− YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark);
3559−
3560− /* Note that we change the 'simple_key_allowed' flag. */
3561−
3562− if (leading_blanks) {
3563− parser->simple_key_allowed = 1;
3564− }
3565−
3566− STRING_DEL(parser, leading_break);
3567− STRING_DEL(parser, trailing_breaks);
3568− STRING_DEL(parser, whitespaces);
3569−
3570− return 1;
3571−
3572−error:
3573− STRING_DEL(parser, string);
3574− STRING_DEL(parser, leading_break);
3575− STRING_DEL(parser, trailing_breaks);
3576− STRING_DEL(parser, whitespaces);
3577−
3578− return 0;
3579−}
3580−
Text/Libyaml.hs → libyaml/src/Text/Libyaml.hsrenamed+348−150
@@ -7,21 +7,37 @@
77{-# LANGUAGE RankNTypes #-}
88{-# LANGUAGE CPP #-}
99{-# LANGUAGE TypeFamilies #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
1011
1112-- | Low-level, streaming YAML interface. For a higher-level interface, see
1213-- "Data.Yaml".
1314module Text.Libyaml
1415 ( -- * The event stream
15− Event (..)
16+ MarkedEvent(..)
17+ , Event (..)
1618 , Style (..)
19+ , SequenceStyle (..)
20+ , MappingStyle (..)
1721 , Tag (..)
1822 , AnchorName
1923 , Anchor
2024 -- * Encoding and decoding
2125 , encode
26+ , encodeWith
2227 , decode
28+ , decodeMarked
2329 , encodeFile
2430 , decodeFile
31+ , decodeFileMarked
32+ , encodeFileWith
33+ , FormatOptions
34+ , defaultFormatOptions
35+ , setWidth
36+ , setTagRendering
37+ , renderScalarTags
38+ , renderAllTags
39+ , renderNoTags
40+ , renderUriTags
2541 -- * Error handling
2642 , YamlException (..)
2743 , YamlMark (..)
@@ -29,6 +45,7 @@ module Text.Libyaml
2945
3046import Prelude hiding (pi)
3147
48+import Data.Bits ((.|.))
3249import Foreign.C
3350import Foreign.Ptr
3451import Foreign.ForeignPtr
@@ -36,6 +53,7 @@ import Foreign.ForeignPtr
3653import Foreign.ForeignPtr.Unsafe
3754#endif
3855import Foreign.Marshal.Alloc
56+import qualified System.Posix.Internals as Posix
3957
4058#if !MIN_VERSION_base(4,8,0)
4159import Control.Applicative
@@ -47,12 +65,16 @@ import Control.Monad.Trans.Resource
4765import Data.Conduit hiding (Source, Sink, Conduit)
4866import Data.Data
4967
50−import Data.ByteString (ByteString, packCStringLen)
51−import qualified Data.ByteString
68+import Data.ByteString (ByteString, packCString, packCStringLen)
5269import qualified Data.ByteString.Char8 as B8
5370import qualified Data.ByteString.Internal as B
5471import qualified Data.ByteString.Unsafe as BU
5572
73+#if WINDOWS && __GLASGOW_HASKELL__ >= 806
74+import System.Directory (removeFile)
75+import qualified Control.Exception
76+#endif
77+
5678data Event =
5779 EventStreamStart
5880 | EventStreamEnd
@@ -60,12 +82,23 @@ data Event =
6082 | EventDocumentEnd
6183 | EventAlias !AnchorName
6284 | EventScalar !ByteString !Tag !Style !Anchor
63− | EventSequenceStart !Anchor
85+ | EventSequenceStart !Tag !SequenceStyle !Anchor
6486 | EventSequenceEnd
65− | EventMappingStart !Anchor
87+ | EventMappingStart !Tag !MappingStyle !Anchor
6688 | EventMappingEnd
6789 deriving (Show, Eq)
6890
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+--
69102data Style = Any
70103 | Plain
71104 | SingleQuoted
@@ -75,6 +108,18 @@ data Style = Any
75108 | PlainNoTag
76109 deriving (Show, Read, Eq, Enum, Bounded, Ord, Data, Typeable)
77110
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+
78123data Tag = StrTag
79124 | FloatTag
80125 | NullTag
@@ -87,6 +132,11 @@ data Tag = StrTag
87132 | NoTag
88133 deriving (Show, Eq, Read, Data, Typeable)
89134
135+tagSuppressed :: Tag -> Bool
136+tagSuppressed (NoTag) = True
137+tagSuppressed (UriTag "") = True
138+tagSuppressed _ = False
139+
90140type AnchorName = String
91141type Anchor = Maybe AnchorName
92142
@@ -144,20 +194,41 @@ foreign import ccall unsafe "yaml_parser_set_input_file"
144194 -> File
145195 -> IO ()
146196
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+
147215data FileStruct
148216type File = Ptr FileStruct
149217
150−foreign import ccall unsafe "fopen"
151− c_fopen :: Ptr CChar
152− -> Ptr CChar
153− -> IO File
154−
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
155226foreign import ccall unsafe "fclose"
156227 c_fclose :: File
157− -> IO ()
228+ -> IO CInt
158229
159230foreign import ccall unsafe "fclose_helper"
160− c_fclose_helper :: File -> IO ()
231+ c_fclose_helper :: File -> IO CInt
161232
162233foreign import ccall unsafe "yaml_parser_parse"
163234 c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
@@ -171,14 +242,8 @@ foreign import ccall "get_parser_error_problem"
171242foreign import ccall "get_parser_error_context"
172243 c_get_parser_error_context :: Parser -> IO (Ptr CUChar)
173244
174−foreign import ccall unsafe "get_parser_error_index"
175− c_get_parser_error_index :: Parser -> IO CULong
176−
177−foreign import ccall unsafe "get_parser_error_line"
178− c_get_parser_error_line :: Parser -> IO CULong
179−
180−foreign import ccall unsafe "get_parser_error_column"
181− c_get_parser_error_column :: Parser -> IO CULong
245+foreign import ccall unsafe "get_parser_error_mark"
246+ c_get_parser_error_mark :: Parser -> IO MarkRaw
182247
183248makeString :: MonadIO m => (a -> m (Ptr CUChar)) -> a -> m String
184249makeString f a = do
@@ -203,6 +268,12 @@ data EventType = YamlNoEvent
203268foreign import ccall unsafe "get_event_type"
204269 c_get_event_type :: EventRaw -> IO CInt
205270
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+
206277foreign import ccall unsafe "get_scalar_value"
207278 c_get_scalar_value :: EventRaw -> IO (Ptr CUChar)
208279
@@ -212,9 +283,6 @@ foreign import ccall unsafe "get_scalar_length"
212283foreign import ccall unsafe "get_scalar_tag"
213284 c_get_scalar_tag :: EventRaw -> IO (Ptr CUChar)
214285
215−foreign import ccall unsafe "get_scalar_tag_len"
216− c_get_scalar_tag_len :: EventRaw -> IO CULong
217−
218286foreign import ccall unsafe "get_scalar_style"
219287 c_get_scalar_style :: EventRaw -> IO CInt
220288
@@ -224,16 +292,43 @@ foreign import ccall unsafe "get_scalar_anchor"
224292foreign import ccall unsafe "get_sequence_start_anchor"
225293 c_get_sequence_start_anchor :: EventRaw -> IO CString
226294
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+
227301foreign import ccall unsafe "get_mapping_start_anchor"
228302 c_get_mapping_start_anchor :: EventRaw -> IO CString
229303
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+
230310foreign import ccall unsafe "get_alias_anchor"
231311 c_get_alias_anchor :: EventRaw -> IO CString
232312
233−getEvent :: EventRaw -> IO (Maybe Event)
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)
234327getEvent er = do
235328 et <- c_get_event_type er
236− case toEnum $ fromEnum et of
329+ startMark <- c_get_start_mark er >>= getMark
330+ endMark <- c_get_end_mark er >>= getMark
331+ event <- case toEnum $ fromEnum et of
237332 YamlNoEvent -> return Nothing
238333 YamlStreamStartEvent -> return $ Just EventStreamStart
239334 YamlStreamEndEvent -> return $ Just EventStreamEnd
@@ -248,38 +343,26 @@ getEvent er = do
248343 YamlScalarEvent -> do
249344 yvalue <- c_get_scalar_value er
250345 ylen <- c_get_scalar_length er
251− ytag <- c_get_scalar_tag er
252− ytag_len <- c_get_scalar_tag_len er
253− ystyle <- c_get_scalar_style er
254− let ytag_len' = fromEnum ytag_len
255346 let yvalue' = castPtr yvalue
256− let ytag' = castPtr ytag
257347 let ylen' = fromEnum ylen
258348 bs <- packCStringLen (yvalue', ylen')
259− tagbs <-
260− if ytag_len' == 0
261− then return Data.ByteString.empty
262− else packCStringLen (ytag', ytag_len')
263− let style = toEnum $ fromEnum ystyle
264− yanchor <- c_get_scalar_anchor er
265− anchor <- if yanchor == nullPtr
266− then return Nothing
267− else Just <$> peekCString yanchor
268− return $ Just $ EventScalar bs (bsToTag tagbs) style anchor
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
269353 YamlSequenceStartEvent -> do
270− yanchor <- c_get_sequence_start_anchor er
271− anchor <- if yanchor == nullPtr
272− then return Nothing
273− else Just <$> peekCString yanchor
274− return $ Just $ EventSequenceStart anchor
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
275358 YamlSequenceEndEvent -> return $ Just EventSequenceEnd
276359 YamlMappingStartEvent -> do
277− yanchor <- c_get_mapping_start_anchor er
278− anchor <- if yanchor == nullPtr
279− then return Nothing
280− else Just <$> peekCString yanchor
281− return $ Just $ EventMappingStart anchor
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
282364 YamlMappingEndEvent -> return $ Just EventMappingEnd
365+ return $ (\e -> MarkedEvent e startMark endMark) <$> event
283366
284367-- Emitter
285368
@@ -319,6 +402,9 @@ foreign import ccall unsafe "yaml_emitter_set_unicode"
319402foreign import ccall unsafe "yaml_emitter_set_output_file"
320403 c_yaml_emitter_set_output_file :: Emitter -> File -> IO ()
321404
405+foreign import ccall unsafe "yaml_emitter_set_width"
406+ c_yaml_emitter_set_width :: Emitter -> CInt -> IO ()
407+
322408foreign import ccall unsafe "yaml_emitter_emit"
323409 c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
324410
@@ -376,8 +462,8 @@ foreign import ccall unsafe "yaml_alias_event_initialize"
376462 -> Ptr CUChar
377463 -> IO CInt
378464
379−toEventRaw :: Event -> (EventRaw -> IO a) -> IO a
380−toEventRaw e f = allocaBytes eventSize $ \er -> do
465+toEventRaw :: FormatOptions -> Event -> (EventRaw -> IO a) -> IO a
466+toEventRaw opts e f = allocaBytes eventSize $ \er -> do
381467 ret <- case e of
382468 EventStreamStart ->
383469 c_yaml_stream_start_event_initialize
@@ -395,13 +481,13 @@ toEventRaw e f = allocaBytes eventSize $ \er -> do
395481 len' = fromIntegral len :: CInt
396482 let thetag' = tagToString thetag
397483 withCString thetag' $ \tag' -> do
398− let (pi, style) =
399− case style0 of
400− PlainNoTag -> (1, Plain)
401− x -> (0, x)
484+ let pi0 = tagsImplicit e
485+ (pi, style) =
486+ case style0 of
487+ PlainNoTag -> (1, Plain)
488+ x -> (pi0, x)
402489 style' = toEnum $ fromEnum style
403490 tagP = castPtr tag'
404− qi = if null thetag' then 1 else 0
405491 case anchor of
406492 Nothing ->
407493 c_yaml_scalar_event_initialize
@@ -411,7 +497,7 @@ toEventRaw e f = allocaBytes eventSize $ \er -> do
411497 value' -- value
412498 len' -- length
413499 pi -- plain_implicit
414− qi -- quoted_implicit
500+ pi -- quoted_implicit
415501 style' -- style
416502 Just anchor' ->
417503 withCString anchor' $ \anchorP' -> do
@@ -423,42 +509,50 @@ toEventRaw e f = allocaBytes eventSize $ \er -> do
423509 value' -- value
424510 len' -- length
425511 0 -- plain_implicit
426− qi -- quoted_implicit
512+ pi -- quoted_implicit
427513 style' -- style
428− EventSequenceStart Nothing ->
429− c_yaml_sequence_start_event_initialize
430− er
431− nullPtr
432− nullPtr
433− 1
434− 0 -- YAML_ANY_SEQUENCE_STYLE
435− EventSequenceStart (Just anchor) ->
436− withCString anchor $ \anchor' -> do
437− let anchorP = castPtr anchor'
514+ EventSequenceStart tag style Nothing ->
515+ withCString (tagToString tag) $ \tag' -> do
516+ let tagP = castPtr tag'
438517 c_yaml_sequence_start_event_initialize
439− er
440− anchorP
441− nullPtr
442− 1
443− 0 -- YAML_ANY_SEQUENCE_STYLE
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)
444534 EventSequenceEnd ->
445535 c_yaml_sequence_end_event_initialize er
446− EventMappingStart Nothing ->
447− c_yaml_mapping_start_event_initialize
448− er
449− nullPtr
450− nullPtr
451− 1
452− 0 -- YAML_ANY_SEQUENCE_STYLE
453− EventMappingStart (Just anchor) ->
454− withCString anchor $ \anchor' -> do
455− let anchorP = castPtr anchor'
536+ EventMappingStart tag style Nothing ->
537+ withCString (tagToString tag) $ \tag' -> do
538+ let tagP = castPtr tag'
456539 c_yaml_mapping_start_event_initialize
457540 er
458− anchorP
459541 nullPtr
460− 1
461− 0 -- YAML_ANY_SEQUENCE_STYLE
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)
462556 EventMappingEnd ->
463557 c_yaml_mapping_end_event_initialize er
464558 EventAlias anchor ->
@@ -469,19 +563,29 @@ toEventRaw e f = allocaBytes eventSize $ \er -> do
469563 anchorP
470564 unless (ret == 1) $ throwIO $ ToEventRawException ret
471565 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
472571
473572newtype ToEventRawException = ToEventRawException CInt
474573 deriving (Show, Typeable)
475574instance Exception ToEventRawException
476575
477−decode :: MonadResource m => B.ByteString
478−#if MIN_VERSION_conduit(1, 0, 0)
479− -> Producer m Event
480−#else
481− -> GSource m Event
482−#endif
483−decode bs | B8.null bs = return ()
484−decode bs =
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 =
485589 bracketP alloc cleanup (runParser . fst)
486590 where
487591 alloc = mask_ $ do
@@ -503,13 +607,36 @@ decode bs =
503607 c_yaml_parser_delete ptr
504608 free ptr
505609
506−decodeFile :: MonadResource m => FilePath
507−#if MIN_VERSION_conduit(1, 0, 0)
508− -> Producer m Event
509−#else
510− -> GSource m Event
511−#endif
512−decodeFile file =
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 =
513640 bracketP alloc cleanup (runParser . fst)
514641 where
515642 alloc = mask_ $ do
@@ -521,12 +648,9 @@ decodeFile file =
521648 free ptr
522649 throwIO $ YamlException "Yaml out of memory"
523650 else do
524− file' <- liftIO
525− $ withCString file $ \file' -> withCString "r" $ \r' ->
526− c_fopen file' r'
651+ file' <- openFile file read_flags "r"
527652 if file' == nullPtr
528653 then do
529− c_fclose_helper file'
530654 c_yaml_parser_delete ptr
531655 free ptr
532656 throwIO $ YamlException
@@ -535,16 +659,12 @@ decodeFile file =
535659 c_yaml_parser_set_input_file ptr file'
536660 return (ptr, file')
537661 cleanup (ptr, file') = do
538− c_fclose_helper file'
662+ res <- c_fclose_helper file'
663+ when (res /= 0) $ throwIO $ YamlException $ "could not close file: " ++ file
539664 c_yaml_parser_delete ptr
540665 free ptr
541666
542−runParser :: MonadResource m => Parser
543−#if MIN_VERSION_conduit(1, 0, 0)
544− -> Producer m Event
545−#else
546− -> GSource m Event
547−#endif
667+runParser :: MonadResource m => Parser -> ConduitM i MarkedEvent m ()
548668runParser parser = do
549669 e <- liftIO $ parserParseOne' parser
550670 case e of
@@ -553,7 +673,7 @@ runParser parser = do
553673 Right (Just ev) -> yield ev >> runParser parser
554674
555675parserParseOne' :: Parser
556− -> IO (Either YamlException (Maybe Event))
676+ -> IO (Either YamlException (Maybe MarkedEvent))
557677parserParseOne' parser = allocaBytes eventSize $ \er -> do
558678 res <- liftIO $ c_yaml_parser_parse parser er
559679 flip finally (c_yaml_event_delete er) $
@@ -561,21 +681,92 @@ parserParseOne' parser = allocaBytes eventSize $ \er -> do
561681 then do
562682 problem <- makeString c_get_parser_error_problem parser
563683 context <- makeString c_get_parser_error_context parser
564− index <- c_get_parser_error_index parser
565− line <- c_get_parser_error_line parser
566− column <- c_get_parser_error_column parser
567− let problemMark = YamlMark (fromIntegral index) (fromIntegral line) (fromIntegral column)
684+ problemMark <- c_get_parser_error_mark parser >>= getMark
568685 return $ Left $ YamlParseException problem context problemMark
569686 else Right <$> getEvent er
570687
571−encode :: MonadResource m
572−#if MIN_VERSION_conduit(1, 0, 0)
573− => Consumer Event m ByteString
574−#else
575− => GSink Event m ByteString
576−#endif
577−encode =
578− runEmitter alloc close
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
579770 where
580771 alloc emitter = do
581772 fbuf <- mallocForeignPtrBytes bufferSize
@@ -585,23 +776,35 @@ encode =
585776 close _ fbuf = withForeignPtr fbuf $ \b -> do
586777 ptr' <- c_get_buffer_buff b
587778 len <- c_get_buffer_used b
588− fptr <- newForeignPtr_ $ castPtr ptr'
779+ fptr <- newForeignPtr finalizerFree $ castPtr ptr'
589780 return $ B.fromForeignPtr fptr 0 $ fromIntegral len
590781
782+
591783encodeFile :: MonadResource m
592784 => FilePath
593−#if MIN_VERSION_conduit(1, 0, 0)
594− -> Consumer Event m ()
595−#else
596− -> GInfSink Event m
597−#endif
598−encodeFile filePath =
599− bracketP getFile c_fclose $ \file -> runEmitter (alloc file) (\u _ -> return u)
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)
600796 where
797+ cleanup file = do
798+ res <- c_fclose file
799+ when (res /= 0) $ throwIO $ YamlException $ "could not close file: " ++ filePath
800+
601801 getFile = do
602− file <- withCString filePath $
603− \filePath' -> withCString "w" $
604− \w' -> c_fopen filePath' w'
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"
605808 if file == nullPtr
606809 then throwIO $ YamlException $ "could not open file for write: " ++ filePath
607810 else return file
@@ -609,15 +812,11 @@ encodeFile filePath =
609812 alloc file emitter = c_yaml_emitter_set_output_file emitter file
610813
611814runEmitter :: MonadResource m
612− => (Emitter -> IO a) -- ^ alloc
613−#if MIN_VERSION_conduit(1, 0, 0)
815+ => FormatOptions
816+ -> (Emitter -> IO a) -- ^ alloc
614817 -> (() -> a -> IO b) -- ^ close
615− -> Consumer Event m b
616−#else
617− -> (u -> a -> IO b) -- ^ close
618− -> Pipe l Event o u m b
619−#endif
620−runEmitter allocI closeI =
818+ -> ConduitM Event o m b
819+runEmitter opts allocI closeI =
621820 bracketP alloc cleanup go
622821 where
623822 alloc = mask_ $ do
@@ -627,6 +826,9 @@ runEmitter allocI closeI =
627826#ifndef __NO_UNICODE__
628827 c_yaml_emitter_set_unicode emitter 1
629828#endif
829+ c_yaml_emitter_set_width emitter $ case formatOptionsWidth opts of
830+ Nothing -> -1 --infinite
831+ Just width -> fromIntegral width
630832 a <- allocI emitter
631833 return (emitter, a)
632834 cleanup (emitter, _) = do
@@ -636,14 +838,10 @@ runEmitter allocI closeI =
636838 go (emitter, a) =
637839 loop
638840 where
639−#if MIN_VERSION_conduit(1, 0, 0)
640841 loop = await >>= maybe (close ()) push
641−#else
642− loop = awaitE >>= either close push
643−#endif
644842
645843 push e = do
646− _ <- liftIO $ toEventRaw e $ c_yaml_emitter_emit emitter
844+ _ <- liftIO $ toEventRaw opts e $ c_yaml_emitter_emit emitter
647845 loop
648846 close u = liftIO $ closeI u a
649847
libyaml/writer.cdeleted−141
@@ -1,141 +0,0 @@
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−
libyaml/yaml.hdeleted−1973
@@ -1,1973 +0,0 @@
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−#if defined(__MINGW32__)
30−# define YAML_DECLARE(type) type
31−#elif defined(_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−
libyaml/yaml_private.hdeleted−661
@@ -1,661 +0,0 @@
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−#include <stddef.h>
11−
12−#ifndef _MSC_VER
13−#include <stdint.h>
14−#else
15−#ifdef _WIN64
16−#define PTRDIFF_MAX _I64_MAX
17−#else
18−#define PTRDIFF_MAX INT_MAX
19−#endif
20−#endif
21−
22−/*
23− * Memory management.
24− */
25−
26−YAML_DECLARE(void *)
27−yaml_malloc(size_t size);
28−
29−YAML_DECLARE(void *)
30−yaml_realloc(void *ptr, size_t size);
31−
32−YAML_DECLARE(void)
33−yaml_free(void *ptr);
34−
35−YAML_DECLARE(yaml_char_t *)
36−yaml_strdup(const yaml_char_t *);
37−
38−/*
39− * Reader: Ensure that the buffer contains at least `length` characters.
40− */
41−
42−YAML_DECLARE(int)
43−yaml_parser_update_buffer(yaml_parser_t *parser, size_t length);
44−
45−/*
46− * Scanner: Ensure that the token stack contains at least one token ready.
47− */
48−
49−YAML_DECLARE(int)
50−yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
51−
52−/*
53− * The size of the input raw buffer.
54− */
55−
56−#define INPUT_RAW_BUFFER_SIZE 16384
57−
58−/*
59− * The size of the input buffer.
60− *
61− * It should be possible to decode the whole raw buffer.
62− */
63−
64−#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3)
65−
66−/*
67− * The size of the output buffer.
68− */
69−
70−#define OUTPUT_BUFFER_SIZE 16384
71−
72−/*
73− * The size of the output raw buffer.
74− *
75− * It should be possible to encode the whole output buffer.
76− */
77−
78−#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
79−
80−/*
81− * The size of other stacks and queues.
82− */
83−
84−#define INITIAL_STACK_SIZE 16
85−#define INITIAL_QUEUE_SIZE 16
86−#define INITIAL_STRING_SIZE 16
87−
88−/*
89− * Buffer management.
90− */
91−
92−#define BUFFER_INIT(context,buffer,size) \
93− (((buffer).start = yaml_malloc(size)) ? \
94− ((buffer).last = (buffer).pointer = (buffer).start, \
95− (buffer).end = (buffer).start+(size), \
96− 1) : \
97− ((context)->error = YAML_MEMORY_ERROR, \
98− 0))
99−
100−#define BUFFER_DEL(context,buffer) \
101− (yaml_free((buffer).start), \
102− (buffer).start = (buffer).pointer = (buffer).end = 0)
103−
104−/*
105− * String management.
106− */
107−
108−typedef struct {
109− yaml_char_t *start;
110− yaml_char_t *end;
111− yaml_char_t *pointer;
112−} yaml_string_t;
113−
114−YAML_DECLARE(int)
115−yaml_string_extend(yaml_char_t **start,
116− yaml_char_t **pointer, yaml_char_t **end);
117−
118−YAML_DECLARE(int)
119−yaml_string_join(
120− yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
121− yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end);
122−
123−#define NULL_STRING { NULL, NULL, NULL }
124−
125−#define STRING(string,length) { (string), (string)+(length), (string) }
126−
127−#define STRING_ASSIGN(value,string,length) \
128− ((value).start = (string), \
129− (value).end = (string)+(length), \
130− (value).pointer = (string))
131−
132−#define STRING_INIT(context,string,size) \
133− (((string).start = yaml_malloc(size)) ? \
134− ((string).pointer = (string).start, \
135− (string).end = (string).start+(size), \
136− memset((string).start, 0, (size)), \
137− 1) : \
138− ((context)->error = YAML_MEMORY_ERROR, \
139− 0))
140−
141−#define STRING_DEL(context,string) \
142− (yaml_free((string).start), \
143− (string).start = (string).pointer = (string).end = 0)
144−
145−#define STRING_EXTEND(context,string) \
146− (((string).pointer+5 < (string).end) \
147− || yaml_string_extend(&(string).start, \
148− &(string).pointer, &(string).end))
149−
150−#define CLEAR(context,string) \
151− ((string).pointer = (string).start, \
152− memset((string).start, 0, (string).end-(string).start))
153−
154−#define JOIN(context,string_a,string_b) \
155− ((yaml_string_join(&(string_a).start, &(string_a).pointer, \
156− &(string_a).end, &(string_b).start, \
157− &(string_b).pointer, &(string_b).end)) ? \
158− ((string_b).pointer = (string_b).start, \
159− 1) : \
160− ((context)->error = YAML_MEMORY_ERROR, \
161− 0))
162−
163−/*
164− * String check operations.
165− */
166−
167−/*
168− * Check the octet at the specified position.
169− */
170−
171−#define CHECK_AT(string,octet,offset) \
172− ((string).pointer[offset] == (yaml_char_t)(octet))
173−
174−/*
175− * Check the current octet in the buffer.
176− */
177−
178−#define CHECK(string,octet) CHECK_AT((string),(octet),0)
179−
180−/*
181− * Check if the character at the specified position is an alphabetical
182− * character, a digit, '_', or '-'.
183− */
184−
185−#define IS_ALPHA_AT(string,offset) \
186− (((string).pointer[offset] >= (yaml_char_t) '0' && \
187− (string).pointer[offset] <= (yaml_char_t) '9') || \
188− ((string).pointer[offset] >= (yaml_char_t) 'A' && \
189− (string).pointer[offset] <= (yaml_char_t) 'Z') || \
190− ((string).pointer[offset] >= (yaml_char_t) 'a' && \
191− (string).pointer[offset] <= (yaml_char_t) 'z') || \
192− (string).pointer[offset] == '_' || \
193− (string).pointer[offset] == '-')
194−
195−#define IS_ALPHA(string) IS_ALPHA_AT((string),0)
196−
197−/*
198− * Check if the character at the specified position is a digit.
199− */
200−
201−#define IS_DIGIT_AT(string,offset) \
202− (((string).pointer[offset] >= (yaml_char_t) '0' && \
203− (string).pointer[offset] <= (yaml_char_t) '9'))
204−
205−#define IS_DIGIT(string) IS_DIGIT_AT((string),0)
206−
207−/*
208− * Get the value of a digit.
209− */
210−
211−#define AS_DIGIT_AT(string,offset) \
212− ((string).pointer[offset] - (yaml_char_t) '0')
213−
214−#define AS_DIGIT(string) AS_DIGIT_AT((string),0)
215−
216−/*
217− * Check if the character at the specified position is a hex-digit.
218− */
219−
220−#define IS_HEX_AT(string,offset) \
221− (((string).pointer[offset] >= (yaml_char_t) '0' && \
222− (string).pointer[offset] <= (yaml_char_t) '9') || \
223− ((string).pointer[offset] >= (yaml_char_t) 'A' && \
224− (string).pointer[offset] <= (yaml_char_t) 'F') || \
225− ((string).pointer[offset] >= (yaml_char_t) 'a' && \
226− (string).pointer[offset] <= (yaml_char_t) 'f'))
227−
228−#define IS_HEX(string) IS_HEX_AT((string),0)
229−
230−/*
231− * Get the value of a hex-digit.
232− */
233−
234−#define AS_HEX_AT(string,offset) \
235− (((string).pointer[offset] >= (yaml_char_t) 'A' && \
236− (string).pointer[offset] <= (yaml_char_t) 'F') ? \
237− ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \
238− ((string).pointer[offset] >= (yaml_char_t) 'a' && \
239− (string).pointer[offset] <= (yaml_char_t) 'f') ? \
240− ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \
241− ((string).pointer[offset] - (yaml_char_t) '0'))
242−
243−#define AS_HEX(string) AS_HEX_AT((string),0)
244−
245−/*
246− * Check if the character is ASCII.
247− */
248−
249−#define IS_ASCII_AT(string,offset) \
250− ((string).pointer[offset] <= (yaml_char_t) '\x7F')
251−
252−#define IS_ASCII(string) IS_ASCII_AT((string),0)
253−
254−/*
255− * Check if the character can be printed unescaped.
256− */
257−
258−#define IS_PRINTABLE_AT(string,offset) \
259− (((string).pointer[offset] == 0x0A) /* . == #x0A */ \
260− || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \
261− && (string).pointer[offset] <= 0x7E) \
262− || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \
263− && (string).pointer[offset+1] >= 0xA0) \
264− || ((string).pointer[offset] > 0xC2 \
265− && (string).pointer[offset] < 0xED) \
266− || ((string).pointer[offset] == 0xED \
267− && (string).pointer[offset+1] < 0xA0) \
268− || ((string).pointer[offset] == 0xEE) \
269− || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \
270− && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \
271− && (string).pointer[offset+2] == 0xBF) \
272− && !((string).pointer[offset+1] == 0xBF \
273− && ((string).pointer[offset+2] == 0xBE \
274− || (string).pointer[offset+2] == 0xBF))))
275−
276−#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0)
277−
278−/*
279− * Check if the character at the specified position is NUL.
280− */
281−
282−#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset))
283−
284−#define IS_Z(string) IS_Z_AT((string),0)
285−
286−/*
287− * Check if the character at the specified position is BOM.
288− */
289−
290−#define IS_BOM_AT(string,offset) \
291− (CHECK_AT((string),'\xEF',(offset)) \
292− && CHECK_AT((string),'\xBB',(offset)+1) \
293− && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */
294−
295−#define IS_BOM(string) IS_BOM_AT(string,0)
296−
297−/*
298− * Check if the character at the specified position is space.
299− */
300−
301−#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset))
302−
303−#define IS_SPACE(string) IS_SPACE_AT((string),0)
304−
305−/*
306− * Check if the character at the specified position is tab.
307− */
308−
309−#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset))
310−
311−#define IS_TAB(string) IS_TAB_AT((string),0)
312−
313−/*
314− * Check if the character at the specified position is blank (space or tab).
315− */
316−
317−#define IS_BLANK_AT(string,offset) \
318− (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset)))
319−
320−#define IS_BLANK(string) IS_BLANK_AT((string),0)
321−
322−/*
323− * Check if the character at the specified position is a line break.
324− */
325−
326−#define IS_BREAK_AT(string,offset) \
327− (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \
328− || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \
329− || (CHECK_AT((string),'\xC2',(offset)) \
330− && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \
331− || (CHECK_AT((string),'\xE2',(offset)) \
332− && CHECK_AT((string),'\x80',(offset)+1) \
333− && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \
334− || (CHECK_AT((string),'\xE2',(offset)) \
335− && CHECK_AT((string),'\x80',(offset)+1) \
336− && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */
337−
338−#define IS_BREAK(string) IS_BREAK_AT((string),0)
339−
340−#define IS_CRLF_AT(string,offset) \
341− (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1))
342−
343−#define IS_CRLF(string) IS_CRLF_AT((string),0)
344−
345−/*
346− * Check if the character is a line break or NUL.
347− */
348−
349−#define IS_BREAKZ_AT(string,offset) \
350− (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset)))
351−
352−#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0)
353−
354−/*
355− * Check if the character is a line break, space, or NUL.
356− */
357−
358−#define IS_SPACEZ_AT(string,offset) \
359− (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
360−
361−#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0)
362−
363−/*
364− * Check if the character is a line break, space, tab, or NUL.
365− */
366−
367−#define IS_BLANKZ_AT(string,offset) \
368− (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset)))
369−
370−#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0)
371−
372−/*
373− * Determine the width of the character.
374− */
375−
376−#define WIDTH_AT(string,offset) \
377− (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \
378− ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \
379− ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \
380− ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0)
381−
382−#define WIDTH(string) WIDTH_AT((string),0)
383−
384−/*
385− * Move the string pointer to the next character.
386− */
387−
388−#define MOVE(string) ((string).pointer += WIDTH((string)))
389−
390−/*
391− * Copy a character and move the pointers of both strings.
392− */
393−
394−#define COPY(string_a,string_b) \
395− ((*(string_b).pointer & 0x80) == 0x00 ? \
396− (*((string_a).pointer++) = *((string_b).pointer++)) : \
397− (*(string_b).pointer & 0xE0) == 0xC0 ? \
398− (*((string_a).pointer++) = *((string_b).pointer++), \
399− *((string_a).pointer++) = *((string_b).pointer++)) : \
400− (*(string_b).pointer & 0xF0) == 0xE0 ? \
401− (*((string_a).pointer++) = *((string_b).pointer++), \
402− *((string_a).pointer++) = *((string_b).pointer++), \
403− *((string_a).pointer++) = *((string_b).pointer++)) : \
404− (*(string_b).pointer & 0xF8) == 0xF0 ? \
405− (*((string_a).pointer++) = *((string_b).pointer++), \
406− *((string_a).pointer++) = *((string_b).pointer++), \
407− *((string_a).pointer++) = *((string_b).pointer++), \
408− *((string_a).pointer++) = *((string_b).pointer++)) : 0)
409−
410−/*
411− * Stack and queue management.
412− */
413−
414−YAML_DECLARE(int)
415−yaml_stack_extend(void **start, void **top, void **end);
416−
417−YAML_DECLARE(int)
418−yaml_queue_extend(void **start, void **head, void **tail, void **end);
419−
420−#define STACK_INIT(context,stack,size) \
421− (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
422− ((stack).top = (stack).start, \
423− (stack).end = (stack).start+(size), \
424− 1) : \
425− ((context)->error = YAML_MEMORY_ERROR, \
426− 0))
427−
428−#define STACK_DEL(context,stack) \
429− (yaml_free((stack).start), \
430− (stack).start = (stack).top = (stack).end = 0)
431−
432−#define STACK_EMPTY(context,stack) \
433− ((stack).start == (stack).top)
434−
435−#define STACK_LIMIT(context,stack,size) \
436− ((stack).top - (stack).start < (size) ? \
437− 1 : \
438− ((context)->error = YAML_MEMORY_ERROR, \
439− 0))
440−
441−#define PUSH(context,stack,value) \
442− (((stack).top != (stack).end \
443− || yaml_stack_extend((void **)&(stack).start, \
444− (void **)&(stack).top, (void **)&(stack).end)) ? \
445− (*((stack).top++) = value, \
446− 1) : \
447− ((context)->error = YAML_MEMORY_ERROR, \
448− 0))
449−
450−#define POP(context,stack) \
451− (*(--(stack).top))
452−
453−#define QUEUE_INIT(context,queue,size) \
454− (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
455− ((queue).head = (queue).tail = (queue).start, \
456− (queue).end = (queue).start+(size), \
457− 1) : \
458− ((context)->error = YAML_MEMORY_ERROR, \
459− 0))
460−
461−#define QUEUE_DEL(context,queue) \
462− (yaml_free((queue).start), \
463− (queue).start = (queue).head = (queue).tail = (queue).end = 0)
464−
465−#define QUEUE_EMPTY(context,queue) \
466− ((queue).head == (queue).tail)
467−
468−#define ENQUEUE(context,queue,value) \
469− (((queue).tail != (queue).end \
470− || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
471− (void **)&(queue).tail, (void **)&(queue).end)) ? \
472− (*((queue).tail++) = value, \
473− 1) : \
474− ((context)->error = YAML_MEMORY_ERROR, \
475− 0))
476−
477−#define DEQUEUE(context,queue) \
478− (*((queue).head++))
479−
480−#define QUEUE_INSERT(context,queue,index,value) \
481− (((queue).tail != (queue).end \
482− || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \
483− (void **)&(queue).tail, (void **)&(queue).end)) ? \
484− (memmove((queue).head+(index)+1,(queue).head+(index), \
485− ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \
486− *((queue).head+(index)) = value, \
487− (queue).tail++, \
488− 1) : \
489− ((context)->error = YAML_MEMORY_ERROR, \
490− 0))
491−
492−/*
493− * Token initializers.
494− */
495−
496−#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \
497− (memset(&(token), 0, sizeof(yaml_token_t)), \
498− (token).type = (token_type), \
499− (token).start_mark = (token_start_mark), \
500− (token).end_mark = (token_end_mark))
501−
502−#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \
503− (TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \
504− (token).data.stream_start.encoding = (token_encoding))
505−
506−#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \
507− (TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark)))
508−
509−#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \
510− (TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \
511− (token).data.alias.value = (token_value))
512−
513−#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \
514− (TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \
515− (token).data.anchor.value = (token_value))
516−
517−#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \
518− (TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \
519− (token).data.tag.handle = (token_handle), \
520− (token).data.tag.suffix = (token_suffix))
521−
522−#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \
523− (TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \
524− (token).data.scalar.value = (token_value), \
525− (token).data.scalar.length = (token_length), \
526− (token).data.scalar.style = (token_style))
527−
528−#define VERSION_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \
529− (TOKEN_INIT((token),YAML_VERSION_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
530− (token).data.version_directive.major = (token_major), \
531− (token).data.version_directive.minor = (token_minor))
532−
533−#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \
534− (TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \
535− (token).data.tag_directive.handle = (token_handle), \
536− (token).data.tag_directive.prefix = (token_prefix))
537−
538−/*
539− * Event initializers.
540− */
541−
542−#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \
543− (memset(&(event), 0, sizeof(yaml_event_t)), \
544− (event).type = (event_type), \
545− (event).start_mark = (event_start_mark), \
546− (event).end_mark = (event_end_mark))
547−
548−#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \
549− (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \
550− (event).data.stream_start.encoding = (event_encoding))
551−
552−#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \
553− (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark)))
554−
555−#define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \
556− event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \
557− (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \
558− (event).data.document_start.version_directive = (event_version_directive), \
559− (event).data.document_start.tag_directives.start = (event_tag_directives_start), \
560− (event).data.document_start.tag_directives.end = (event_tag_directives_end), \
561− (event).data.document_start.implicit = (event_implicit))
562−
563−#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \
564− (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \
565− (event).data.document_end.implicit = (event_implicit))
566−
567−#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \
568− (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \
569− (event).data.alias.anchor = (event_anchor))
570−
571−#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \
572− event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \
573− (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \
574− (event).data.scalar.anchor = (event_anchor), \
575− (event).data.scalar.tag = (event_tag), \
576− (event).data.scalar.value = (event_value), \
577− (event).data.scalar.length = (event_length), \
578− (event).data.scalar.plain_implicit = (event_plain_implicit), \
579− (event).data.scalar.quoted_implicit = (event_quoted_implicit), \
580− (event).data.scalar.style = (event_style))
581−
582−#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \
583− event_implicit,event_style,start_mark,end_mark) \
584− (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \
585− (event).data.sequence_start.anchor = (event_anchor), \
586− (event).data.sequence_start.tag = (event_tag), \
587− (event).data.sequence_start.implicit = (event_implicit), \
588− (event).data.sequence_start.style = (event_style))
589−
590−#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \
591− (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark)))
592−
593−#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \
594− event_implicit,event_style,start_mark,end_mark) \
595− (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \
596− (event).data.mapping_start.anchor = (event_anchor), \
597− (event).data.mapping_start.tag = (event_tag), \
598− (event).data.mapping_start.implicit = (event_implicit), \
599− (event).data.mapping_start.style = (event_style))
600−
601−#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \
602− (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark)))
603−
604−/*
605− * Document initializer.
606− */
607−
608−#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \
609− document_version_directive,document_tag_directives_start, \
610− document_tag_directives_end,document_start_implicit, \
611− document_end_implicit,document_start_mark,document_end_mark) \
612− (memset(&(document), 0, sizeof(yaml_document_t)), \
613− (document).nodes.start = (document_nodes_start), \
614− (document).nodes.end = (document_nodes_end), \
615− (document).nodes.top = (document_nodes_start), \
616− (document).version_directive = (document_version_directive), \
617− (document).tag_directives.start = (document_tag_directives_start), \
618− (document).tag_directives.end = (document_tag_directives_end), \
619− (document).start_implicit = (document_start_implicit), \
620− (document).end_implicit = (document_end_implicit), \
621− (document).start_mark = (document_start_mark), \
622− (document).end_mark = (document_end_mark))
623−
624−/*
625− * Node initializers.
626− */
627−
628−#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \
629− (memset(&(node), 0, sizeof(yaml_node_t)), \
630− (node).type = (node_type), \
631− (node).tag = (node_tag), \
632− (node).start_mark = (node_start_mark), \
633− (node).end_mark = (node_end_mark))
634−
635−#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \
636− node_style,start_mark,end_mark) \
637− (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \
638− (node).data.scalar.value = (node_value), \
639− (node).data.scalar.length = (node_length), \
640− (node).data.scalar.style = (node_style))
641−
642−#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \
643− node_style,start_mark,end_mark) \
644− (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \
645− (node).data.sequence.items.start = (node_items_start), \
646− (node).data.sequence.items.end = (node_items_end), \
647− (node).data.sequence.items.top = (node_items_start), \
648− (node).data.sequence.style = (node_style))
649−
650−#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \
651− node_style,start_mark,end_mark) \
652− (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \
653− (node).data.mapping.pairs.start = (node_pairs_start), \
654− (node).data.mapping.pairs.end = (node_pairs_end), \
655− (node).data.mapping.pairs.top = (node_pairs_start), \
656− (node).data.mapping.style = (node_style))
657−
658−#define YAML_VERSION_STRING "0.1.5"
659−#define YAML_VERSION_MAJOR 0
660−#define YAML_VERSION_MINOR 1
661−#define YAML_VERSION_PATCH 5
stack.yaml+8−1
@@ -1,5 +1,12 @@
1−resolver: lts-3.0
1+resolver: lts-22.13
22
33flags:
44 yaml:
55 no-examples: false
6+
7+packages:
8+ - yaml
9+ - libyaml
10+
11+extra-deps:
12+ - libyaml-clib-0.2.5
test/Data/Yaml/IncludeSpec.hsdeleted−44
@@ -1,44 +0,0 @@
1−{-# LANGUAGE QuasiQuotes #-}
2−module Data.Yaml.IncludeSpec (main, spec) where
3−
4−import Test.Hspec
5−import Data.Either.Compat
6−import Data.Aeson
7−import Data.Aeson.QQ
8−import Data.Yaml (ParseException)
9−
10−import Data.Yaml.Include
11−
12−main :: IO ()
13−main = hspec spec
14−
15−spec :: Spec
16−spec = do
17− describe "decodeFile" $ do
18− it "supports includes" $ do
19− decodeFile "test/resources/foo.yaml" `shouldReturn` Just [aesonQQ|
20− {
21− foo: 23,
22− bar: {one: 1, two: 2},
23− baz: 42
24− }
25− |]
26−
27− it "supports recursive includes" $ do
28− decodeFile "test/resources/baz.yaml" `shouldReturn` Just [aesonQQ|
29− {
30− foo: {
31− foo: 23,
32− bar: {one: 1, two: 2},
33− baz: 42
34− }
35− }
36− |]
37−
38− it "aborts on cyclic includes" $ do
39− (decodeFile "test/resources/loop/foo.yaml" :: IO (Maybe Value)) `shouldThrow` anyException
40−
41− describe "decodeFileEither" $ do
42− context "when file does not exist" $ do
43− it "returns Left" $ do
44− (decodeFileEither "./does_not_exist.yaml" :: IO (Either ParseException Value)) >>= (`shouldSatisfy` isLeft)
test/Data/YamlSpec.hsdeleted−486
@@ -1,486 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE PackageImports #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−{-# LANGUAGE TemplateHaskell #-}
6−
7−module Data.YamlSpec (main, spec) where
8−
9−import qualified Text.Libyaml as Y
10−import qualified Data.ByteString.Char8 as B8
11−
12−import Test.HUnit hiding (Test, path)
13−
14−import qualified Data.Conduit as C
15−import qualified Control.Monad.Trans.Resource as C
16−import qualified Data.Conduit.List as CL
17−
18−import Control.Monad
19−import Control.Exception (try, SomeException)
20−import Test.Hspec
21−import Data.Either.Compat
22−import Test.Mockery.Directory
23−
24−import qualified Data.Yaml as D
25−import qualified Data.Yaml.Pretty as Pretty
26−import Data.Yaml (object, array, (.=))
27−import Data.Maybe
28−import qualified Data.HashMap.Strict as M
29−import qualified Data.Text as T
30−import Data.Aeson.TH
31−import Data.Text (Text)
32−import Data.Vector (Vector)
33−import qualified Data.Vector as V
34−import Data.HashMap.Strict (HashMap)
35−import qualified Data.HashMap.Strict as HM
36−
37−data TestJSON = TestJSON
38− { string :: Text
39− , number :: Int
40− , anArray :: Vector Text
41− , hash :: HashMap Text Text
42− , extrastring :: Text
43− } deriving (Show, Eq)
44−
45−deriveJSON defaultOptions ''TestJSON
46−
47−main :: IO ()
48−main = hspec spec
49−
50−spec :: Spec
51−spec = do
52− describe "streaming" $ do
53− it "count scalars with anchor" caseCountScalarsWithAnchor
54− it "count sequences with anchor" caseCountSequencesWithAnchor
55− it "count mappings with anchor" caseCountMappingsWithAnchor
56− it "count aliases" caseCountAliases
57− it "count scalars" caseCountScalars
58− it "largest string" caseLargestString
59− it "encode/decode" caseEncodeDecode
60− it "encode/decode file" caseEncodeDecodeFile
61− it "interleaved encode/decode" caseInterleave
62− it "decode invalid document (without segfault)" caseDecodeInvalidDocument
63− describe "Data.Yaml" $ do
64− it "encode/decode" caseEncodeDecodeData
65− it "encode/decode file" caseEncodeDecodeFileData
66− it "encode/decode strings" caseEncodeDecodeStrings
67− it "decode invalid file" caseDecodeInvalid
68− it "processes datatypes" caseDataTypes
69− describe "Data.Yaml.Pretty" $ do
70− it "encode/decode" caseEncodeDecodeDataPretty
71− it "encode/decode strings" caseEncodeDecodeStringsPretty
72− it "processes datatypes" caseDataTypesPretty
73− describe "Data.Yaml aliases" $ do
74− it "simple scalar alias" caseSimpleScalarAlias
75− it "simple sequence alias" caseSimpleSequenceAlias
76− it "simple mapping alias" caseSimpleMappingAlias
77− it "mapping alias before anchor" caseMappingAliasBeforeAnchor
78− it "mapping alias inside anchor" caseMappingAliasInsideAnchor
79− it "scalar alias overriding" caseScalarAliasOverriding
80− describe "Data.Yaml merge keys" $ do
81− it "test uniqueness of keys" caseAllKeysShouldBeUnique
82− it "test mapping merge" caseSimpleMappingMerge
83− it "test sequence of mappings merging" caseMergeSequence
84− describe "numbers" $ do
85− it "parses as string when quoted" caseQuotedNumber
86− it "parses as number when unquoted" caseUnquotedNumber
87− it "parses as number !!str is present" caseAttribNumber
88− it "integers have no decimals" caseIntegerDecimals
89− describe "booleans" $ do
90− it "parses when all lowercase" caseLowercaseBool
91− it "parses when all uppercase" caseUppercaseBool
92− it "parses when titlecase" caseTitlecaseBool
93− describe "empty input" $ do
94− it "doesn't crash" caseEmptyInput
95− describe "alias stripping" $ do
96− it "works" caseStripAlias
97− describe "nulls" $ do
98− checkNull "null"
99− checkNull "Null"
100− checkNull "NULL"
101− checkNull "~"
102− checkNull ""
103−
104− describe "pretty output" $ do
105− it "simple nulls" $ D.encode (object ["foo" .= D.Null]) `shouldBe` "foo: null\n"
106− it "simple numbers" $ D.encode (object ["foo" .= (4 :: Int)]) `shouldBe` "foo: 4\n"
107− it "True" $ D.encode (object ["foo" .= True]) `shouldBe` "foo: true\n"
108− it "False" $ D.encode (object ["foo" .= False]) `shouldBe` "foo: false\n"
109− it "simple string" $ D.encode (object ["foo" .= ("bar" :: T.Text)]) `shouldBe` "foo: bar\n"
110−
111− describe "special keys" $ do
112− let tester key = it (T.unpack key) $
113− let value = object [key .= True]
114− in D.decode (D.encode value) `shouldBe` Just value
115− mapM_ tester specialStrings
116−
117− describe "special values" $ do
118− let tester value = it (T.unpack value) $
119− let value' = object ["foo" .= value]
120− in D.decode (D.encode value') `shouldBe` Just value'
121− mapM_ tester specialStrings
122−
123− describe "decodeFileEither" $ do
124− it "loads YAML through JSON into Haskell data" $ do
125− tj <- either (error . show) id `fmap` D.decodeFileEither "test/json.yaml"
126− tj `shouldBe` TestJSON
127− { string = "str"
128− , number = 2
129− , anArray = V.fromList ["a", "b"]
130− , hash = HM.fromList [("key1", "value1"), ("key2", "value2")]
131− , extrastring = "1234-foo"
132− }
133−
134− context "when file does not exist" $ do
135− it "returns Left" $ do
136− (D.decodeFileEither "./does_not_exist.yaml" :: IO (Either D.ParseException D.Value)) >>= (`shouldSatisfy` isLeft)
137−
138−
139− describe "round-tripping of special scalars" $ do
140− let special = words "y Y On ON false 12345 12345.0 12345a 12e3"
141− forM_ special $ \w -> it w $
142− let v = object ["word" .= w]
143− in D.decode (D.encode v) `shouldBe` Just v
144− it "no tags" $ D.encode (object ["word" .= ("true" :: String)]) `shouldBe` "word: 'true'\n"
145−
146− it "aliases in keys #49" caseIssue49
147−
148− it "serialization of +123 #64" $ do
149− D.decode (D.encode ("+123" :: String)) `shouldBe` Just ("+123" :: String)
150−
151− it "preserves Scientific precision" casePreservesScientificPrecision
152−
153−
154−specialStrings :: [T.Text]
155−specialStrings =
156− [ "fo\"o"
157− , "fo\'o"
158− , "fo\\'o"
159− , "fo: o"
160− , "foo\nbar\nbaz\n"
161− ]
162−
163−counter :: Monad m => (Y.Event -> Bool) -> C.Sink Y.Event m Int
164−counter pred' =
165− CL.fold (\cnt e -> (if pred' e then 1 else 0) + cnt) 0
166−
167−caseHelper :: String
168− -> (Y.Event -> Bool)
169− -> Int
170− -> Assertion
171−caseHelper yamlString pred' expRes = do
172− res <- C.runResourceT $ Y.decode (B8.pack yamlString) C.$$ counter pred'
173− res @?= expRes
174−
175−caseCountScalarsWithAnchor :: Assertion
176−caseCountScalarsWithAnchor =
177− caseHelper yamlString isScalarA 1
178− where
179− yamlString = "foo:\n - &anchor bin1\n - bin2\n - bin3"
180− isScalarA (Y.EventScalar _ _ _ (Just _)) = True
181− isScalarA _ = False
182−
183−caseCountSequencesWithAnchor :: Assertion
184−caseCountSequencesWithAnchor =
185− caseHelper yamlString isSequenceStartA 1
186− where
187− yamlString = "foo: &anchor\n - bin1\n - bin2\n - bin3"
188− isSequenceStartA (Y.EventSequenceStart (Just _)) = True
189− isSequenceStartA _ = False
190−
191−caseCountMappingsWithAnchor :: Assertion
192−caseCountMappingsWithAnchor =
193− caseHelper yamlString isMappingA 1
194− where
195− yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3"
196− isMappingA (Y.EventMappingStart (Just _)) = True
197− isMappingA _ = False
198−
199−caseCountAliases :: Assertion
200−caseCountAliases =
201− caseHelper yamlString isAlias 1
202− where
203− yamlString = "foo: &anchor\n key1: bin1\n key2: bin2\n key3: bin3\nboo: *anchor"
204− isAlias Y.EventAlias{} = True
205− isAlias _ = False
206−
207−caseCountScalars :: Assertion
208−caseCountScalars = do
209− res <- C.runResourceT $ Y.decode yamlBS C.$$ CL.fold adder accum
210− res @?= (7, 1, 2)
211− where
212− yamlString = "foo:\n baz: [bin1, bin2, bin3]\nbaz: bazval"
213− yamlBS = B8.pack yamlString
214− adder (s, l, m) (Y.EventScalar{}) = (s + 1, l, m)
215− adder (s, l, m) (Y.EventSequenceStart{}) = (s, l + 1, m)
216− adder (s, l, m) (Y.EventMappingStart{}) = (s, l, m + 1)
217− adder a _ = a
218− accum = (0, 0, 0) :: (Int, Int, Int)
219−
220−caseLargestString :: Assertion
221−caseLargestString = do
222− res <- C.runResourceT $ Y.decodeFile filePath C.$$ CL.fold adder accum
223− res @?= (length expected, expected)
224− where
225− expected = "this one is just a little bit bigger than the others"
226− filePath = "test/largest-string.yaml"
227− adder (i, s) (Y.EventScalar bs _ _ _) =
228− let s' = B8.unpack bs
229− i' = length s'
230− in if i' > i then (i', s') else (i, s)
231− adder acc _ = acc
232− accum = (0, "no strings found")
233−
234−newtype MyEvent = MyEvent Y.Event deriving Show
235−instance Eq MyEvent where
236− (MyEvent (Y.EventScalar s t _ _)) == (MyEvent (Y.EventScalar s' t' _ _)) =
237− s == s' && t == t'
238− MyEvent e1 == MyEvent e2 = e1 == e2
239−
240−caseEncodeDecode :: Assertion
241−caseEncodeDecode = do
242− eList <- C.runResourceT $ Y.decode yamlBS C.$$ CL.consume
243− bs <- C.runResourceT $ CL.sourceList eList C.$$ Y.encode
244− eList2 <- C.runResourceT $ Y.decode bs C.$$ CL.consume
245− map MyEvent eList @=? map MyEvent eList2
246− where
247− yamlString = "foo: bar\nbaz:\n - bin1\n - bin2\n"
248− yamlBS = B8.pack yamlString
249−
250−caseEncodeDecodeFile :: Assertion
251−caseEncodeDecodeFile = withFile "" $ \tmpPath -> do
252− eList <- C.runResourceT $ Y.decodeFile filePath C.$$ CL.consume
253− C.runResourceT $ CL.sourceList eList C.$$ Y.encodeFile tmpPath
254− eList2 <- C.runResourceT $ Y.decodeFile filePath C.$$ CL.consume
255− map MyEvent eList @=? map MyEvent eList2
256− where
257− filePath = "test/largest-string.yaml"
258−
259−caseInterleave :: Assertion
260−caseInterleave = withFile "" $ \tmpPath -> withFile "" $ \tmpPath2 -> do
261− () <- C.runResourceT $ Y.decodeFile filePath C.$$ Y.encodeFile tmpPath
262− () <- C.runResourceT $ Y.decodeFile tmpPath C.$$ Y.encodeFile tmpPath2
263− f1 <- readFile tmpPath
264− f2 <- readFile tmpPath2
265− f1 @=? f2
266− where
267− filePath = "test/largest-string.yaml"
268−
269−caseDecodeInvalidDocument :: Assertion
270−caseDecodeInvalidDocument = do
271− x <- try $ C.runResourceT $ Y.decode yamlBS C.$$ CL.sinkNull
272− case x of
273− Left (_ :: SomeException) -> return ()
274− Right y -> do
275− putStrLn $ "bad return value: " ++ show y
276− assertFailure "expected parsing exception, but got no errors"
277− where
278− yamlString = " - foo\n - baz\nbuz"
279− yamlBS = B8.pack yamlString
280−
281−mkScalar :: String -> D.Value
282−mkScalar = mkStrScalar
283−
284−mkStrScalar :: String -> D.Value
285−mkStrScalar = D.String . T.pack
286−
287−mappingKey :: D.Value-> String -> D.Value
288−mappingKey (D.Object m) k = (fromJust . M.lookup (T.pack k) $ m)
289−mappingKey _ _ = error "expected Object"
290−
291−decodeYaml :: String -> Maybe D.Value
292−decodeYaml s = D.decode $ B8.pack s
293−
294−sample :: D.Value
295−sample = array
296− [ D.String "foo"
297− , object
298− [ ("bar1", D.String "bar2")
299− , ("bar3", D.String "")
300− ]
301− , D.String ""
302− ]
303−
304−caseEncodeDecodeData :: Assertion
305−caseEncodeDecodeData = do
306− let out = D.decode $ D.encode sample
307− out @?= Just sample
308−
309−caseEncodeDecodeDataPretty :: Assertion
310−caseEncodeDecodeDataPretty = do
311− let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample
312− out @?= Just sample
313−
314−caseEncodeDecodeFileData :: Assertion
315−caseEncodeDecodeFileData = withFile "" $ \fp -> do
316− D.encodeFile fp sample
317− out <- D.decodeFile fp
318− out @?= Just sample
319−
320−caseEncodeDecodeStrings :: Assertion
321−caseEncodeDecodeStrings = do
322− let out = D.decode $ D.encode sample
323− out @?= Just sample
324−
325−caseEncodeDecodeStringsPretty :: Assertion
326−caseEncodeDecodeStringsPretty = do
327− let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample
328− out @?= Just sample
329−
330−caseDecodeInvalid :: Assertion
331−caseDecodeInvalid = do
332− let invalid = B8.pack "\tthis is 'not' valid :-)"
333− Nothing @=? (D.decode invalid :: Maybe D.Value)
334−
335−caseSimpleScalarAlias :: Assertion
336−caseSimpleScalarAlias = do
337− let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch"
338− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
339− let res = fromJust maybeRes
340− res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")]
341−
342−caseSimpleSequenceAlias :: Assertion
343−caseSimpleSequenceAlias = do
344− let maybeRes = decodeYaml "seq: &anch\n - foo\n - baz\nseq2: *anch"
345− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
346− let res = fromJust maybeRes
347− res @?= object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])]
348−
349−caseSimpleMappingAlias :: Assertion
350−caseSimpleMappingAlias = do
351− let maybeRes = decodeYaml "map: &anch\n key1: foo\n key2: baz\nmap2: *anch"
352− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
353− let res = fromJust maybeRes
354− res @?= object [(T.pack "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (T.pack "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])]
355−
356−caseMappingAliasBeforeAnchor :: Assertion
357−caseMappingAliasBeforeAnchor = do
358− let res = decodeYaml "map: *anch\nmap2: &anch\n key1: foo\n key2: baz"
359− isNothing res @? "decode should return Nothing due to unknown alias"
360−
361−caseMappingAliasInsideAnchor :: Assertion
362−caseMappingAliasInsideAnchor = do
363− let res = decodeYaml "map: &anch\n key1: foo\n key2: *anch"
364− isNothing res @? "decode should return Nothing due to unknown alias"
365−
366−caseScalarAliasOverriding :: Assertion
367−caseScalarAliasOverriding = do
368− let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch"
369− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
370− let res = fromJust maybeRes
371− res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")]
372−
373−caseAllKeysShouldBeUnique :: Assertion
374−caseAllKeysShouldBeUnique = do
375− let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\nfoo1: buz"
376− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
377− let res = fromJust maybeRes
378− mappingKey res "foo1" @?= (mkScalar "buz")
379−
380−caseSimpleMappingMerge :: Assertion
381−caseSimpleMappingMerge = do
382− let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"
383− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
384− let res = fromJust maybeRes
385− mappingKey res "foo1" @?= (mkScalar "foo")
386− mappingKey res "foo3" @?= (mkScalar "fuz")
387−
388−caseMergeSequence :: Assertion
389−caseMergeSequence = do
390− let maybeRes = decodeYaml "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 ]"
391− isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"
392− let res = fromJust maybeRes
393− mappingKey res "foo1" @?= (mkScalar "foo")
394− mappingKey res "k1" @?= (D.String "1")
395− mappingKey res "k2" @?= (D.String "2")
396− mappingKey res "k3" @?= (D.String "4")
397−
398−caseDataTypes :: Assertion
399−caseDataTypes =
400− D.decode (D.encode val) @?= Just val
401− where
402− val = object
403− [ ("string", D.String "foo")
404− , ("int", D.Number 5)
405− , ("float", D.Number 4.3)
406− , ("true", D.Bool True)
407− , ("false", D.Bool False)
408− , ("null", D.Null)
409− ]
410−
411−caseDataTypesPretty :: Assertion
412−caseDataTypesPretty =
413− D.decode (Pretty.encodePretty Pretty.defConfig val) @?= Just val
414− where
415− val = object
416− [ ("string", D.String "foo")
417− , ("int", D.Number 5)
418− , ("float", D.Number 4.3)
419− , ("true", D.Bool True)
420− , ("false", D.Bool False)
421− , ("null", D.Null)
422− ]
423−caseQuotedNumber, caseUnquotedNumber, caseAttribNumber, caseIntegerDecimals :: Assertion
424−caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")])
425−caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])
426−caseAttribNumber = D.decode "foo: !!str 1234" @?= Just (object [("foo", D.String "1234")])
427−caseIntegerDecimals = D.encode (1 :: Int) @?= "1\n...\n"
428−
429−obj :: Maybe D.Value
430−obj = Just (object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)])
431−
432−caseLowercaseBool, caseUppercaseBool, caseTitlecaseBool :: Assertion
433−caseLowercaseBool = D.decode "foo: off\nbar: y\nbaz: true" @?= obj
434−caseUppercaseBool = D.decode "foo: FALSE\nbar: Y\nbaz: ON" @?= obj
435−caseTitlecaseBool = D.decode "foo: No\nbar: Yes\nbaz: True" @?= obj
436−
437−caseEmptyInput :: Assertion
438−caseEmptyInput = D.decode B8.empty @?= (Nothing :: Maybe D.Value)
439−
440−checkNull :: T.Text -> Spec
441−checkNull x =
442− it ("null recognized: " ++ show x) assertion
443− where
444− assertion = Just (object [("foo", D.Null)]) @=? D.decode (B8.pack $ "foo: " ++ T.unpack x)
445−
446−caseStripAlias :: Assertion
447−caseStripAlias =
448− D.decode src @?= Just (object
449− [ "Default" .= object
450− [ "foo" .= (1 :: Int)
451− , "bar" .= (2 :: Int)
452− ]
453− , "Obj" .= object
454− [ "foo" .= (1 :: Int)
455− , "bar" .= (2 :: Int)
456− , "key" .= (3 :: Int)
457− ]
458− ])
459− where
460− src = "Default: &def\n foo: 1\n bar: 2\nObj:\n <<: *def\n key: 3\n"
461−
462−caseIssue49 :: Assertion
463−caseIssue49 =
464− D.decodeEither src @?= Right (object
465− [ "a" .= object [ "value" .= (1.0 :: Double) ]
466− , "b" .= object [ "value" .= (1.2 :: Double) ]
467− ])
468− where
469− src = "---\na:\n &id5 value: 1.0\nb:\n *id5: 1.2"
470−
471−-- | We cannot guarantee this before aeson started using 'Scientific'.
472−casePreservesScientificPrecision :: Assertion
473−casePreservesScientificPrecision = do
474− D.decodeEither "x: 1e-100000" @?= Right (object
475− [ "x" .= D.Number (read "1e-100000") ])
476− -- Note that this ought to work also without 'Scientific', given
477− -- that @read (show "9.78159610558926e-5") == 9.78159610558926e-5@.
478− -- However, it didn't work (and still doesn't work with aeson < 0.7)
479− -- for two reasons:
480− --
481− -- * We use 'Data.Text.Read.double', which is not as accurate as it
482− -- can be;
483− -- * Even if we used 'Data.Text.Read.rational' we would not get good
484− -- results, because of <https://github.com/bos/text/issues/34>.
485− D.decodeEither "x: 9.78159610558926e-5" @?= Right (object
486− [ "x" .= D.Number (read "9.78159610558926e-5") ])
yaml.cabaldeleted−158
@@ -1,158 +0,0 @@
1−name: yaml
2−version: 0.8.17.2
3−license: BSD3
4−license-file: LICENSE
5−author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov
6−maintainer: Michael Snoyman <michael@snoyman.com>
7−synopsis: Support for parsing and rendering YAML documents.
8−description: Please see the README.md file.
9−category: Web
10−stability: stable
11−cabal-version: >= 1.8
12−build-type: Simple
13−homepage: http://github.com/snoyberg/yaml/
14−extra-source-files: c/helper.h
15− libyaml/yaml_private.h
16− libyaml/yaml.h
17− libyaml/LICENSE
18− test/largest-string.yaml
19− test/json.yaml
20− test/resources/foo.yaml
21− test/resources/bar.yaml
22− test/resources/baz.yaml
23− test/resources/loop/foo.yaml
24− test/resources/loop/bar.yaml
25− README.md
26− ChangeLog.md
27−
28−flag no-exe
29− description: don't install the yaml2json or json2yaml executables
30− default: False
31−
32−flag no-examples
33− description: don't build the examples
34− default: True
35−
36−flag system-libyaml
37− description: Use the system-wide libyaml instead of the bundled copy
38− default: False
39−
40−flag no-unicode
41− description: Don't enable unicode output. Instead, unicode characters will be escaped.
42− default: False
43−
44−library
45− build-depends: base >= 4 && < 5
46− , transformers >= 0.1
47− , bytestring >= 0.9.1.4
48− , conduit >= 1.1.0 && < 1.3
49− , resourcet >= 0.3 && < 1.2
50− , aeson >= 0.7
51− , containers
52− , unordered-containers
53− , vector
54− , text
55− , attoparsec >= 0.11.3.0
56− , scientific
57− , filepath
58− , directory
59− , enclosed-exceptions
60− , semigroups
61− exposed-modules: Text.Libyaml
62− Data.Yaml
63− Data.Yaml.Aeson
64− Data.Yaml.Builder
65− Data.Yaml.Config
66− Data.Yaml.Pretty
67− Data.Yaml.Parser
68− Data.Yaml.Include
69− other-modules:
70− Data.Yaml.Internal
71− ghc-options: -Wall
72− c-sources: c/helper.c
73− include-dirs: c
74− if flag(no-unicode)
75− cpp-options: -D__NO_UNICODE__
76− if flag(system-libyaml)
77− pkgconfig-depends: yaml-0.1
78− else
79− c-sources: libyaml/api.c,
80− libyaml/dumper.c,
81− libyaml/emitter.c,
82− libyaml/loader.c,
83− libyaml/parser.c,
84− libyaml/reader.c,
85− libyaml/scanner.c,
86− libyaml/writer.c
87− include-dirs: libyaml
88−
89−executable yaml2json
90− if flag(no-exe)
91− Buildable: False
92− else
93− Buildable: True
94−
95− hs-source-dirs: exe
96− main-is: yaml2json.hs
97− build-depends: base >= 4 && < 5
98− , yaml
99− , bytestring >= 0.9.1.4
100− , aeson >= 0.7
101−
102−executable json2yaml
103− if flag(no-exe)
104− Buildable: False
105− else
106− Buildable: True
107−
108− hs-source-dirs: exe
109− main-is: json2yaml.hs
110− build-depends: base >= 4 && < 5
111− , yaml
112− , bytestring >= 0.9.1.4
113− , aeson >= 0.7
114−
115−
116−test-suite spec
117− type: exitcode-stdio-1.0
118− hs-source-dirs: test
119− main-is: Spec.hs
120− other-modules: Data.YamlSpec
121− Data.Yaml.IncludeSpec
122− cpp-options: -DTEST
123− build-depends: hspec >= 1.3
124− , HUnit
125− , base >= 4 && < 5
126− , transformers >= 0.1
127− , bytestring >= 0.9.1.4
128− , conduit
129− , yaml
130− , text
131− , aeson >= 0.7
132− , unordered-containers
133− , vector
134− , resourcet
135− , aeson-qq
136− , mockery
137− , base-compat
138− ghc-options: -Wall
139−
140−executable examples
141− if flag(no-examples)
142− Buildable: False
143− else
144− Buildable: True
145− build-depends: base
146− , bytestring
147− , raw-strings-qq
148− , text
149− , yaml
150− hs-source-dirs: examples
151− main-is: Main.hs
152− other-modules: Config
153− Simple
154− ghc-options: -Wall
155−
156−source-repository head
157− type: git
158− location: https://github.com/snoyberg/yaml
yaml/ChangeLog.mdnew file+303
@@ -0,0 +1,303 @@
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
LICENSE → yaml/LICENSErenamed

The content is the same.

yaml/README.mdnew file+26
@@ -0,0 +1,26 @@
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+```
Setup.lhs → yaml/Setup.lhsrenamed

The content is the same.

builder-test.hs → yaml/builder-test.hsrenamed

The content is the same.

examples/Config.hs → yaml/examples/Config.hsrenamed+4−2
@@ -9,6 +9,7 @@ import Data.Yaml (FromJSON(..), (.:))
99import Text.RawString.QQ
1010import Data.ByteString (ByteString)
1111import Control.Applicative
12+import Prelude -- Ensure Applicative is in scope and we have no warnings, before/after AMP.
1213
1314configYaml :: ByteString
1415configYaml = [r|
@@ -49,5 +50,6 @@ instance FromJSON Config where
4950 parseJSON _ = fail "Expected Object for Config value"
5051
5152main :: IO ()
52−main =
53− print $ (Y.decode configYaml :: Maybe Config)
53+main = do
54+ config <- Y.decodeThrow configYaml
55+ print (config :: Config)
examples/Main.hs → yaml/examples/Main.hsrenamed

The content is the same.

examples/Simple.hs → yaml/examples/Simple.hsrenamed+2−1
@@ -6,7 +6,8 @@ import qualified Data.Yaml as Y
66
77main :: IO ()
88main = do
9− print $ (Y.decode "[1,2,3]" :: Maybe [Integer])
9+ res <- Y.decodeThrow "[1,2,3]"
10+ print (res :: [Integer])
1011
1112-- You can go one step further and decode into a custom type by implementing
1213-- 'FromJSON' for that type. This is also appropriate where extra
yaml/exe/Common.hsnew file+68
@@ -0,0 +1,68 @@
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.hsnew file+106
@@ -0,0 +1,106 @@
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.hsnew file+87
@@ -0,0 +1,87 @@
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.yamlnew file+113
@@ -0,0 +1,113 @@
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
parser-test.hs → yaml/parser-test.hsrenamed

The content is the same.

yaml/src/Data/Yaml.hsnew file+292
@@ -0,0 +1,292 @@
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." #-}
Data/Yaml/Aeson.hs → yaml/src/Data/Yaml/Aeson.hsrenamed

The content is the same.

yaml/src/Data/Yaml/Builder.hsnew file+240
@@ -0,0 +1,240 @@
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
Data/Yaml/Config.hs → yaml/src/Data/Yaml/Config.hsrenamed+40−17
@@ -5,7 +5,7 @@
55-- In particular, merging environment variables with yaml values
66--
77-- 'loadYamlSettings' is a high-level API for loading YAML and merging environment variables.
8−-- A yaml value of @_env:ENV_VAR:default@ will lookup the environment variable @ENV_VAR@.
8+-- A yaml value of @_env:ENV_VAR:default@ or just @_env:ENV_VAR@ will lookup the environment variable @ENV_VAR@.
99--
1010-- On a historical note, this code was taken directly from the yesod web framework's configuration module.
1111module Data.Yaml.Config
@@ -33,7 +33,13 @@ import Data.Monoid
3333import Data.Semigroup
3434import Data.List.NonEmpty (nonEmpty)
3535import 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
3641import qualified Data.HashMap.Strict as H
42+#endif
3743import Data.Text (Text, pack)
3844import System.Environment (getArgs, getEnvironment)
3945import Control.Arrow ((***))
@@ -41,9 +47,20 @@ import Control.Monad (forM)
4147import Control.Exception (throwIO)
4248import Data.Text.Encoding (encodeUtf8)
4349import qualified Data.Yaml as Y
50+import qualified Data.Yaml.Include as YI
4451import Data.Maybe (fromMaybe)
4552import qualified Data.Text as T
4653
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+
4764newtype MergedValue = MergedValue { getMergedValue :: Value }
4865
4966instance Semigroup MergedValue where
@@ -63,7 +80,7 @@ mergeValues x _ = x
6380--
6481-- @since 0.8.16
6582applyEnvValue :: Bool -- ^ require an environment variable to be present?
66− -> H.HashMap Text Text -> Value -> Value
83+ -> KeyMap Text -> Value -> Value
6784applyEnvValue requireEnv' env =
6885 goV
6986 where
@@ -73,7 +90,7 @@ applyEnvValue requireEnv' env =
7390 t2 <- T.stripPrefix "_env:" t1
7491 let (name, t3) = T.break (== ':') t2
7592 mdef = fmap parseValue $ T.stripPrefix ":" t3
76− Just $ case H.lookup name env of
93+ Just $ case H.lookup (fromText name) env of
7794 Just val ->
7895 -- If the default value parses as a String, we treat the
7996 -- environment variable as a raw value and do not parse it.
@@ -92,13 +109,16 @@ applyEnvValue requireEnv' env =
92109 _ -> Null
93110 goV v = v
94111
95− parseValue val = fromMaybe (String val) $ Y.decode $ encodeUtf8 val
112+ parseValue val = either
113+ (const (String val))
114+ id
115+ (Y.decodeThrow $ encodeUtf8 val)
96116
97117-- | Get the actual environment as a @HashMap@ from @Text@ to @Text@.
98118--
99119-- @since 0.8.16
100−getCurrentEnv :: IO (H.HashMap Text Text)
101−getCurrentEnv = fmap (H.fromList . map (pack *** pack)) getEnvironment
120+getCurrentEnv :: IO (KeyMap Text)
121+getCurrentEnv = fmap (H.fromList . map (fromText . pack *** pack)) getEnvironment
102122
103123-- | A convenience wrapper around 'applyEnvValue' and 'getCurrentEnv'
104124--
@@ -114,8 +134,8 @@ applyCurrentEnv requireEnv' orig = flip (applyEnvValue requireEnv') orig <$> get
114134data EnvUsage = IgnoreEnv
115135 | UseEnv
116136 | RequireEnv
117− | UseCustomEnv (H.HashMap Text Text)
118− | RequireCustomEnv (H.HashMap Text Text)
137+ | UseCustomEnv (KeyMap Text)
138+ | RequireCustomEnv (KeyMap Text)
119139
120140-- | Do not use any environment variables, instead relying on defaults values
121141-- in the config file.
@@ -142,14 +162,14 @@ requireEnv = RequireEnv
142162-- @HashMap@ as the environment.
143163--
144164-- @since 0.8.16
145−useCustomEnv :: H.HashMap Text Text -> EnvUsage
165+useCustomEnv :: KeyMap Text -> EnvUsage
146166useCustomEnv = UseCustomEnv
147167
148168-- | Same as 'requireEnv', but instead of the actual environment, use the
149169-- provided @HashMap@ as the environment.
150170--
151171-- @since 0.8.16
152−requireCustomEnv :: H.HashMap Text Text -> EnvUsage
172+requireCustomEnv :: KeyMap Text -> EnvUsage
153173requireCustomEnv = RequireCustomEnv
154174
155175-- | Load the settings from the following three sources:
@@ -165,6 +185,11 @@ requireCustomEnv = RequireCustomEnv
165185--
166186-- > loadYamlSettings ["config/foo.yaml"] [] useEnv
167187--
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+--
168193-- @since 0.8.16
169194loadYamlSettings
170195 :: FromJSON settings
@@ -174,11 +199,9 @@ loadYamlSettings
174199 -> IO settings
175200loadYamlSettings runTimeFiles compileValues envUsage = do
176201 runValues <- forM runTimeFiles $ \fp -> do
177− eres <- Y.decodeFileEither fp
202+ eres <- YI.decodeFileEither fp
178203 case eres of
179− Left e -> do
180− putStrLn $ "loadYamlSettings: Could not parse file as YAML: " ++ fp
181− throwIO e
204+ Left e -> throwIO (Y.LoadSettingsException fp e)
182205 Right value -> return value
183206
184207 value' <-
@@ -193,9 +216,9 @@ loadYamlSettings runTimeFiles compileValues envUsage = do
193216 UseCustomEnv env -> return $ applyEnvValue False env value'
194217 RequireCustomEnv env -> return $ applyEnvValue True env value'
195218
196− case fromJSON value of
197− Error s -> error $ "Could not convert to AppSettings: " ++ s
198− Success settings -> return settings
219+ case Y.parseEither parseJSON value of
220+ Left s -> error $ "Could not convert to expected type: " ++ s
221+ Right settings -> return settings
199222
200223-- | Same as @loadYamlSettings@, but get the list of runtime config files from
201224-- the command line arguments.
Data/Yaml/Include.hs → yaml/src/Data/Yaml/Include.hsrenamed+41−9
@@ -1,5 +1,16 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE RankNTypes #-}
2−module Data.Yaml.Include (decodeFile, decodeFileEither) where
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
314
415import Control.Exception (throwIO)
516import Control.Monad (when)
@@ -13,30 +24,41 @@ import Data.Text.Encoding (decodeUtf8)
1324import System.Directory
1425import System.FilePath
1526
16−import Data.Yaml.Internal (ParseException(..), decodeHelper_, decodeHelper)
27+import Data.Yaml.Internal (ParseException(..), Warning(..), decodeHelper_, decodeHelper)
1728import Text.Libyaml hiding (decodeFile)
1829import qualified Text.Libyaml as Y
1930
2031eventsFromFile
2132 :: MonadResource m
2233 => FilePath
23− -> Producer m Event
34+ -> ConduitM i Event m ()
2435eventsFromFile = go []
2536 where
26− go :: MonadResource m => [FilePath] -> FilePath -> Producer m Event
37+ go :: MonadResource m => [FilePath] -> FilePath -> ConduitM i Event m ()
2738 go seen fp = do
28− cfp <- liftIO $ canonicalizePath fp
39+ cfp <- liftIO $ handleNotFound $ canonicalizePath fp
2940 when (cfp `elem` seen) $ do
3041 liftIO $ throwIO CyclicIncludes
31− Y.decodeFile cfp $= do
42+ Y.decodeFile cfp .| do
3243 awaitForever $ \event -> case event of
3344 EventScalar f (UriTag "!include") _ _ -> do
3445 let includeFile = takeDirectory cfp </> unpack (decodeUtf8 f)
35− go (cfp : seen) includeFile $= CL.filter (`notElem` irrelevantEvents)
46+ go (cfp : seen) includeFile .| CL.filter (`notElem` irrelevantEvents)
3647 _ -> yield event
3748
3849 irrelevantEvents = [EventStreamStart, EventDocumentStart, EventDocumentEnd, EventStreamEnd]
3950
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+
4062-- | Like `Data.Yaml.decodeFile` but with support for relative and absolute
4163-- includes.
4264--
@@ -47,7 +69,7 @@ decodeFile
4769 :: FromJSON a
4870 => FilePath
4971 -> IO (Maybe a)
50−decodeFile fp = decodeHelper (eventsFromFile fp) >>= either throwIO (return . either (const Nothing) id)
72+decodeFile fp = (fmap snd <$> decodeHelper (eventsFromFile fp)) >>= either throwIO (return . either (const Nothing) id)
5173
5274-- | Like `Data.Yaml.decodeFileEither` but with support for relative and
5375-- absolute includes.
@@ -59,4 +81,14 @@ decodeFileEither
5981 :: FromJSON a
6082 => FilePath
6183 -> IO (Either ParseException a)
62−decodeFileEither = decodeHelper_ . eventsFromFile
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.hsnew file+469
@@ -0,0 +1,469 @@
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
Data/Yaml/Parser.hs → yaml/src/Data/Yaml/Parser.hsrenamed+24−19
@@ -9,20 +9,18 @@ import Control.Applicative
99import Control.Exception (Exception)
1010import Control.Monad (MonadPlus (..), liftM, ap)
1111import Control.Monad.Trans.Class (lift)
12−import Control.Monad.Trans.Resource (MonadThrow, monadThrow, runResourceT)
12+import Control.Monad.Trans.Resource (MonadThrow, throwM)
1313import Control.Monad.Trans.Writer.Strict (tell, WriterT)
1414import Data.ByteString (ByteString)
1515import Data.Conduit
16−#if MIN_VERSION_conduit(1,1,0)
1716import Data.Conduit.Lift (runWriterC)
18−#define runWriterSC runWriterC
19−#else
20−import Data.Conduit.Lift (runWriterSC)
21−#endif
2217import qualified Data.Map as Map
2318#if !MIN_VERSION_base(4,8,0)
2419import Data.Monoid (Monoid (..))
2520#endif
21+#if !MIN_VERSION_base(4,11,0)
22+import Data.Semigroup (Semigroup(..))
23+#endif
2624import Data.Text (Text, pack, unpack)
2725import Data.Text.Encoding (decodeUtf8)
2826import Data.Text.Read (signed, decimal)
@@ -41,15 +39,22 @@ instance Applicative YamlParser where
4139instance Alternative YamlParser where
4240 empty = fail "empty"
4341 (<|>) = mplus
42+instance Semigroup (YamlParser a) where
43+ (<>) = mplus
4444instance Monoid (YamlParser a) where
4545 mempty = fail "mempty"
46− mappend = mplus
46+#if !MIN_VERSION_base(4,11,0)
47+ mappend = (<>)
48+#endif
4749instance Monad YamlParser where
4850 return = pure
4951 YamlParser f >>= g = YamlParser $ \am ->
5052 case f am of
5153 Left t -> Left t
5254 Right x -> unYamlParser (g x) am
55+#if MIN_VERSION_base(4,13,0)
56+instance MonadFail YamlParser where
57+#endif
5358 fail = YamlParser . const . Left . pack
5459instance MonadPlus YamlParser where
5560 mzero = fail "mzero"
@@ -129,7 +134,7 @@ data RawDoc = RawDoc YamlValue AnchorMap
129134parseRawDoc :: (FromYaml a, MonadThrow m) => RawDoc -> m a
130135parseRawDoc (RawDoc val am) =
131136 case unYamlParser (fromYaml val) am of
132− Left t -> monadThrow $ FromYamlException t
137+ Left t -> throwM $ FromYamlException t
133138 Right x -> return x
134139
135140(.:) :: FromYaml a => [(Text, YamlValue)] -> Text -> YamlParser a
@@ -145,11 +150,11 @@ data YamlParseException
145150 deriving (Show, Typeable)
146151instance Exception YamlParseException
147152
148−sinkValue :: MonadThrow m => Consumer Event (WriterT AnchorMap m) YamlValue
153+sinkValue :: MonadThrow m => ConduitM Event o (WriterT AnchorMap m) YamlValue
149154sinkValue =
150155 start
151156 where
152− start = await >>= maybe (monadThrow UnexpectedEndOfEvents) go
157+ start = await >>= maybe (throwM UnexpectedEndOfEvents) go
153158
154159 tell' Nothing val = return val
155160 tell' (Just name) val = do
@@ -160,21 +165,21 @@ sinkValue =
160165 go EventDocumentStart = start
161166 go (EventAlias a) = return $ Alias a
162167 go (EventScalar a b c d) = tell' d $ Scalar a b c d
163− go (EventSequenceStart mname) = do
168+ go (EventSequenceStart _tag _style mname) = do
164169 vals <- goS id
165170 let val = Sequence vals mname
166171 tell' mname val
167− go (EventMappingStart mname) = do
172+ go (EventMappingStart _tag _style mname) = do
168173 pairs <- goM id
169174 let val = Mapping pairs mname
170175 tell' mname val
171176
172− go e = monadThrow $ UnexpectedEvent e
177+ go e = throwM $ UnexpectedEvent e
173178
174179 goS front = do
175180 me <- await
176181 case me of
177− Nothing -> monadThrow UnexpectedEndOfEvents
182+ Nothing -> throwM UnexpectedEndOfEvents
178183 Just EventSequenceEnd -> return $ front []
179184 Just e -> do
180185 val <- go e
@@ -183,17 +188,17 @@ sinkValue =
183188 goM front = do
184189 mk <- await
185190 case mk of
186− Nothing -> monadThrow UnexpectedEndOfEvents
191+ Nothing -> throwM UnexpectedEndOfEvents
187192 Just EventMappingEnd -> return $ front []
188193 Just (EventScalar a b c d) -> do
189194 _ <- tell' d $ Scalar a b c d
190195 let k = decodeUtf8 a
191196 v <- start
192197 goM (front . ((k, v):))
193− Just e -> monadThrow $ UnexpectedEvent e
198+ Just e -> throwM $ UnexpectedEvent e
194199
195−sinkRawDoc :: MonadThrow m => Consumer Event m RawDoc
196−sinkRawDoc = uncurry RawDoc <$> runWriterSC sinkValue
200+sinkRawDoc :: MonadThrow m => ConduitM Event o m RawDoc
201+sinkRawDoc = uncurry RawDoc <$> runWriterC sinkValue
197202
198203readYamlFile :: FromYaml a => FilePath -> IO a
199−readYamlFile fp = runResourceT (decodeFile fp $$ sinkRawDoc) >>= parseRawDoc
204+readYamlFile fp = runConduitRes (decodeFile fp .| sinkRawDoc) >>= parseRawDoc
Data/Yaml/Pretty.hs → yaml/src/Data/Yaml/Pretty.hsrenamed+47−11
@@ -1,13 +1,16 @@
11{-# LANGUAGE CPP #-}
22-- | Prettier YAML encoding.
33--
4−-- Since 0.8.13
4+-- @since 0.8.13
55module Data.Yaml.Pretty
66 ( encodePretty
77 , Config
88 , getConfCompare
99 , setConfCompare
10+ , getConfDropNull
11+ , setConfDropNull
1012 , defConfig
13+ , pretty
1114 ) where
1215
1316import Prelude hiding (null)
@@ -15,10 +18,16 @@ import Prelude hiding (null)
1518#if !MIN_VERSION_base(4,8,0)
1619import Control.Applicative ((<$>))
1720#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
1828import Data.Aeson.Types
1929import Data.ByteString (ByteString)
2030import Data.Function (on)
21−import qualified Data.HashMap.Strict as HM
2231import Data.List (sortBy)
2332#if !MIN_VERSION_base(4,8,0)
2433import Data.Monoid
@@ -28,31 +37,58 @@ import qualified Data.Vector as V
2837
2938import Data.Yaml.Builder
3039
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+
3150-- |
32−-- Since 0.8.13
51+-- @since 0.8.13
3352data Config = Config
3453 { confCompare :: Text -> Text -> Ordering -- ^ Function used to sort keys in objects
54+ , confDropNull :: Bool -- ^ Drop null values from objects
3555 }
3656
37−-- | The default configuration: do not sort objects.
57+-- | The default configuration: do not sort objects or drop keys
3858--
39−-- Since 0.8.13
59+-- @since 0.8.13
4060defConfig :: Config
41−defConfig = Config mempty
61+defConfig = Config mempty False
4262
4363-- |
44−-- Since 0.8.13
64+-- @since 0.8.13
4565getConfCompare :: Config -> Text -> Text -> Ordering
4666getConfCompare = confCompare
4767
48−-- |
49−-- Since 0.8.13
68+-- | Sets ordering for object keys
69+--
70+-- @since 0.8.13
5071setConfCompare :: (Text -> Text -> Ordering) -> Config -> Config
5172setConfCompare cmp c = c { confCompare = cmp }
5273
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+
5385pretty :: Config -> Value -> YamlBuilder
5486pretty cfg = go
55− where go (Object o) = mapping (sortBy (confCompare cfg `on` fst) $ HM.toList $ HM.map go o)
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)
5692 go (Array a) = array (go <$> V.toList a)
5793 go Null = null
5894 go (String s) = string s
@@ -61,6 +97,6 @@ pretty cfg = go
6197
6298-- | Configurable 'encode'.
6399--
64−-- Since 0.8.13
100+-- @since 0.8.13
65101encodePretty :: ToJSON a => Config -> a -> ByteString
66102encodePretty cfg = toByteString . pretty cfg . toJSON
yaml/src/Data/Yaml/TH.hsnew file+80
@@ -0,0 +1,80 @@
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.hsnew file+139
@@ -0,0 +1,139 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+899
@@ -0,0 +1,899 @@
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+ ]
test/Spec.hs → yaml/test/Spec.hsrenamed

The content is the same.

test/json.yaml → yaml/test/json.yamlrenamed

The content is the same.

test/largest-string.yaml → yaml/test/largest-string.yamlrenamed

The content is the same.

yaml/test/resources/accent/foo.yamlnew file+1
@@ -0,0 +1 @@
1+foo: true
test/resources/bar.yaml → yaml/test/resources/bar.yamlrenamed

The content is the same.

test/resources/baz.yaml → yaml/test/resources/baz.yamlrenamed

The content is the same.

yaml/test/resources/empty.yamlnew file

No changes to the content.

yaml/test/resources/empty2.yamlnew file+1
@@ -0,0 +1 @@
1+# comment
test/resources/foo.yaml → yaml/test/resources/foo.yamlrenamed

The content is the same.

test/resources/loop/bar.yaml → yaml/test/resources/loop/bar.yamlrenamed

The content is the same.

test/resources/loop/foo.yaml → yaml/test/resources/loop/foo.yamlrenamed

The content is the same.

yaml/yaml.cabalnew file+228
@@ -0,0 +1,228 @@
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