Merge pull request #103 from Herringway/kill-whitespace-errors-dead

Kill whitespace errors dead, finally
This commit is contained in:
Sebastian Wilzbach 2018-04-10 04:21:56 +02:00 committed by GitHub
commit 02cbf4d459
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 163 additions and 166 deletions

View file

@ -108,7 +108,7 @@ final class Composer
Node getNode() @safe Node getNode() @safe
{ {
//Get the root node of the next document. //Get the root node of the next document.
assert(!parser_.checkEvent(EventID.StreamEnd), assert(!parser_.checkEvent(EventID.StreamEnd),
"Trying to get a node from Composer when there is no node to " ~ "Trying to get a node from Composer when there is no node to " ~
"get. use checkNode() to determine if there is a node."); "get. use checkNode() to determine if there is a node.");
@ -118,7 +118,7 @@ final class Composer
///Get single YAML document, throwing if there is more than one document. ///Get single YAML document, throwing if there is more than one document.
Node getSingleNode() @trusted Node getSingleNode() @trusted
{ {
assert(!parser_.checkEvent(EventID.StreamEnd), assert(!parser_.checkEvent(EventID.StreamEnd),
"Trying to get a node from Composer when there is no node to " ~ "Trying to get a node from Composer when there is no node to " ~
"get. use checkNode() to determine if there is a node."); "get. use checkNode() to determine if there is a node.");
@ -141,7 +141,7 @@ final class Composer
/// ///
///Params: pairAppenderLevel = Current level in the pair appender stack. ///Params: pairAppenderLevel = Current level in the pair appender stack.
/// nodeAppenderLevel = Current level the node appender stack. /// nodeAppenderLevel = Current level the node appender stack.
void ensureAppendersExist(const uint pairAppenderLevel, const uint nodeAppenderLevel) void ensureAppendersExist(const uint pairAppenderLevel, const uint nodeAppenderLevel)
@trusted @trusted
{ {
while(pairAppenders_.length <= pairAppenderLevel) while(pairAppenders_.length <= pairAppenderLevel)
@ -235,10 +235,10 @@ final class Composer
Node composeScalarNode() @safe Node composeScalarNode() @safe
{ {
immutable event = parser_.getEvent(); immutable event = parser_.getEvent();
const tag = resolver_.resolve(NodeID.Scalar, event.tag, event.value, const tag = resolver_.resolve(NodeID.Scalar, event.tag, event.value,
event.implicit); event.implicit);
Node node = constructor_.node(event.startMark, event.endMark, tag, Node node = constructor_.node(event.startMark, event.endMark, tag,
event.value, event.scalarStyle); event.value, event.scalarStyle);
return node; return node;
@ -248,14 +248,14 @@ final class Composer
/// ///
/// Params: pairAppenderLevel = Current level of the pair appender stack. /// Params: pairAppenderLevel = Current level of the pair appender stack.
/// nodeAppenderLevel = Current level of the node appender stack. /// nodeAppenderLevel = Current level of the node appender stack.
Node composeSequenceNode(const uint pairAppenderLevel, const uint nodeAppenderLevel) Node composeSequenceNode(const uint pairAppenderLevel, const uint nodeAppenderLevel)
@system @system
{ {
ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel); ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel);
auto nodeAppender = &(nodeAppenders_[nodeAppenderLevel]); auto nodeAppender = &(nodeAppenders_[nodeAppenderLevel]);
immutable startEvent = parser_.getEvent(); immutable startEvent = parser_.getEvent();
const tag = resolver_.resolve(NodeID.Sequence, startEvent.tag, null, const tag = resolver_.resolve(NodeID.Sequence, startEvent.tag, null,
startEvent.implicit); startEvent.implicit);
while(!parser_.checkEvent(EventID.SequenceEnd)) while(!parser_.checkEvent(EventID.SequenceEnd))
@ -319,7 +319,7 @@ final class Composer
} }
foreach(node; toMerge) foreach(node; toMerge)
{ {
merge(*pairAppender, flatten(node, startMark, endMark, merge(*pairAppender, flatten(node, startMark, endMark,
pairAppenderLevel + 1, nodeAppenderLevel)); pairAppenderLevel + 1, nodeAppenderLevel));
} }
} }
@ -327,7 +327,7 @@ final class Composer
else if(root.isSequence) foreach(ref Node node; root) else if(root.isSequence) foreach(ref Node node; root)
{ {
if(!node.isType!(Node.Pair[])){error(node);} if(!node.isType!(Node.Pair[])){error(node);}
merge(*pairAppender, flatten(node, startMark, endMark, merge(*pairAppender, flatten(node, startMark, endMark,
pairAppenderLevel + 1, nodeAppenderLevel)); pairAppenderLevel + 1, nodeAppenderLevel));
} }
else else
@ -350,14 +350,14 @@ final class Composer
{ {
ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel); ensureAppendersExist(pairAppenderLevel, nodeAppenderLevel);
immutable startEvent = parser_.getEvent(); immutable startEvent = parser_.getEvent();
const tag = resolver_.resolve(NodeID.Mapping, startEvent.tag, null, const tag = resolver_.resolve(NodeID.Mapping, startEvent.tag, null,
startEvent.implicit); startEvent.implicit);
auto pairAppender = &(pairAppenders_[pairAppenderLevel]); auto pairAppender = &(pairAppenders_[pairAppenderLevel]);
Tuple!(Node, Mark)[] toMerge; Tuple!(Node, Mark)[] toMerge;
while(!parser_.checkEvent(EventID.MappingEnd)) while(!parser_.checkEvent(EventID.MappingEnd))
{ {
auto pair = Node.Pair(composeNode(pairAppenderLevel + 1, nodeAppenderLevel), auto pair = Node.Pair(composeNode(pairAppenderLevel + 1, nodeAppenderLevel),
composeNode(pairAppenderLevel + 1, nodeAppenderLevel)); composeNode(pairAppenderLevel + 1, nodeAppenderLevel));
//Need to flatten and merge the node referred by YAMLMerge. //Need to flatten and merge the node referred by YAMLMerge.
@ -373,7 +373,7 @@ final class Composer
} }
foreach(node; toMerge) foreach(node; toMerge)
{ {
merge(*pairAppender, flatten(node[0], startEvent.startMark, node[1], merge(*pairAppender, flatten(node[0], startEvent.startMark, node[1],
pairAppenderLevel + 1, nodeAppenderLevel)); pairAppenderLevel + 1, nodeAppenderLevel));
} }

View file

@ -343,13 +343,13 @@ final class Constructor
/// Construct a _null _node. /// Construct a _null _node.
YAMLNull constructNull(ref Node node) @safe pure nothrow @nogc YAMLNull constructNull(ref Node node) @safe pure nothrow @nogc
{ {
return YAMLNull(); return YAMLNull();
} }
/// Construct a merge _node - a _node that merges another _node into a mapping. /// Construct a merge _node - a _node that merges another _node into a mapping.
YAMLMerge constructMerge(ref Node node) @safe pure nothrow @nogc YAMLMerge constructMerge(ref Node node) @safe pure nothrow @nogc
{ {
return YAMLMerge(); return YAMLMerge();
} }

View file

@ -123,7 +123,7 @@ struct Dumper
//catch(StreamException e) //catch(StreamException e)
catch(Exception e) catch(Exception e)
{ {
throw new YAMLException("Unable to open file " ~ filename ~ throw new YAMLException("Unable to open file " ~ filename ~
" for YAML dumping: " ~ e.msg); " for YAML dumping: " ~ e.msg);
} }
// need to destroy the File we constructed. // need to destroy the File we constructed.
@ -171,7 +171,7 @@ struct Dumper
///Set indentation width. 2 by default. Must not be zero. ///Set indentation width. 2 by default. Must not be zero.
@property void indent(uint indent) pure @safe nothrow @property void indent(uint indent) pure @safe nothrow
in in
{ {
assert(indent != 0, "Can't use zero YAML indent width"); assert(indent != 0, "Can't use zero YAML indent width");
} }
body body
@ -195,7 +195,7 @@ struct Dumper
@property void encoding(Encoding encoding) pure @safe nothrow @property void encoding(Encoding encoding) pure @safe nothrow
{ {
encoding_ = encoding; encoding_ = encoding;
} }
///Always explicitly write document start? ///Always explicitly write document start?
@property void explicitStart(bool explicit) pure @safe nothrow @property void explicitStart(bool explicit) pure @safe nothrow
@ -216,10 +216,10 @@ struct Dumper
} }
/** /**
* Specify tag directives. * Specify tag directives.
* *
* A tag directive specifies a shorthand notation for specifying _tags. * A tag directive specifies a shorthand notation for specifying _tags.
* Each tag directive associates a handle with a prefix. This allows for * Each tag directive associates a handle with a prefix. This allows for
* compact tag notation. * compact tag notation.
* *
* Each handle specified MUST start and end with a '!' character * Each handle specified MUST start and end with a '!' character
@ -262,13 +262,13 @@ struct Dumper
/** /**
* Dump one or more YAML _documents to the file/stream. * Dump one or more YAML _documents to the file/stream.
* *
* Note that while you can call dump() multiple times on the same * Note that while you can call dump() multiple times on the same
* dumper, you will end up writing multiple YAML "files" to the same * dumper, you will end up writing multiple YAML "files" to the same
* file/stream. * file/stream.
* *
* Params: documents = Documents to _dump (root nodes of the _documents). * Params: documents = Documents to _dump (root nodes of the _documents).
* *
* Throws: YAMLException on error (e.g. invalid nodes, * Throws: YAMLException on error (e.g. invalid nodes,
* unable to write to file/stream). * unable to write to file/stream).
*/ */
void dump(Node[] documents ...) @trusted void dump(Node[] documents ...) @trusted
@ -285,7 +285,7 @@ struct Dumper
} }
catch(YAMLException e) catch(YAMLException e)
{ {
throw new YAMLException("Unable to dump YAML to stream " throw new YAMLException("Unable to dump YAML to stream "
~ name_ ~ " : " ~ e.msg); ~ name_ ~ " : " ~ e.msg);
} }
} }
@ -310,7 +310,7 @@ struct Dumper
} }
catch(YAMLException e) catch(YAMLException e)
{ {
throw new YAMLException("Unable to emit YAML to stream " throw new YAMLException("Unable to emit YAML to stream "
~ name_ ~ " : " ~ e.msg); ~ name_ ~ " : " ~ e.msg);
} }
} }

