yaml 0.8.30 → 0.8.31
raw patch · 19 files changed
+234/−201 lines, 19 filesdep ~base
Dependency ranges changed: base
Files
- ChangeLog.md +6/−0
- Data/Yaml.hs +34/−12
- Data/Yaml/Config.hs +4/−1
- Data/Yaml/TH.hs +5/−11
- README.md +4/−1
- examples/Config.hs +3/−2
- examples/Simple.hs +2/−1
- libyaml/LICENSE +1/−0
- libyaml/api.c +26/−25
- libyaml/dumper.c +2/−2
- libyaml/emitter.c +2/−2
- libyaml/loader.c +4/−4
- libyaml/parser.c +9/−13
- libyaml/reader.c +3/−3
- libyaml/scanner.c +3/−9
- libyaml/yaml.h +3/−3
- libyaml/yaml_private.h +46/−20
- test/Data/YamlSpec.hs +73/−90
- yaml.cabal +4/−2
ChangeLog.md view
@@ -1,3 +1,9 @@+## 0.8.31++* Add `decodeThrow` and `decodeFileThrow` convenience functions.+* Upgrade libyaml versions+* Deprecate `decode` and `decodeEither`+ ## 0.8.30 * Removed `AppSettings` mentioned in `loadYamlSettings` error message.
Data/Yaml.hs view
@@ -26,8 +26,18 @@ #else module Data.Yaml #endif- ( -- * Types- Value (..)+ ( -- * Encoding+ encode+ , encodeFile+ -- * Decoding+ , decodeEither'+ , decodeFileEither+ , decodeThrow+ , decodeFileThrow+ -- ** More control over decoding+ , decodeHelper+ -- * Types+ , Value (..) , Parser , Object , Array@@ -55,22 +65,17 @@ -- * Classes , ToJSON (..) , FromJSON (..)- -- * Encoding/decoding- , encode- , encodeFile+ -- * Deprecated , decode , decodeFile- -- ** Better error information , decodeEither- , decodeEither'- , decodeFileEither- -- ** More control over decoding- , decodeHelper ) where #if !MIN_VERSION_base(4,8,0) import Control.Applicative((<$>)) #endif import Control.Exception+import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.Trans.Resource (MonadThrow, throwM) import Data.Aeson ( Value (..), ToJSON (..), FromJSON (..), object , (.=) , (.:) , (.:?) , (.!=)@@ -99,11 +104,13 @@ import Text.Libyaml hiding (encode, decode, encodeFile, decodeFile) import qualified Text.Libyaml as Y +-- | Encode a value into its YAML representation. encode :: ToJSON a => a -> ByteString encode obj = unsafePerformIO $ runConduitRes $ CL.sourceList (objToEvents $ toJSON obj) .| Y.encode +-- | Encode a value into its YAML representation and save to the given file. encodeFile :: ToJSON a => FilePath -> a -> IO () encodeFile fp obj = runConduitRes $ CL.sourceList (objToEvents $ toJSON obj)@@ -160,6 +167,7 @@ decode bs = unsafePerformIO $ either (const Nothing) id <$> decodeHelper_ (Y.decode bs)+{-# DEPRECATED decode "Please use decodeEither or decodeThrow, which provide information on how the decode failed" #-} decodeFile :: FromJSON a => FilePath@@ -169,7 +177,7 @@ -- | A version of 'decodeFile' which should not throw runtime exceptions. ----- Since 0.8.4+-- @since 0.8.4 decodeFileEither :: FromJSON a => FilePath@@ -180,16 +188,30 @@ decodeEither bs = unsafePerformIO $ either (Left . prettyPrintParseException) id <$> decodeHelper (Y.decode bs)+{-# DEPRECATED decodeEither "Please use decodeEither' or decodeThrow, which provide more useful failures" #-} -- | More helpful version of 'decodeEither' which returns the 'YamlException'. ----- Since 0.8.3+-- @since 0.8.3 decodeEither' :: FromJSON a => ByteString -> Either ParseException a decodeEither' = either Left (either (Left . AesonException) Right) . unsafePerformIO . decodeHelper . Y.decode +-- | A version of 'decodeEither'' lifted to MonadThrow+--+-- @since 0.8.31+decodeThrow :: (MonadThrow m, FromJSON a) => ByteString -> m a+decodeThrow = either throwM return . decodeEither'++-- | A version of 'decodeFileEither' lifted to MonadIO+--+-- @since 0.8.31+decodeFileThrow :: (MonadIO m, FromJSON a) => FilePath -> m a+decodeFileThrow f = liftIO $ decodeFileEither f >>= either throwIO return++-- | Construct a new 'Value' from a list of 'Value's. array :: [Value] -> Value array = Array . V.fromList
Data/Yaml/Config.hs view
@@ -93,7 +93,10 @@ _ -> Null goV v = v - parseValue val = fromMaybe (String val) $ Y.decode $ encodeUtf8 val+ parseValue val = either+ (const (String val))+ id+ (Y.decodeThrow $ encodeUtf8 val) -- | Get the actual environment as a @HashMap@ from @Text@ to @Text@. --
Data/Yaml/TH.hs view
@@ -30,7 +30,6 @@ import Data.Yaml hiding (decodeFile) -#if MIN_VERSION_template_haskell(2,9,0) -- | Decode a YAML file at compile time. Only available on GHC version @7.8.1@ -- or higher. --@@ -47,18 +46,13 @@ decodeFile :: forall a. (Lift a, FromJSON a) => FilePath -> Q (TExp a) decodeFile path = do addDependentFile path- runIO (decodeFileEither path) >>= \case- Left err -> fail (prettyPrintParseException err)- Right x -> fmap TExp (lift (x :: a))-#endif--decodeValue :: String -> Either String Value-decodeValue = decodeEither . encodeUtf8 . T.pack+ x <- runIO $ decodeFileThrow path+ fmap TExp (lift (x :: a)) yamlExp :: String -> Q Exp-yamlExp input = case decodeValue input of- Left err -> fail err- Right a -> lift a+yamlExp input = do+ val <- runIO $ decodeThrow $ encodeUtf8 $ T.pack input+ lift (val :: Value) -- | A @QuasiQuoter@ for YAML. --
README.md view
@@ -1,8 +1,11 @@ ## yaml +[](https://travis-ci.org/snoyberg/yaml)+[](https://ci.appveyor.com/project/snoyberg/yaml/branch/master)+ Provides support for parsing and emitting Yaml documents. -This package includes the [full libyaml C library version 0.1.7 by Kirill Simonov](http://pyyaml.org/wiki/LibYAML) in the package so you don't need to worry about any non-Haskell dependencies.+This package includes the [full libyaml C library version 0.2.1 by Kirill Simonov](https://github.com/yaml/libyaml) in the package so you don't need to worry about any non-Haskell dependencies. 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.
examples/Config.hs view
@@ -50,5 +50,6 @@ parseJSON _ = fail "Expected Object for Config value" main :: IO ()-main =- print $ (Y.decode configYaml :: Maybe Config)+main = do+ config <- Y.decodeThrow configYaml+ print (config :: Config)
examples/Simple.hs view
@@ -6,7 +6,8 @@ main :: IO () main = do- print $ (Y.decode "[1,2,3]" :: Maybe [Integer])+ res <- Y.decodeThrow "[1,2,3]"+ print (res :: [Integer]) -- You can go one step further and decode into a custom type by implementing -- 'FromJSON' for that type. This is also appropriate where extra
libyaml/LICENSE view
@@ -1,3 +1,4 @@+Copyright (c) 2017-2018 Ingy döt Net Copyright (c) 2006-2016 Kirill Simonov Permission is hereby granted, free of charge, to any person obtaining a copy of
libyaml/api.c view
@@ -81,7 +81,7 @@ yaml_string_extend(yaml_char_t **start, yaml_char_t **pointer, yaml_char_t **end) {- yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2);+ yaml_char_t *new_start = (yaml_char_t *)yaml_realloc((void*)*start, (*end - *start)*2); if (!new_start) return 0; @@ -101,8 +101,9 @@ YAML_DECLARE(int) yaml_string_join( yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,- yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end)+ yaml_char_t **b_start, yaml_char_t **b_pointer, SHIM(yaml_char_t **b_end)) {+ UNUSED_PARAM(b_end) if (*b_start == *b_pointer) return 1; @@ -184,17 +185,17 @@ goto error; if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE)) goto error;- if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE))+ if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*)) goto error;- if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->indents, int*)) goto error;- if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*)) goto error;- if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*)) goto error;- if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->marks, yaml_mark_t*)) goto error;- if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*)) goto error; return 1;@@ -250,7 +251,7 @@ yaml_string_read_handler(void *data, unsigned char *buffer, size_t size, size_t *size_read) {- yaml_parser_t *parser = data;+ yaml_parser_t *parser = (yaml_parser_t *)data; if (parser->input.string.current == parser->input.string.end) { *size_read = 0;@@ -276,7 +277,7 @@ yaml_file_read_handler(void *data, unsigned char *buffer, size_t size, size_t *size_read) {- yaml_parser_t *parser = data;+ yaml_parser_t *parser = (yaml_parser_t *)data; *size_read = fread(buffer, 1, size, parser->input.file); return !ferror(parser->input.file);@@ -362,13 +363,13 @@ goto error; if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE)) goto error;- if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE))+ if (!STACK_INIT(emitter, emitter->states, yaml_emitter_state_t*)) goto error;- if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE))+ if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE, yaml_event_t*)) goto error;- if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE))+ if (!STACK_INIT(emitter, emitter->indents, int*)) goto error;- if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE))+ if (!STACK_INIT(emitter, emitter->tag_directives, yaml_tag_directive_t*)) goto error; return 1;@@ -420,7 +421,7 @@ static int yaml_string_write_handler(void *data, unsigned char *buffer, size_t size) {- yaml_emitter_t *emitter = data;+ yaml_emitter_t *emitter = (yaml_emitter_t *)data; if (emitter->output.string.size - *emitter->output.string.size_written < size) {@@ -446,7 +447,7 @@ static int yaml_file_write_handler(void *data, unsigned char *buffer, size_t size) {- yaml_emitter_t *emitter = data;+ yaml_emitter_t *emitter = (yaml_emitter_t *)data; return (fwrite(buffer, 1, size, emitter->output.file) == size); }@@ -724,7 +725,7 @@ /* Valid tag directives are expected. */ if (version_directive) {- version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));+ version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t); if (!version_directive_copy) goto error; version_directive_copy->major = version_directive->major; version_directive_copy->minor = version_directive->minor;@@ -732,7 +733,7 @@ if (tag_directives_start != tag_directives_end) { yaml_tag_directive_t *tag_directive;- if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))+ if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*)) goto error; for (tag_directive = tag_directives_start; tag_directive != tag_directives_end; tag_directive ++) {@@ -852,7 +853,7 @@ } if (!yaml_check_utf8(value, length)) goto error;- value_copy = yaml_malloc(length+1);+ value_copy = YAML_MALLOC(length+1); if (!value_copy) goto error; memcpy(value_copy, value, length); value_copy[length] = '\0';@@ -1064,10 +1065,10 @@ (tag_directives_start == tag_directives_end)); /* Valid tag directives are expected. */ - if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error;+ if (!STACK_INIT(&context, nodes, yaml_node_t*)) goto error; if (version_directive) {- version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t));+ version_directive_copy = YAML_MALLOC_STATIC(yaml_version_directive_t); if (!version_directive_copy) goto error; version_directive_copy->major = version_directive->major; version_directive_copy->minor = version_directive->minor;@@ -1075,7 +1076,7 @@ if (tag_directives_start != tag_directives_end) { yaml_tag_directive_t *tag_directive;- if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))+ if (!STACK_INIT(&context, tag_directives_copy, yaml_tag_directive_t*)) goto error; for (tag_directive = tag_directives_start; tag_directive != tag_directives_end; tag_directive ++) {@@ -1228,7 +1229,7 @@ } if (!yaml_check_utf8(value, length)) goto error;- value_copy = yaml_malloc(length+1);+ value_copy = YAML_MALLOC(length+1); if (!value_copy) goto error; memcpy(value_copy, value, length); value_copy[length] = '\0';@@ -1275,7 +1276,7 @@ tag_copy = yaml_strdup(tag); if (!tag_copy) goto error; - if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error;+ if (!STACK_INIT(&context, items, yaml_node_item_t*)) goto error; SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, style, mark, mark);@@ -1320,7 +1321,7 @@ tag_copy = yaml_strdup(tag); if (!tag_copy) goto error; - if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error;+ if (!STACK_INIT(&context, pairs, yaml_node_pair_t*)) goto error; MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, style, mark, mark);
libyaml/dumper.c view
@@ -245,9 +245,9 @@ #define ANCHOR_TEMPLATE_LENGTH 16 static yaml_char_t *-yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id)+yaml_emitter_generate_anchor(SHIM(yaml_emitter_t *emitter), int anchor_id) {- yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH);+ yaml_char_t *anchor = YAML_MALLOC(ANCHOR_TEMPLATE_LENGTH); if (!anchor) return NULL;
libyaml/emitter.c view
@@ -1002,7 +1002,7 @@ */ static int-yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event)+yaml_emitter_emit_alias(yaml_emitter_t *emitter, SHIM(yaml_event_t *event)) { if (!yaml_emitter_process_anchor(emitter)) return 0;@@ -1087,7 +1087,7 @@ */ static int-yaml_emitter_check_empty_document(yaml_emitter_t *emitter)+yaml_emitter_check_empty_document(SHIM(yaml_emitter_t *emitter)) { return 0; }
libyaml/loader.c view
@@ -72,7 +72,7 @@ assert(document); /* Non-NULL document object is expected. */ memset(document, 0, sizeof(yaml_document_t));- if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, document->nodes, yaml_node_t*)) goto error; if (!parser->stream_start_produced) {@@ -90,7 +90,7 @@ return 1; } - if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, parser->aliases, yaml_alias_data_t*)) goto error; parser->document = document;@@ -339,7 +339,7 @@ if (!tag) goto error; } - if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error;+ if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error; SEQUENCE_NODE_INIT(node, tag, items.start, items.end, first_event->data.sequence_start.style,@@ -402,7 +402,7 @@ if (!tag) goto error; } - if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error;+ if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error; MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, first_event->data.mapping_start.style,
libyaml/parser.c view
@@ -605,7 +605,7 @@ if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) { size_t prefix_len = strlen((char *)tag_directive->prefix); size_t suffix_len = strlen((char *)tag_suffix);- tag = yaml_malloc(prefix_len+suffix_len+1);+ tag = YAML_MALLOC(prefix_len+suffix_len+1); if (!tag) { parser->error = YAML_MEMORY_ERROR; goto error;@@ -685,7 +685,7 @@ return 1; } else if (anchor || tag) {- yaml_char_t *value = yaml_malloc(1);+ yaml_char_t *value = YAML_MALLOC(1); if (!value) { parser->error = YAML_MEMORY_ERROR; goto error;@@ -759,9 +759,8 @@ else if (token->type == YAML_BLOCK_END_TOKEN) {- yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ parser->state = POP(parser, parser->states);- dummy_mark = POP(parser, parser->marks);+ (void)POP(parser, parser->marks); SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); SKIP_TOKEN(parser); return 1;@@ -869,9 +868,8 @@ else if (token->type == YAML_BLOCK_END_TOKEN) {- yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ parser->state = POP(parser, parser->states);- dummy_mark = POP(parser, parser->marks);+ (void)POP(parser, parser->marks); MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); SKIP_TOKEN(parser); return 1;@@ -952,7 +950,6 @@ yaml_event_t *event, int first) { yaml_token_t *token;- yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ if (first) { token = PEEK_TOKEN(parser);@@ -997,7 +994,7 @@ } parser->state = POP(parser, parser->states);- dummy_mark = POP(parser, parser->marks);+ (void)POP(parser, parser->marks); SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); SKIP_TOKEN(parser); return 1;@@ -1104,7 +1101,6 @@ yaml_event_t *event, int first) { yaml_token_t *token;- yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ if (first) { token = PEEK_TOKEN(parser);@@ -1158,7 +1154,7 @@ } parser->state = POP(parser, parser->states);- dummy_mark = POP(parser, parser->marks);+ (void)POP(parser, parser->marks); MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); SKIP_TOKEN(parser); return 1;@@ -1212,7 +1208,7 @@ { yaml_char_t *value; - value = yaml_malloc(1);+ value = YAML_MALLOC(1); if (!value) { parser->error = YAML_MEMORY_ERROR; return 0;@@ -1249,7 +1245,7 @@ } tag_directives = { NULL, NULL, NULL }; yaml_token_t *token; - if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE))+ if (!STACK_INIT(parser, tag_directives, yaml_tag_directive_t*)) goto error; token = PEEK_TOKEN(parser);@@ -1270,7 +1266,7 @@ "found incompatible YAML document", token->start_mark); goto error; }- version_directive = yaml_malloc(sizeof(yaml_version_directive_t));+ version_directive = YAML_MALLOC_STATIC(yaml_version_directive_t); if (!version_directive) { parser->error = YAML_MEMORY_ERROR; goto error;
libyaml/reader.c view
@@ -460,10 +460,10 @@ } - if (parser->offset >= PTRDIFF_MAX)+ if (parser->offset >= MAX_FILE_SIZE) { return yaml_parser_set_reader_error(parser, "input is too long",- PTRDIFF_MAX, -1);+ parser->offset, -1);+ } return 1; }-
libyaml/scanner.c view
@@ -1186,11 +1186,9 @@ static int yaml_parser_decrease_flow_level(yaml_parser_t *parser) {- yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */- if (parser->flow_level) { parser->flow_level --;- dummy_key = POP(parser, parser->simple_keys);+ (void)POP(parser, parser->simple_keys); } return 1;@@ -2401,7 +2399,7 @@ { /* Set the handle to '' */ - handle = yaml_malloc(1);+ handle = YAML_MALLOC(1); if (!handle) goto error; handle[0] = '\0'; @@ -2453,7 +2451,7 @@ /* Set the handle to '!'. */ yaml_free(handle);- handle = yaml_malloc(2);+ handle = YAML_MALLOC(2); if (!handle) goto error; handle[0] = '!'; handle[1] = '\0';@@ -3164,10 +3162,6 @@ case '/': *(string.pointer++) = '/';- break;-- case '\'':- *(string.pointer++) = '\''; break; case '\\':
libyaml/yaml.h view
@@ -1091,7 +1091,7 @@ yaml_error_type_t error; /** Error description. */ const char *problem;- /** The byte about which the problem occurred. */+ /** The byte about which the problem occured. */ size_t problem_offset; /** The problematic value (@c -1 is none). */ int problem_value;@@ -1940,8 +1940,8 @@ * * The documen object may be generated using the yaml_parser_load() function * or the yaml_document_initialize() function. The emitter takes the- * responsibility for the document object and destoys its content after- * it is emitted. The document object is destroyedeven if the function fails.+ * responsibility for the document object and destroys its content after+ * it is emitted. The document object is destroyed even if the function fails. * * @param[in,out] emitter An emitter object. * @param[in,out] document A document object.
libyaml/yaml_private.h view
@@ -8,16 +8,6 @@ #include <limits.h> #include <stddef.h> -#ifndef _MSC_VER-#include <stdint.h>-#else-#ifdef _WIN64-#define PTRDIFF_MAX _I64_MAX-#else-#define PTRDIFF_MAX INT_MAX-#endif-#endif- /* * Memory management. */@@ -77,6 +67,17 @@ #define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2) /*+ * The maximum size of a YAML input file.+ * This used to be PTRDIFF_MAX, but that's not entirely portable+ * because stdint.h isn't available on all platforms.+ * It is not entirely clear why this isn't the maximum value+ * that can fit into the parser->offset field.+ */++#define MAX_FILE_SIZE (~(size_t)0 / 2)+++/* * The size of other stacks and queues. */ @@ -89,7 +90,7 @@ */ #define BUFFER_INIT(context,buffer,size) \- (((buffer).start = yaml_malloc(size)) ? \+ (((buffer).start = (yaml_char_t *)yaml_malloc(size)) ? \ ((buffer).last = (buffer).pointer = (buffer).start, \ (buffer).end = (buffer).start+(size), \ 1) : \@@ -129,7 +130,7 @@ (value).pointer = (string)) #define STRING_INIT(context,string,size) \- (((string).start = yaml_malloc(size)) ? \+ (((string).start = YAML_MALLOC(size)) ? \ ((string).pointer = (string).start, \ (string).end = (string).start+(size), \ memset((string).start, 0, (size)), \@@ -419,10 +420,10 @@ YAML_DECLARE(int) yaml_queue_extend(void **start, void **head, void **tail, void **end); -#define STACK_INIT(context,stack,size) \- (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \+#define STACK_INIT(context,stack,type) \+ (((stack).start = (type)yaml_malloc(INITIAL_STACK_SIZE*sizeof(*(stack).start))) ? \ ((stack).top = (stack).start, \- (stack).end = (stack).start+(size), \+ (stack).end = (stack).start+INITIAL_STACK_SIZE, \ 1) : \ ((context)->error = YAML_MEMORY_ERROR, \ 0))@@ -452,8 +453,8 @@ #define POP(context,stack) \ (*(--(stack).top)) -#define QUEUE_INIT(context,queue,size) \- (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \+#define QUEUE_INIT(context,queue,size,type) \+ (((queue).start = (type)yaml_malloc((size)*sizeof(*(queue).start))) ? \ ((queue).head = (queue).tail = (queue).start, \ (queue).end = (queue).start+(size), \ 1) : \@@ -657,8 +658,33 @@ (node).data.mapping.pairs.top = (node_pairs_start), \ (node).data.mapping.style = (node_style)) +/* Strict C compiler warning helpers */++#if defined(__clang__) || defined(__GNUC__)+# define HASATTRIBUTE_UNUSED+#endif+#ifdef HASATTRIBUTE_UNUSED+# define __attribute__unused__ __attribute__((__unused__))+#else+# define __attribute__unused__+#endif++/* Shim arguments are arguments that must be included in your function,+ * but serve no purpose inside. Silence compiler warnings. */+#define SHIM(a) /*@unused@*/ a __attribute__unused__++/* UNUSED_PARAM() marks a shim argument in the body to silence compiler warnings */+#ifdef __clang__+# define UNUSED_PARAM(a) (void)(a);+#else+# define UNUSED_PARAM(a) /*@-noeffect*/if (0) (void)(a)/*@=noeffect*/;+#endif++#define YAML_MALLOC_STATIC(type) (type*)yaml_malloc(sizeof(type))+#define YAML_MALLOC(size) (yaml_char_t *)yaml_malloc(size)+ /* For Haskell yaml package, since we do not use the configure script */-#define YAML_VERSION_STRING "0.1.7"+#define YAML_VERSION_STRING "0.2.1" #define YAML_VERSION_MAJOR 0-#define YAML_VERSION_MINOR 1-#define YAML_VERSION_PATCH 7+#define YAML_VERSION_MINOR 2+#define YAML_VERSION_PATCH 1
test/Data/YamlSpec.hs view
@@ -46,6 +46,11 @@ deriveJSON defaultOptions ''TestJSON +shouldDecode :: (Show a, D.FromJSON a, Eq a) => B8.ByteString -> a -> IO ()+shouldDecode bs expected = do+ actual <- D.decodeThrow bs+ actual `shouldBe` expected+ main :: IO () main = hspec spec @@ -120,13 +125,13 @@ describe "special keys" $ do let tester key = it (T.unpack key) $ let value = object [key .= True]- in D.decode (D.encode value) `shouldBe` Just value+ in D.encode value `shouldDecode` value mapM_ tester specialStrings describe "special values" $ do let tester value = it (T.unpack value) $ let value' = object ["foo" .= value]- in D.decode (D.encode value') `shouldBe` Just value'+ in D.encode value' `shouldDecode` value' mapM_ tester specialStrings describe "decodeFileEither" $ do@@ -149,13 +154,13 @@ let special = words "y Y On ON false 12345 12345.0 12345a 12e3" forM_ special $ \w -> it w $ let v = object ["word" .= w]- in D.decode (D.encode v) `shouldBe` Just v+ in D.encode v `shouldDecode` v it "no tags" $ D.encode (object ["word" .= ("true" :: String)]) `shouldBe` "word: 'true'\n" it "aliases in keys #49" caseIssue49 it "serialization of +123 #64" $ do- D.decode (D.encode ("+123" :: String)) `shouldBe` Just ("+123" :: String)+ D.encode ("+123" :: String) `shouldDecode` ("+123" :: String) it "preserves Scientific precision" casePreservesScientificPrecision @@ -299,9 +304,6 @@ mappingKey (D.Object m) k = (fromJust . M.lookup (T.pack k) $ m) mappingKey _ _ = error "expected Object" -decodeYaml :: String -> Maybe D.Value-decodeYaml s = D.decode $ B8.pack s- sample :: D.Value sample = array [ D.String "foo"@@ -313,20 +315,17 @@ ] caseEncodeDecodeData :: Assertion-caseEncodeDecodeData = do- let out = D.decode $ D.encode sample- out @?= Just sample+caseEncodeDecodeData = D.encode sample `shouldDecode` sample caseEncodeDecodeDataPretty :: Assertion-caseEncodeDecodeDataPretty = do- let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample- out @?= Just sample+caseEncodeDecodeDataPretty =+ Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample caseEncodeDecodeFileData :: Assertion caseEncodeDecodeFileData = withFile "" $ \fp -> do D.encodeFile fp sample- out <- D.decodeFile fp- out @?= Just sample+ out <- D.decodeFileThrow fp+ out @?= sample caseEncodeDecodeNonAsciiFileData :: Assertion caseEncodeDecodeNonAsciiFileData = do@@ -334,89 +333,74 @@ inTempDirectory $ do createDirectory "accenté" D.encodeFile "accenté/bar.yaml" mySample- out1 <- D.decodeFile "accenté/bar.yaml"- out1 @?= Just mySample+ out1 <- D.decodeFileThrow "accenté/bar.yaml"+ out1 @?= mySample c <- readFile "test/resources/accent/foo.yaml" inTempDirectory $ do createDirectoryIfMissing True "test/resources/unicode/accenté/" writeFile "test/resources/unicode/accenté/foo.yaml" c- out2 <- D.decodeFile "test/resources/unicode/accenté/foo.yaml"- out2 @?= Just mySample+ out2 <- D.decodeFileThrow "test/resources/unicode/accenté/foo.yaml"+ out2 @?= mySample caseEncodeDecodeStrings :: Assertion-caseEncodeDecodeStrings = do- let out = D.decode $ D.encode sample- out @?= Just sample+caseEncodeDecodeStrings = D.encode sample `shouldDecode` sample caseEncodeDecodeStringsPretty :: Assertion-caseEncodeDecodeStringsPretty = do- let out = D.decode $ Pretty.encodePretty Pretty.defConfig sample- out @?= Just sample+caseEncodeDecodeStringsPretty =+ Pretty.encodePretty Pretty.defConfig sample `shouldDecode` sample caseDecodeInvalid :: Assertion-caseDecodeInvalid = do- let invalid = B8.pack "\tthis is 'not' valid :-)"- Nothing @=? (D.decode invalid :: Maybe D.Value)+caseDecodeInvalid =+ D.decodeThrow "\tthis is 'not' valid :-)" `shouldBe`+ (Nothing :: Maybe D.Value) caseSimpleScalarAlias :: Assertion-caseSimpleScalarAlias = do- let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")]+caseSimpleScalarAlias =+ "- &anch foo\n- baz\n- *anch" `shouldDecode`+ array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo")] caseSimpleSequenceAlias :: Assertion-caseSimpleSequenceAlias = do- let maybeRes = decodeYaml "seq: &anch\n - foo\n - baz\nseq2: *anch"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- res @?= object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])]+caseSimpleSequenceAlias =+ "seq: &anch\n - foo\n - baz\nseq2: *anch" `shouldDecode`+ object [("seq", array [(mkScalar "foo"), (mkScalar "baz")]), ("seq2", array [(mkScalar "foo"), (mkScalar "baz")])] caseSimpleMappingAlias :: Assertion-caseSimpleMappingAlias = do- let maybeRes = decodeYaml "map: &anch\n key1: foo\n key2: baz\nmap2: *anch"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- res @?= object [(T.pack "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (T.pack "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])]+caseSimpleMappingAlias =+ "map: &anch\n key1: foo\n key2: baz\nmap2: *anch" `shouldDecode`+ object [(T.pack "map", object [("key1", mkScalar "foo"), ("key2", (mkScalar "baz"))]), (T.pack "map2", object [("key1", (mkScalar "foo")), ("key2", mkScalar "baz")])] caseMappingAliasBeforeAnchor :: Assertion-caseMappingAliasBeforeAnchor = do- let res = decodeYaml "map: *anch\nmap2: &anch\n key1: foo\n key2: baz"- isNothing res @? "decode should return Nothing due to unknown alias"+caseMappingAliasBeforeAnchor =+ case D.decodeThrow "map: *anch\nmap2: &anch\n key1: foo\n key2: baz" of+ Nothing -> pure ()+ Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias" caseMappingAliasInsideAnchor :: Assertion caseMappingAliasInsideAnchor = do- let res = decodeYaml "map: &anch\n key1: foo\n key2: *anch"- isNothing res @? "decode should return Nothing due to unknown alias"+ case D.decodeThrow "map: &anch\n key1: foo\n key2: *anch" of+ Nothing -> pure ()+ Just (_ :: D.Value) -> error "decode should return Nothing due to unknown alias" caseScalarAliasOverriding :: Assertion-caseScalarAliasOverriding = do- let maybeRes = decodeYaml "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- res @?= array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")]+caseScalarAliasOverriding =+ "- &anch foo\n- baz\n- *anch\n- &anch boo\n- buz\n- *anch" `shouldDecode`+ array [(mkScalar "foo"), (mkScalar "baz"), (mkScalar "foo"), (mkScalar "boo"), (mkScalar "buz"), (mkScalar "boo")] caseAllKeysShouldBeUnique :: Assertion caseAllKeysShouldBeUnique = do- let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\nfoo1: buz"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- mappingKey res "foo1" @?= (mkScalar "buz")+ res <- D.decodeThrow "foo1: foo\nfoo2: baz\nfoo1: buz"+ mappingKey res "foo1" `shouldBe` mkScalar "buz" caseSimpleMappingMerge :: Assertion caseSimpleMappingMerge = do- let maybeRes = decodeYaml "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes- mappingKey res "foo1" @?= (mkScalar "foo")- mappingKey res "foo3" @?= (mkScalar "fuz")+ res <- D.decodeThrow "foo1: foo\nfoo2: baz\n<<:\n foo1: buz\n foo3: fuz"+ mappingKey res "foo1" `shouldBe` mkScalar "foo"+ mappingKey res "foo3" `shouldBe` mkScalar "fuz" caseMergeSequence :: Assertion caseMergeSequence = do- 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 ]"- isJust maybeRes @? "decoder should return Just YamlObject but returned Nothing"- let res = fromJust maybeRes+ 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 ]" mappingKey res "foo1" @?= (mkScalar "foo") mappingKey res "k1" @?= (D.String "1") mappingKey res "k2" @?= (D.String "2")@@ -424,7 +408,7 @@ caseDataTypes :: Assertion caseDataTypes =- D.decode (D.encode val) @?= Just val+ D.encode val `shouldDecode` val where val = object [ ("string", D.String "foo")@@ -437,11 +421,11 @@ caseEncodeInvalidNumbers :: Assertion caseEncodeInvalidNumbers =- D.encode (D.String ".") @?= ".\n"+ D.encode (D.String ".") `shouldBe` ".\n" caseDataTypesPretty :: Assertion caseDataTypesPretty =- D.decode (Pretty.encodePretty Pretty.defConfig val) @?= Just val+ Pretty.encodePretty Pretty.defConfig val `shouldDecode` val where val = object [ ("string", D.String "foo")@@ -452,21 +436,21 @@ , ("null", D.Null) ] caseQuotedNumber, caseUnquotedNumber, caseAttribNumber, caseIntegerDecimals :: Assertion-caseQuotedNumber = D.decode "foo: \"1234\"" @?= Just (object [("foo", D.String "1234")])-caseUnquotedNumber = D.decode "foo: 1234" @?= Just (object [("foo", D.Number 1234)])-caseAttribNumber = D.decode "foo: !!str 1234" @?= Just (object [("foo", D.String "1234")])-caseIntegerDecimals = D.encode (1 :: Int) @?= "1\n"+caseQuotedNumber = "foo: \"1234\"" `shouldDecode` object [("foo", D.String "1234")]+caseUnquotedNumber = "foo: 1234" `shouldDecode` object [("foo", D.Number 1234)]+caseAttribNumber = "foo: !!str 1234" `shouldDecode` object [("foo", D.String "1234")]+caseIntegerDecimals = "1\n" `shouldDecode` (1 :: Int) -obj :: Maybe D.Value-obj = Just (object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)])+obj :: D.Value+obj = object [("foo", D.Bool False), ("bar", D.Bool True), ("baz", D.Bool True)] caseLowercaseBool, caseUppercaseBool, caseTitlecaseBool :: Assertion-caseLowercaseBool = D.decode "foo: off\nbar: y\nbaz: true" @?= obj-caseUppercaseBool = D.decode "foo: FALSE\nbar: Y\nbaz: ON" @?= obj-caseTitlecaseBool = D.decode "foo: No\nbar: Yes\nbaz: True" @?= obj+caseLowercaseBool = "foo: off\nbar: y\nbaz: true" `shouldDecode` obj+caseUppercaseBool = "foo: FALSE\nbar: Y\nbaz: ON" `shouldDecode` obj+caseTitlecaseBool = "foo: No\nbar: Yes\nbaz: True" `shouldDecode` obj caseEmptyInput :: Assertion-caseEmptyInput = D.decodeEither B8.empty @?= Right D.Null+caseEmptyInput = B8.empty `shouldDecode` D.Null caseEmptyInputFile :: Assertion caseEmptyInputFile = do@@ -474,7 +458,7 @@ either (Left . D.prettyPrintParseException) Right out @?= Right D.Null caseCommentOnlyInput :: Assertion-caseCommentOnlyInput = D.decodeEither "# comment\n" @?= Right D.Null+caseCommentOnlyInput = "# comment\n" `shouldDecode` D.Null caseCommentOnlyInputFile :: Assertion caseCommentOnlyInputFile = do@@ -483,13 +467,12 @@ checkNull :: T.Text -> Spec checkNull x =- it ("null recognized: " ++ show x) assertion- where- assertion = Just (object [("foo", D.Null)]) @=? D.decode (B8.pack $ "foo: " ++ T.unpack x)+ it ("null recognized: " ++ show x) $+ B8.pack ("foo: " ++ T.unpack x) `shouldDecode` object [("foo", D.Null)] caseStripAlias :: Assertion caseStripAlias =- D.decode src @?= Just (object+ src `shouldDecode` object [ "Default" .= object [ "foo" .= (1 :: Int) , "bar" .= (2 :: Int)@@ -499,24 +482,24 @@ , "bar" .= (2 :: Int) , "key" .= (3 :: Int) ]- ])+ ] where src = "Default: &def\n foo: 1\n bar: 2\nObj:\n <<: *def\n key: 3\n" caseIssue49 :: Assertion caseIssue49 =- D.decodeEither src @?= Right (object+ src `shouldDecode` object [ "a" .= object [ "value" .= (1.0 :: Double) ] , "b" .= object [ "value" .= (1.2 :: Double) ]- ])+ ] where src = "---\na:\n &id5 value: 1.0\nb:\n *id5: 1.2" -- | We cannot guarantee this before aeson started using 'Scientific'. casePreservesScientificPrecision :: Assertion casePreservesScientificPrecision = do- D.decodeEither "x: 1e-100000" @?= Right (object- [ "x" .= D.Number (read "1e-100000") ])+ "x: 1e-100000" `shouldDecode` object+ [ "x" .= D.Number (read "1e-100000") ] -- Note that this ought to work also without 'Scientific', given -- that @read (show "9.78159610558926e-5") == 9.78159610558926e-5@. -- However, it didn't work (and still doesn't work with aeson < 0.7)@@ -526,8 +509,8 @@ -- can be; -- * Even if we used 'Data.Text.Read.rational' we would not get good -- results, because of <https://github.com/bos/text/issues/34>.- D.decodeEither "x: 9.78159610558926e-5" @?= Right (object- [ "x" .= D.Number (read "9.78159610558926e-5") ])+ "x: 9.78159610558926e-5" `shouldDecode` object+ [ "x" .= D.Number (read "9.78159610558926e-5") ] caseTruncatesFiles :: Assertion caseTruncatesFiles = withSystemTempFile "truncate.yaml" $ \fp h -> do
yaml.cabal view
@@ -1,5 +1,5 @@ name: yaml-version: 0.8.30+version: 0.8.31 license: BSD3 license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov@@ -46,7 +46,9 @@ library other-extensions: LambdaCase- build-depends: base >= 4 && < 5+ if impl(ghc < 8.0.2)+ buildable: False+ build-depends: base >= 4.9.1 && < 5 , transformers >= 0.1 , bytestring >= 0.9.1.4 , conduit >= 1.2.8 && < 1.4