View file

@ -68,13 +68,13 @@ private mixin FastCharSearch!"\n\u0085\u2028\u2029"d newlineSearch_;
private alias canFind = std.algorithm.canFind; private alias canFind = std.algorithm.canFind;
//Emits YAML events into a file/stream. //Emits YAML events into a file/stream.
struct Emitter struct Emitter
{ {
private: private:
alias dyaml.tagdirective.TagDirective TagDirective; alias dyaml.tagdirective.TagDirective TagDirective;
///Default tag handle shortcuts and replacements. ///Default tag handle shortcuts and replacements.
static TagDirective[] defaultTagDirectives_ = static TagDirective[] defaultTagDirectives_ =
[TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")]; [TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
///Stream to write to. ///Stream to write to.
@ -165,7 +165,7 @@ struct Emitter
* indent = Indentation width. * indent = Indentation width.
* lineBreak = Line break character/s. * lineBreak = Line break character/s.
*/ */
this(YStream stream, const bool canonical, const int indent, const int width, this(YStream stream, const bool canonical, const int indent, const int width,
const LineBreak lineBreak) @trusted const LineBreak lineBreak) @trusted
in{assert(stream.writeable, "Can't emit YAML to a non-writable stream");} in{assert(stream.writeable, "Can't emit YAML to a non-writable stream");}
body body
@ -200,9 +200,9 @@ struct Emitter
private: private:
///Pop and return the newest state in states_. ///Pop and return the newest state in states_.
void delegate() popState() @trusted void delegate() popState() @trusted
{ {
enforce(states_.length > 0, enforce(states_.length > 0,
new YAMLException("Emitter: Need to pop a state but there are no states left")); new YAMLException("Emitter: Need to pop a state but there are no states left"));
const result = states_.back; const result = states_.back;
states_.length = states_.length - 1; states_.length = states_.length - 1;
@ -212,7 +212,7 @@ struct Emitter
///Pop and return the newest indent in indents_. ///Pop and return the newest indent in indents_.
int popIndent() @trusted int popIndent() @trusted
{ {
enforce(indents_.length > 0, enforce(indents_.length > 0,
new YAMLException("Emitter: Need to pop an indent level but there" ~ new YAMLException("Emitter: Need to pop an indent level but there" ~
" are no indent levels left")); " are no indent levels left"));
const result = indents_.back; const result = indents_.back;
@ -261,7 +261,7 @@ struct Emitter
{ {
int level = 0; int level = 0;
//Rather ugly, but good enough for now. //Rather ugly, but good enough for now.
//Couldn't be bothered writing a range as events_ should eventually //Couldn't be bothered writing a range as events_ should eventually
//become a Phobos queue/linked list. //become a Phobos queue/linked list.
events_.startIteration(); events_.startIteration();
@ -347,7 +347,7 @@ struct Emitter
writeIndicator("...", Yes.needWhitespace); writeIndicator("...", Yes.needWhitespace);
writeIndent(); writeIndent();
} }
if(YAMLVersion !is null) if(YAMLVersion !is null)
{ {
writeVersionDirective(prepareVersion(YAMLVersion)); writeVersionDirective(prepareVersion(YAMLVersion));
@ -360,23 +360,23 @@ struct Emitter
foreach(ref pair; tagDirectives_) foreach(ref pair; tagDirectives_)
{ {
writeTagDirective(prepareTagHandle(pair.handle), writeTagDirective(prepareTagHandle(pair.handle),
prepareTagPrefix(pair.prefix)); prepareTagPrefix(pair.prefix));
} }
} }
bool eq(ref TagDirective a, ref TagDirective b){return a.handle == b.handle;} bool eq(ref TagDirective a, ref TagDirective b){return a.handle == b.handle;}
//Add any default tag directives that have not been overriden. //Add any default tag directives that have not been overriden.
foreach(ref def; defaultTagDirectives_) foreach(ref def; defaultTagDirectives_)
{ {
if(!std.algorithm.canFind!eq(tagDirectives_, def)) if(!std.algorithm.canFind!eq(tagDirectives_, def))
{ {
tagDirectives_ ~= def; tagDirectives_ ~= def;
} }
} }
const implicit = first && !event_.explicitDocument && !canonical_ && const implicit = first && !event_.explicitDocument && !canonical_ &&
YAMLVersion is null && tagDirectives is null && YAMLVersion is null && tagDirectives is null &&
!checkEmptyDocument(); !checkEmptyDocument();
if(!implicit) if(!implicit)
{ {
@ -669,14 +669,14 @@ struct Emitter
///Check if an empty sequence is next. ///Check if an empty sequence is next.
bool checkEmptySequence() const @trusted pure nothrow bool checkEmptySequence() const @trusted pure nothrow
{ {
return event_.id == EventID.SequenceStart && events_.length > 0 return event_.id == EventID.SequenceStart && events_.length > 0
&& events_.peek().id == EventID.SequenceEnd; && events_.peek().id == EventID.SequenceEnd;
} }
///Check if an empty mapping is next. ///Check if an empty mapping is next.
bool checkEmptyMapping() const @trusted pure nothrow bool checkEmptyMapping() const @trusted pure nothrow
{ {
return event_.id == EventID.MappingStart && events_.length > 0 return event_.id == EventID.MappingStart && events_.length > 0
&& events_.peek().id == EventID.MappingEnd; && events_.peek().id == EventID.MappingEnd;
} }
@ -695,12 +695,12 @@ struct Emitter
} }
///Check if a simple key is next. ///Check if a simple key is next.
bool checkSimpleKey() @trusted bool checkSimpleKey() @trusted
{ {
uint length = 0; uint length = 0;
const id = event_.id; const id = event_.id;
const scalar = id == EventID.Scalar; const scalar = id == EventID.Scalar;
const collectionStart = id == EventID.MappingStart || const collectionStart = id == EventID.MappingStart ||
id == EventID.SequenceStart; id == EventID.SequenceStart;
if((id == EventID.Alias || scalar || collectionStart) if((id == EventID.Alias || scalar || collectionStart)
@ -727,9 +727,9 @@ struct Emitter
if(length >= 128){return false;} if(length >= 128){return false;}
return id == EventID.Alias || return id == EventID.Alias ||
(scalar && !analysis_.flags.empty && !analysis_.flags.multiline) || (scalar && !analysis_.flags.empty && !analysis_.flags.multiline) ||
checkEmptySequence() || checkEmptySequence() ||
checkEmptyMapping(); checkEmptyMapping();
} }
@ -742,7 +742,7 @@ struct Emitter
style_ = chooseScalarStyle(); style_ = chooseScalarStyle();
} }
//if(analysis_.flags.multiline && (context_ != Context.MappingSimpleKey) && //if(analysis_.flags.multiline && (context_ != Context.MappingSimpleKey) &&
// ([ScalarStyle.Invalid, ScalarStyle.Plain, ScalarStyle.SingleQuoted, ScalarStyle.DoubleQuoted) // ([ScalarStyle.Invalid, ScalarStyle.Plain, ScalarStyle.SingleQuoted, ScalarStyle.DoubleQuoted)
// .canFind(style_)) // .canFind(style_))
//{ //{
@ -829,10 +829,10 @@ struct Emitter
const singleQuoted = style == ScalarStyle.SingleQuoted; const singleQuoted = style == ScalarStyle.SingleQuoted;
const doubleQuoted = style == ScalarStyle.DoubleQuoted; const doubleQuoted = style == ScalarStyle.DoubleQuoted;
const allowPlain = flowLevel_ > 0 ? analysis_.flags.allowFlowPlain const allowPlain = flowLevel_ > 0 ? analysis_.flags.allowFlowPlain
: analysis_.flags.allowBlockPlain; : analysis_.flags.allowBlockPlain;
//simple empty or multiline scalars can't be written in plain style //simple empty or multiline scalars can't be written in plain style
const simpleNonPlain = (context_ == Context.MappingSimpleKey) && const simpleNonPlain = (context_ == Context.MappingSimpleKey) &&
(analysis_.flags.empty || analysis_.flags.multiline); (analysis_.flags.empty || analysis_.flags.multiline);
if(doubleQuoted || canonical_) if(doubleQuoted || canonical_)
@ -845,14 +845,14 @@ struct Emitter
return ScalarStyle.Plain; return ScalarStyle.Plain;
} }
if(block && flowLevel_ == 0 && context_ != Context.MappingSimpleKey && if(block && flowLevel_ == 0 && context_ != Context.MappingSimpleKey &&
analysis_.flags.allowBlock) analysis_.flags.allowBlock)
{ {
return style; return style;
} }
if((invalidOrPlain || singleQuoted) && if((invalidOrPlain || singleQuoted) &&
analysis_.flags.allowSingleQuoted && analysis_.flags.allowSingleQuoted &&
!(context_ == Context.MappingSimpleKey && analysis_.flags.multiline)) !(context_ == Context.MappingSimpleKey && analysis_.flags.multiline))
{ {
return ScalarStyle.SingleQuoted; return ScalarStyle.SingleQuoted;
@ -942,7 +942,7 @@ struct Emitter
foreach(ref pair; tagDirectives_) foreach(ref pair; tagDirectives_)
{ {
auto prefix = pair.prefix; auto prefix = pair.prefix;
if(tagString.startsWith(prefix) && if(tagString.startsWith(prefix) &&
(prefix != "!" || prefix.length < tagString.length)) (prefix != "!" || prefix.length < tagString.length))
{ {
handle = pair.handle; handle = pair.handle;
@ -956,7 +956,7 @@ struct Emitter
size_t end = 0; size_t end = 0;
foreach(const dchar c; suffix) foreach(const dchar c; suffix)
{ {
if(isAlphaNum(c) || "-;/?:@&=+$,_.~*\'()[]"d.canFind(c) || if(isAlphaNum(c) || "-;/?:@&=+$,_.~*\'()[]"d.canFind(c) ||
(c == '!' && handle != "!")) (c == '!' && handle != "!"))
{ {
++end; ++end;
@ -1008,11 +1008,11 @@ struct Emitter
return analysis; return analysis;
} }
//Indicators and special characters (All false by default). //Indicators and special characters (All false by default).
bool blockIndicators, flowIndicators, lineBreaks, specialCharacters; bool blockIndicators, flowIndicators, lineBreaks, specialCharacters;
//Important whitespace combinations (All false by default). //Important whitespace combinations (All false by default).
bool leadingSpace, leadingBreak, trailingSpace, trailingBreak, bool leadingSpace, leadingBreak, trailingSpace, trailingBreak,
breakSpace, spaceBreak; breakSpace, spaceBreak;
//Check document indicators. //Check document indicators.
@ -1020,12 +1020,12 @@ struct Emitter
{ {
blockIndicators = flowIndicators = true; blockIndicators = flowIndicators = true;
} }
//First character or preceded by a whitespace. //First character or preceded by a whitespace.
bool preceededByWhitespace = true; bool preceededByWhitespace = true;
//Last character or followed by a whitespace. //Last character or followed by a whitespace.
bool followedByWhitespace = scalar.length == 1 || bool followedByWhitespace = scalar.length == 1 ||
" \t\0\n\r\u0085\u2028\u2029"d.canFind(scalar[1]); " \t\0\n\r\u0085\u2028\u2029"d.canFind(scalar[1]);
//The previous character is a space/break (false by default). //The previous character is a space/break (false by default).
@ -1077,7 +1077,7 @@ struct Emitter
{ {
specialCharacters = true; specialCharacters = true;
} }
//Detect important whitespace combinations. //Detect important whitespace combinations.
if(c == ' ') if(c == ' ')
{ {
@ -1103,16 +1103,16 @@ struct Emitter
mixin FastCharSearch! "\0\n\r\u0085\u2028\u2029 \t"d spaceSearch; mixin FastCharSearch! "\0\n\r\u0085\u2028\u2029 \t"d spaceSearch;
//Prepare for the next character. //Prepare for the next character.
preceededByWhitespace = spaceSearch.canFind(c); preceededByWhitespace = spaceSearch.canFind(c);
followedByWhitespace = index + 2 >= scalar.length || followedByWhitespace = index + 2 >= scalar.length ||
spaceSearch.canFind(scalar[index + 2]); spaceSearch.canFind(scalar[index + 2]);
} }
with(analysis.flags) with(analysis.flags)
{ {
//Let's decide what styles are allowed. //Let's decide what styles are allowed.
allowFlowPlain = allowBlockPlain = allowSingleQuoted allowFlowPlain = allowBlockPlain = allowSingleQuoted
= allowDoubleQuoted = allowBlock = true; = allowDoubleQuoted = allowBlock = true;
//Leading and trailing whitespaces are bad for plain scalars. //Leading and trailing whitespaces are bad for plain scalars.
if(leadingSpace || leadingBreak || trailingSpace || trailingBreak) if(leadingSpace || leadingBreak || trailingSpace || trailingBreak)
{ {
@ -1311,11 +1311,11 @@ struct ScalarWriter
resetTextPosition(); resetTextPosition();
do do
{ {
const dchar c = nextChar(); const dchar c = nextChar();
if(spaces_) if(spaces_)
{ {
if(c != ' ' && tooWide() && split_ && if(c != ' ' && tooWide() && split_ &&
startByte_ != 0 && endByte_ != text_.length) startByte_ != 0 && endByte_ != text_.length)
{ {
writeIndent(Flag!"ResetSpace".no); writeIndent(Flag!"ResetSpace".no);
@ -1359,11 +1359,11 @@ struct ScalarWriter
resetTextPosition(); resetTextPosition();
emitter_.writeIndicator("\"", Yes.needWhitespace); emitter_.writeIndicator("\"", Yes.needWhitespace);
do do
{ {
const dchar c = nextChar(); const dchar c = nextChar();
//handle special characters //handle special characters
if(c == dcharNone || "\"\\\u0085\u2028\u2029\uFEFF"d.canFind(c) || if(c == dcharNone || "\"\\\u0085\u2028\u2029\uFEFF"d.canFind(c) ||
!((c >= '\x20' && c <= '\x7E') || !((c >= '\x20' && c <= '\x7E') ||
((c >= '\xA0' && c <= '\uD7FF') || (c >= '\uE000' && c <= '\uFFFD')))) ((c >= '\xA0' && c <= '\uD7FF') || (c >= '\uE000' && c <= '\uFFFD'))))
{ {
if(startChar_ < endChar_) if(startChar_ < endChar_)
@ -1392,9 +1392,9 @@ struct ScalarWriter
startByte_ = nextEndByte_; startByte_ = nextEndByte_;
} }
} }
if((endByte_ > 0 && endByte_ < text_.length - strideBack(text_, text_.length)) if((endByte_ > 0 && endByte_ < text_.length - strideBack(text_, text_.length))
&& (c == ' ' || startChar_ >= endChar_) && (c == ' ' || startChar_ >= endChar_)
&& (emitter_.column_ + endChar_ - startChar_ > emitter_.bestWidth_) && (emitter_.column_ + endChar_ - startChar_ > emitter_.bestWidth_)
&& split_) && split_)
{ {
//text_[2:1] is ok in Python but not in D, so we have to use min() //text_[2:1] is ok in Python but not in D, so we have to use min()
@ -1425,7 +1425,7 @@ struct ScalarWriter
resetTextPosition(); resetTextPosition();
do do
{ {
const dchar c = nextChar(); const dchar c = nextChar();
if(breaks_) if(breaks_)
{ {
@ -1469,7 +1469,7 @@ struct ScalarWriter
resetTextPosition(); resetTextPosition();
do do
{ {
const dchar c = nextChar(); const dchar c = nextChar();
if(breaks_) if(breaks_)
{ {
@ -1503,7 +1503,7 @@ struct ScalarWriter
resetTextPosition(); resetTextPosition();
do do
{ {
const dchar c = nextChar(); const dchar c = nextChar();
if(spaces_) if(spaces_)
{ {
@ -1561,7 +1561,7 @@ struct ScalarWriter
///Is the current line too wide? ///Is the current line too wide?
@property bool tooWide() const pure @safe nothrow @property bool tooWide() const pure @safe nothrow
{ {
return startChar_ + 1 == endChar_ && return startChar_ + 1 == endChar_ &&
emitter_.column_ > emitter_.bestWidth_; emitter_.column_ > emitter_.bestWidth_;
} }
@ -1571,7 +1571,7 @@ struct ScalarWriter
size_t hintsIdx = 0; size_t hintsIdx = 0;
if(text_.length == 0){return hintsIdx;} if(text_.length == 0){return hintsIdx;}
dchar lastChar(const string str, ref size_t end) dchar lastChar(const string str, ref size_t end)
{ {
size_t idx = end = end - strideBack(str, end); size_t idx = end = end - strideBack(str, end);
return decode(text_, idx); return decode(text_, idx);

View file

@ -88,4 +88,3 @@ static this()
'\u2028': 'L', '\u2028': 'L',
'\u2029': 'P']; '\u2029': 'P'];
} }

View file

@ -120,7 +120,7 @@ template ExceptionCtors()
template MarkedExceptionCtors() template MarkedExceptionCtors()
{ {
public: public:
this(string context, const Mark contextMark, string problem, this(string context, const Mark contextMark, string problem,
const Mark problemMark, string file = __FILE__, size_t line = __LINE__) const Mark problemMark, string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @safe pure nothrow
{ {

View file

@ -24,7 +24,7 @@ package:
* Params: chars = String to search in. * Params: chars = String to search in.
* tableSize = Maximum number of bytes used by the table. * tableSize = Maximum number of bytes used by the table.
* *
* Generated method: * Generated method:
* bool canFind(dchar c) * bool canFind(dchar c)
* *
* Determines if a character is in the string. * Determines if a character is in the string.
@ -57,7 +57,7 @@ string searchCode(dstring chars, uint tableSize)()
return specialChars.map!(c => q{cast(uint)c == %s}.format(cast(uint)c)).join(q{ || }); return specialChars.map!(c => q{cast(uint)c == %s}.format(cast(uint)c)).join(q{ || });
} }
const caseInTable = const caseInTable =
q{ q{
if(c < %s) if(c < %s)
{ {
@ -68,21 +68,21 @@ string searchCode(dstring chars, uint tableSize)()
string code; string code;
if(tableSize) if(tableSize)
{ {
code ~= code ~=
q{ q{
static immutable ubyte[%s] table_ = [ static immutable ubyte[%s] table_ = [
%s]; %s];
}.format(tableSize, table[].map!(c => c ? q{true} : q{false}).join(q{, })); }.format(tableSize, table[].map!(c => c ? q{true} : q{false}).join(q{, }));
} }
code ~= code ~=
q{ q{
bool canFind(const dchar c) @safe pure nothrow @nogc bool canFind(const dchar c) @safe pure nothrow @nogc
{ {
%s %s
return %s; return %s;
} }
}.format(tableSize ? caseInTable : "", }.format(tableSize ? caseInTable : "",
specialChars.length ? specialCharsCode() : q{false}); specialChars.length ? specialCharsCode() : q{false});
return code; return code;

View file

@ -75,4 +75,3 @@ struct Flags(names ...) if(names.length <= 8)
flags.empty = false; flags.empty = false;
assert(flags.empty == false && flags.multiline == false); assert(flags.empty == false && flags.multiline == false);
} }

View file

@ -63,7 +63,7 @@ struct Loader
name_ = filename; name_ = filename;
try try
{ {
this(std.file.read(filename)); this(std.file.read(filename));
} }
catch(FileException e) catch(FileException e)
{ {

View file

@ -1026,7 +1026,7 @@ struct Node
/** Return a range object iterating over a sequence, getting each /** Return a range object iterating over a sequence, getting each
* element as T. * element as T.
* *
* If T is Node, simply iterate over the nodes in the sequence. * If T is Node, simply iterate over the nodes in the sequence.
* Otherwise, convert each node to T during iteration. * Otherwise, convert each node to T during iteration.
* *
@ -1052,10 +1052,10 @@ struct Node
/* Input range functionality. */ /* Input range functionality. */
bool empty() @property { return position >= subnodes.length; } bool empty() @property { return position >= subnodes.length; }
void popFront() void popFront()
{ {
enforce(!empty, "Attempted to popFront an empty sequence"); enforce(!empty, "Attempted to popFront an empty sequence");
position++; position++;
} }
T front() @property T front() @property
@ -1071,14 +1071,14 @@ struct Node
Range save() { return this; } Range save() { return this; }
/* Bidirectional range functionality. */ /* Bidirectional range functionality. */
void popBack() void popBack()
{ {
enforce(!empty, "Attempted to popBack an empty sequence"); enforce(!empty, "Attempted to popBack an empty sequence");
subnodes = subnodes[0 .. $ - 1]; subnodes = subnodes[0 .. $ - 1];
} }
T back() T back()
{ {
enforce(!empty, "Attempted to take the back of an empty sequence"); enforce(!empty, "Attempted to take the back of an empty sequence");
static if (is(Unqual!T == Node)) static if (is(Unqual!T == Node))
return subnodes[$ - 1]; return subnodes[$ - 1];

View file

@ -273,16 +273,16 @@ ValidateResult validateUTF8NoGC(const(char[]) str) @safe pure nothrow @nogc
/// ///
/// Params: /// Params:
/// ///
/// validated = If ture, assume str is a valid UTF-8 string and don't generate any /// validated = If ture, assume str is a valid UTF-8 string and don't generate any
/// error-checking code. If validated is true, str $(B must) be a valid /// error-checking code. If validated is true, str $(B must) be a valid
/// character, otherwise undefined behavior will occur. Also affects the /// character, otherwise undefined behavior will occur. Also affects the
/// return type. /// return type.
/// str = Will decode the first code point from this string. /// str = Will decode the first code point from this string.
/// index = Index in str where the code point starts. Will be updated to point to /// index = Index in str where the code point starts. Will be updated to point to
/// the next code point. /// the next code point.
/// ///
/// Returns: If validated is true, the decoded character. /// Returns: If validated is true, the decoded character.
/// Otherwise a struct with a 'decoded' member - the decoded character, and a /// Otherwise a struct with a 'decoded' member - the decoded character, and a
/// 'string errorMessage' member that is null on success and otherwise stores /// 'string errorMessage' member that is null on success and otherwise stores
/// the error message. /// the error message.
auto decodeUTF8NoGC(Flag!"validated" validated)(const(char[]) str, ref size_t index) auto decodeUTF8NoGC(Flag!"validated" validated)(const(char[]) str, ref size_t index)

View file

@ -102,7 +102,7 @@ class ParserException : MarkedYAMLException
/// Generates events from tokens provided by a Scanner. /// Generates events from tokens provided by a Scanner.
/// ///
/// While Parser receives tokens with non-const character slices, the events it /// While Parser receives tokens with non-const character slices, the events it
/// produces are immutable strings, which are usually the same slices, cast to string. /// produces are immutable strings, which are usually the same slices, cast to string.
/// Parser is the last layer of D:YAML that may possibly do any modifications to these /// Parser is the last layer of D:YAML that may possibly do any modifications to these
/// slices. /// slices.
@ -110,7 +110,7 @@ final class Parser
{ {
private: private:
///Default tag handle shortcuts and replacements. ///Default tag handle shortcuts and replacements.
static TagDirective[] defaultTagDirectives_ = static TagDirective[] defaultTagDirectives_ =
[TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")]; [TagDirective("!", "!"), TagDirective("!!", "tag:yaml.org,2002:")];
///Scanner providing YAML tokens. ///Scanner providing YAML tokens.

View file

@ -18,14 +18,14 @@ import std.traits;
package: package:
/// Simple queue implemented as a singly linked list with a tail pointer. /// Simple queue implemented as a singly linked list with a tail pointer.
/// ///
/// Needed in some D:YAML code that needs a queue-like structure without too much /// Needed in some D:YAML code that needs a queue-like structure without too much
/// reallocation that goes with an array. /// reallocation that goes with an array.
/// ///
/// This should be replaced once Phobos has a decent queue/linked list. /// This should be replaced once Phobos has a decent queue/linked list.
/// ///
/// Uses manual allocation through malloc/free. /// Uses manual allocation through malloc/free.
/// ///
/// Also has some features uncommon for a queue, e.g. iteration. Couldn't bother with /// Also has some features uncommon for a queue, e.g. iteration. Couldn't bother with
/// implementing a range, as this is used only as a placeholder until Phobos gets a /// implementing a range, as this is used only as a placeholder until Phobos gets a
/// decent replacement. /// decent replacement.
@ -88,7 +88,7 @@ struct Queue(T)
body body
{ {
const previous = cursor_; const previous = cursor_;
cursor_ = cursor_.next_; cursor_ = cursor_.next_;
return previous.payload_; return previous.payload_;
} }
@ -160,7 +160,7 @@ struct Queue(T)
} }
/// Return the next element in the queue. /// Return the next element in the queue.
ref inout(T) peek() @safe pure nothrow inout @nogc ref inout(T) peek() @safe pure nothrow inout @nogc
in in
{ {
assert(!empty, "Trying to peek at an element in an empty queue"); assert(!empty, "Trying to peek at an element in an empty queue");

View file

@ -5,8 +5,8 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
/** /**
* YAML node _representer. Prepares YAML nodes for output. A tutorial can be * YAML node _representer. Prepares YAML nodes for output. A tutorial can be
* found $(LINK2 ../tutorials/custom_types.html, here). * found $(LINK2 ../tutorials/custom_types.html, here).
* *
* Code based on $(LINK2 http://www.pyyaml.org, PyYAML). * Code based on $(LINK2 http://www.pyyaml.org, PyYAML).
*/ */
@ -60,13 +60,13 @@ final class Representer
/** /**
* Construct a Representer. * Construct a Representer.
* *
* Params: useDefaultRepresenters = Use default representer functions * Params: useDefaultRepresenters = Use default representer functions
* for default YAML types? This can be * for default YAML types? This can be
* disabled to use custom representer * disabled to use custom representer
* functions for default types. * functions for default types.
*/ */
this(const Flag!"useDefaultRepresenters" useDefaultRepresenters = Yes.useDefaultRepresenters) this(const Flag!"useDefaultRepresenters" useDefaultRepresenters = Yes.useDefaultRepresenters)
@safe pure @safe pure
{ {
if(!useDefaultRepresenters){return;} if(!useDefaultRepresenters){return;}
@ -94,7 +94,7 @@ final class Representer
defaultScalarStyle_ = style; defaultScalarStyle_ = style;
} }
///Set default _style for collections. If style is $(D CollectionStyle.Invalid), the _style is chosen automatically. ///Set default _style for collections. If style is $(D CollectionStyle.Invalid), the _style is chosen automatically.
@property void defaultCollectionStyle(CollectionStyle style) pure @safe nothrow @property void defaultCollectionStyle(CollectionStyle style) pure @safe nothrow
{ {
defaultCollectionStyle_ = style; defaultCollectionStyle_ = style;
@ -106,7 +106,6 @@ final class Representer
* The representer function takes references to a $(D Node) storing the data * The representer function takes references to a $(D Node) storing the data
* type and to the $(D Representer). It returns the represented node and may * type and to the $(D Representer). It returns the represented node and may
* throw a $(D RepresenterException). See the example for more information. * throw a $(D RepresenterException). See the example for more information.
*
* *
* *
* Only one function may be specified for one data type. Default data * Only one function may be specified for one data type. Default data
@ -114,10 +113,10 @@ final class Representer
* $(D Representer) constructor. * $(D Representer) constructor.
* *
* *
* Structs and classes must implement the $(D opCmp()) operator for D:YAML * Structs and classes must implement the $(D opCmp()) operator for D:YAML
* support. The signature of the operator that must be implemented * support. The signature of the operator that must be implemented
* is $(D const int opCmp(ref const MyStruct s)) for structs where * is $(D const int opCmp(ref const MyStruct s)) for structs where
* $(I MyStruct) is the struct type, and $(D int opCmp(Object o)) for * $(I MyStruct) is the struct type, and $(D int opCmp(Object o)) for
* classes. Note that the class $(D opCmp()) should not alter the compared * classes. Note that the class $(D opCmp()) should not alter the compared
* values - it is not const for compatibility reasons. * values - it is not const for compatibility reasons.
* *
@ -126,7 +125,7 @@ final class Representer
void addRepresenter(T)(Node function(ref Node, Representer) @safe representer) void addRepresenter(T)(Node function(ref Node, Representer) @safe representer)
@safe pure @safe pure
{ {
assert((typeid(T) in representers_) is null, assert((typeid(T) in representers_) is null,
"Representer function for data type " ~ T.stringof ~ "Representer function for data type " ~ T.stringof ~
" already specified. Can't specify another one"); " already specified. Can't specify another one");
representers_[typeid(T)] = representer; representers_[typeid(T)] = representer;
@ -223,7 +222,7 @@ final class Representer
} }
//If profiling shows a bottleneck on tag construction in these 3 methods, //If profiling shows a bottleneck on tag construction in these 3 methods,
//we'll need to take Tag directly and have string based wrappers for //we'll need to take Tag directly and have string based wrappers for
//user code. //user code.
/** /**
@ -238,7 +237,7 @@ final class Representer
* *
* Returns: The represented node. * Returns: The represented node.
*/ */
Node representScalar(string tag, string scalar, Node representScalar(string tag, string scalar,
ScalarStyle style = ScalarStyle.Invalid) @trusted ScalarStyle style = ScalarStyle.Invalid) @trusted
{ {
if(style == ScalarStyle.Invalid){style = defaultScalarStyle_;} if(style == ScalarStyle.Invalid){style = defaultScalarStyle_;}
@ -291,7 +290,7 @@ final class Representer
* *
* Throws: $(D RepresenterException) if a child could not be represented. * Throws: $(D RepresenterException) if a child could not be represented.
*/ */
Node representSequence(string tag, Node[] sequence, Node representSequence(string tag, Node[] sequence,
CollectionStyle style = CollectionStyle.Invalid) @trusted CollectionStyle style = CollectionStyle.Invalid) @trusted
{ {
Node[] value; Node[] value;
@ -393,7 +392,7 @@ final class Representer
if(style == CollectionStyle.Invalid) if(style == CollectionStyle.Invalid)
{ {
style = defaultCollectionStyle_ != CollectionStyle.Invalid style = defaultCollectionStyle_ != CollectionStyle.Invalid
? defaultCollectionStyle_ ? defaultCollectionStyle_
: bestStyle; : bestStyle;
} }
@ -442,7 +441,7 @@ final class Representer
auto type = data.isUserType ? data.as!YAMLObject.type : data.type; auto type = data.isUserType ? data.as!YAMLObject.type : data.type;
enforce((type in representers_) !is null, enforce((type in representers_) !is null,
new RepresenterException("No representer function for type " new RepresenterException("No representer function for type "
~ type.toString() ~ " , cannot represent.")); ~ type.toString() ~ " , cannot represent."));
Node result = representers_[type](data, this); Node result = representers_[type](data, this);
@ -480,8 +479,8 @@ Node representNull(ref Node node, Representer representer) @safe
Node representString(ref Node node, Representer representer) @safe Node representString(ref Node node, Representer representer) @safe
{ {
string value = node.as!string; string value = node.as!string;
return value is null return value is null
? representNull(node, representer) ? representNull(node, representer)
: representer.representScalar("tag:yaml.org,2002:str", value); : representer.representScalar("tag:yaml.org,2002:str", value);
} }
@ -498,14 +497,14 @@ Node representBytes(ref Node node, Representer representer) @safe
///Represent a bool _node as a bool scalar. ///Represent a bool _node as a bool scalar.
Node representBool(ref Node node, Representer representer) @safe Node representBool(ref Node node, Representer representer) @safe
{ {
return representer.representScalar("tag:yaml.org,2002:bool", return representer.representScalar("tag:yaml.org,2002:bool",
node.as!bool ? "true" : "false"); node.as!bool ? "true" : "false");
} }
///Represent a long _node as an integer scalar. ///Represent a long _node as an integer scalar.
Node representLong(ref Node node, Representer representer) @safe Node representLong(ref Node node, Representer representer) @safe
{ {
return representer.representScalar("tag:yaml.org,2002:int", return representer.representScalar("tag:yaml.org,2002:int",
to!string(node.as!long)); to!string(node.as!long));
} }
@ -526,7 +525,7 @@ Node representReal(ref Node node, Representer representer) @safe
///Represent a SysTime _node as a timestamp. ///Represent a SysTime _node as a timestamp.
Node representSysTime(ref Node node, Representer representer) @safe Node representSysTime(ref Node node, Representer representer) @safe
{ {
return representer.representScalar("tag:yaml.org,2002:timestamp", return representer.representScalar("tag:yaml.org,2002:timestamp",
node.as!SysTime.toISOExtString()); node.as!SysTime.toISOExtString());
} }
@ -614,7 +613,7 @@ struct MyStruct
if(y != s.y){return y - s.y;} if(y != s.y){return y - s.y;}
if(z != s.z){return z - s.z;} if(z != s.z){return z - s.z;}
return 0; return 0;
} }
} }
Node representMyStruct(ref Node node, Representer representer) @safe Node representMyStruct(ref Node node, Representer representer) @safe
@ -628,17 +627,17 @@ Node representMyStruct(ref Node node, Representer representer) @safe
} }
Node representMyStructSeq(ref Node node, Representer representer) @safe Node representMyStructSeq(ref Node node, Representer representer) @safe
{ {
auto value = node.as!MyStruct; auto value = node.as!MyStruct;
auto nodes = [Node(value.x), Node(value.y), Node(value.z)]; auto nodes = [Node(value.x), Node(value.y), Node(value.z)];
return representer.representSequence("!mystruct.tag", nodes); return representer.representSequence("!mystruct.tag", nodes);
} }
Node representMyStructMap(ref Node node, Representer representer) @safe Node representMyStructMap(ref Node node, Representer representer) @safe
{ {
auto value = node.as!MyStruct; auto value = node.as!MyStruct;
auto pairs = [Node.Pair("x", value.x), auto pairs = [Node.Pair("x", value.x),
Node.Pair("y", value.y), Node.Pair("y", value.y),
Node.Pair("z", value.z)]; Node.Pair("z", value.z)];
return representer.representMapping("!mystruct.tag", pairs); return representer.representMapping("!mystruct.tag", pairs);
} }
@ -649,11 +648,11 @@ class MyClass
this(int x, int y, int z) pure @safe nothrow this(int x, int y, int z) pure @safe nothrow
{ {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
} }
override int opCmp(Object o) pure @safe nothrow override int opCmp(Object o) pure @safe nothrow
{ {
MyClass s = cast(MyClass)o; MyClass s = cast(MyClass)o;
@ -686,8 +685,8 @@ import dyaml.stream;
@safe unittest @safe unittest
{ {
foreach(r; [&representMyStruct, foreach(r; [&representMyStruct,
&representMyStructSeq, &representMyStructSeq,
&representMyStructMap]) &representMyStructMap])
{ {
auto dumper = Dumper(new YMemoryStream()); auto dumper = Dumper(new YMemoryStream());

View file

@ -6,10 +6,10 @@
/** /**
* Implements a class that resolves YAML tags. This can be used to implicitly * Implements a class that resolves YAML tags. This can be used to implicitly
* resolve tags for custom data types, removing the need to explicitly * resolve tags for custom data types, removing the need to explicitly
* specify tags in YAML. A tutorial can be found * specify tags in YAML. A tutorial can be found
* $(LINK2 ../tutorials/custom_types.html, here). * $(LINK2 ../tutorials/custom_types.html, here).
* *
* Code based on $(LINK2 http://www.pyyaml.org, PyYAML). * Code based on $(LINK2 http://www.pyyaml.org, PyYAML).
*/ */
module dyaml.resolver; module dyaml.resolver;
@ -30,7 +30,7 @@ import dyaml.exception;
* *
* Can be used to implicitly resolve custom data types of scalar values. * Can be used to implicitly resolve custom data types of scalar values.
*/ */
final class Resolver final class Resolver
{ {
private: private:
// Default tag to use for scalars. // Default tag to use for scalars.
@ -40,7 +40,7 @@ final class Resolver
// Default tag to use for mappings. // Default tag to use for mappings.
string defaultMappingTag_; string defaultMappingTag_;
/* /*
* Arrays of scalar resolver tuples indexed by starting character of a scalar. * Arrays of scalar resolver tuples indexed by starting character of a scalar.
* *
* Each tuple stores regular expression the scalar must match, * Each tuple stores regular expression the scalar must match,
@ -60,7 +60,7 @@ final class Resolver
* *
* Params: defaultImplicitResolvers = Use default YAML implicit resolvers? * Params: defaultImplicitResolvers = Use default YAML implicit resolvers?
*/ */
this(Flag!"useDefaultImplicitResolvers" defaultImplicitResolvers = Yes.useDefaultImplicitResolvers) this(Flag!"useDefaultImplicitResolvers" defaultImplicitResolvers = Yes.useDefaultImplicitResolvers)
@safe @safe
{ {
defaultScalarTag_ = "tag:yaml.org,2002:str"; defaultScalarTag_ = "tag:yaml.org,2002:str";
@ -77,11 +77,11 @@ final class Resolver
} }
/** /**
* Add an implicit scalar resolver. * Add an implicit scalar resolver.
* *
* If a scalar matches regexp and starts with any character in first, * If a scalar matches regexp and starts with any character in first,
* its _tag is set to tag. If it matches more than one resolver _regexp * its _tag is set to tag. If it matches more than one resolver _regexp
* resolvers added _first override ones added later. Default resolvers * resolvers added _first override ones added later. Default resolvers
* override any user specified resolvers, but they can be disabled in * override any user specified resolvers, but they can be disabled in
* Resolver constructor. * Resolver constructor.
* *
@ -93,8 +93,8 @@ final class Resolver
* first = String of possible starting characters of the scalar. * first = String of possible starting characters of the scalar.
* *
*/ */
void addImplicitResolver(string tag, Regex!char regexp, string first) void addImplicitResolver(string tag, Regex!char regexp, string first)
pure @safe pure @safe
{ {
foreach(const dchar c; first) foreach(const dchar c; first)
{ {
@ -153,7 +153,7 @@ final class Resolver
size_t dummy; size_t dummy;
const dchar first = value.length == 0 ? '\0' : decode(value, dummy); const dchar first = value.length == 0 ? '\0' : decode(value, dummy);
auto resolvers = (first in yamlImplicitResolvers_) is null ? auto resolvers = (first in yamlImplicitResolvers_) is null ?
[] : yamlImplicitResolvers_[first]; [] : yamlImplicitResolvers_[first];
//If regexp matches, return tag. //If regexp matches, return tag.
@ -187,19 +187,19 @@ final class Resolver
return true; return true;
} }
assert(tagMatch("tag:yaml.org,2002:bool", assert(tagMatch("tag:yaml.org,2002:bool",
["yes", "NO", "True", "on"])); ["yes", "NO", "True", "on"]));
assert(tagMatch("tag:yaml.org,2002:float", assert(tagMatch("tag:yaml.org,2002:float",
["6.8523015e+5", "685.230_15e+03", "685_230.15", ["6.8523015e+5", "685.230_15e+03", "685_230.15",
"190:20:30.15", "-.inf", ".NaN"])); "190:20:30.15", "-.inf", ".NaN"]));
assert(tagMatch("tag:yaml.org,2002:int", assert(tagMatch("tag:yaml.org,2002:int",
["685230", "+685_230", "02472256", "0x_0A_74_AE", ["685230", "+685_230", "02472256", "0x_0A_74_AE",
"0b1010_0111_0100_1010_1110", "190:20:30"])); "0b1010_0111_0100_1010_1110", "190:20:30"]));
assert(tagMatch("tag:yaml.org,2002:merge", ["<<"])); assert(tagMatch("tag:yaml.org,2002:merge", ["<<"]));
assert(tagMatch("tag:yaml.org,2002:null", ["~", "null", ""])); assert(tagMatch("tag:yaml.org,2002:null", ["~", "null", ""]));
assert(tagMatch("tag:yaml.org,2002:str", assert(tagMatch("tag:yaml.org,2002:str",
["abcd", "9a8b", "9.1adsf"])); ["abcd", "9a8b", "9.1adsf"]));
assert(tagMatch("tag:yaml.org,2002:timestamp", assert(tagMatch("tag:yaml.org,2002:timestamp",
["2001-12-15T02:59:43.1Z", ["2001-12-15T02:59:43.1Z",
"2001-12-14t21:59:43.10-05:00", "2001-12-14t21:59:43.10-05:00",
"2001-12-14 21:59:43.10 -5", "2001-12-14 21:59:43.10 -5",
@ -242,15 +242,15 @@ final class Resolver
"|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"), "|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),
"-+0123456789"); "-+0123456789");
addImplicitResolver("tag:yaml.org,2002:merge", regex(r"^<<$"), "<"); addImplicitResolver("tag:yaml.org,2002:merge", regex(r"^<<$"), "<");
addImplicitResolver("tag:yaml.org,2002:null", addImplicitResolver("tag:yaml.org,2002:null",
regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0"); regex(r"^$|^(?:~|null|Null|NULL)$"), "~nN\0");
addImplicitResolver("tag:yaml.org,2002:timestamp", addImplicitResolver("tag:yaml.org,2002:timestamp",
regex(r"^[0-9][0-9][0-9][0-9]-[0-9][0-9]-" ~ regex(r"^[0-9][0-9][0-9][0-9]-[0-9][0-9]-" ~
"[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9]" ~ "[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9]" ~
"[0-9]?-[0-9][0-9]?[Tt]|[ \t]+[0-9]" ~ "[0-9]?-[0-9][0-9]?[Tt]|[ \t]+[0-9]" ~
"[0-9]?:[0-9][0-9]:[0-9][0-9]" ~ "[0-9]?:[0-9][0-9]:[0-9][0-9]" ~
"(?:\\.[0-9]*)?(?:[ \t]*Z|[-+][0-9]" ~ "(?:\\.[0-9]*)?(?:[ \t]*Z|[-+][0-9]" ~
"[0-9]?(?::[0-9][0-9])?)?$"), "[0-9]?(?::[0-9][0-9])?)?$"),
"0123456789"); "0123456789");
addImplicitResolver("tag:yaml.org,2002:value", regex(r"^=$"), "="); addImplicitResolver("tag:yaml.org,2002:value", regex(r"^=$"), "=");

View file

@ -59,16 +59,16 @@ struct Serializer
* Construct a Serializer. * Construct a Serializer.
* *
* Params: emitter = Emitter to emit events produced. * Params: emitter = Emitter to emit events produced.
* resolver = Resolver used to determine which tags are automaticaly resolvable. * resolver = Resolver used to determine which tags are automaticaly resolvable.
* encoding = Character encoding to use. * encoding = Character encoding to use.
* explicitStart = Do all document starts have to be specified explicitly? * explicitStart = Do all document starts have to be specified explicitly?
* explicitEnd = Do all document ends have to be specified explicitly? * explicitEnd = Do all document ends have to be specified explicitly?
* YAMLVersion = YAML version string. * YAMLVersion = YAML version string.
* tagDirectives = Tag directives to emit. * tagDirectives = Tag directives to emit.
*/ */
this(ref Emitter emitter, Resolver resolver, Encoding encoding, this(ref Emitter emitter, Resolver resolver, Encoding encoding,
const Flag!"explicitStart" explicitStart, const Flag!"explicitStart" explicitStart,
const Flag!"explicitEnd" explicitEnd, string YAMLVersion, const Flag!"explicitEnd" explicitEnd, string YAMLVersion,
TagDirective[] tagDirectives) @trusted TagDirective[] tagDirectives) @trusted
{ {
emitter_ = &emitter; emitter_ = &emitter;
@ -96,7 +96,7 @@ struct Serializer
///Serialize a node, emitting it in the process. ///Serialize a node, emitting it in the process.
void serialize(ref Node node) @safe void serialize(ref Node node) @safe
{ {
emitter_.emit(documentStartEvent(Mark(), Mark(), explicitStart_, emitter_.emit(documentStartEvent(Mark(), Mark(), explicitStart_,
YAMLVersion_, tagDirectives_)); YAMLVersion_, tagDirectives_));
anchorNode(node); anchorNode(node);
serializeNode(node); serializeNode(node);
@ -112,7 +112,7 @@ struct Serializer
/** /**
* Determine if it's a good idea to add an anchor to a node. * Determine if it's a good idea to add an anchor to a node.
* *
* Used to prevent associating every single repeating scalar with an * Used to prevent associating every single repeating scalar with an
* anchor/alias - only nodes long enough can use anchors. * anchor/alias - only nodes long enough can use anchors.
* *
* Params: node = Node to check for anchorability. * Params: node = Node to check for anchorability.
@ -168,8 +168,8 @@ struct Serializer
///Serialize a node and all its subnodes. ///Serialize a node and all its subnodes.
void serializeNode(ref Node node) @safe void serializeNode(ref Node node) @safe
{ {
//If the node has an anchor, emit an anchor (as aliasEvent) on the //If the node has an anchor, emit an anchor (as aliasEvent) on the
//first occurrence, save it in serializedNodes_, and emit an alias //first occurrence, save it in serializedNodes_, and emit an alias
//if it reappears. //if it reappears.
string aliased = null; string aliased = null;
if(anchorable(node) && (node in anchors_) !is null) if(anchorable(node) && (node in anchors_) !is null)
@ -211,12 +211,12 @@ struct Serializer
} }
if(node.isMapping) if(node.isMapping)
{ {
const defaultTag = resolver_.defaultMappingTag; const defaultTag = resolver_.defaultMappingTag;
const implicit = node.tag_ == defaultTag; const implicit = node.tag_ == defaultTag;
emitter_.emit(mappingStartEvent(Mark(), Mark(), aliased, node.tag_, emitter_.emit(mappingStartEvent(Mark(), Mark(), aliased, node.tag_,
implicit, node.collectionStyle)); implicit, node.collectionStyle));
foreach(ref Node key, ref Node value; node) foreach(ref Node key, ref Node value; node)
{ {
serializeNode(key); serializeNode(key);
serializeNode(value); serializeNode(value);
} }

View file

@ -22,7 +22,7 @@ enum ScalarStyle : ubyte
///Collection styles. ///Collection styles.
enum CollectionStyle : ubyte enum CollectionStyle : ubyte
{ {
Invalid = 0, /// Invalid (uninitialized) style Invalid = 0, /// Invalid (uninitialized) style
Block, /// Block style. Block, /// Block style.
Flow /// Flow style. Flow /// Flow style.
} }