diff --git a/source/dyaml/parser.d b/source/dyaml/parser.d index 28a67d5..10fcab3 100644 --- a/source/dyaml/parser.d +++ b/source/dyaml/parser.d @@ -346,23 +346,20 @@ final class Parser while(scanner_.checkToken(TokenID.Directive)) { immutable token = scanner_.getToken(); - //Name and value are separated by '\0'. - const parts = token.value.split("\0"); - const name = parts[0]; - if(name == "YAML") + const value = token.value; + if(token.directive == DirectiveType.YAML) { - enforce(YAMLVersion_ is null, + enforce(YAMLVersion_ is null, new Error("Duplicate YAML directive", token.startMark)); - const minor = parts[1].split(".")[0]; - enforce(minor == "1", + const minor = value.split(".")[0]; + enforce(minor == "1", new Error("Incompatible document (version 1.x is required)", token.startMark)); - YAMLVersion_ = parts[1]; + YAMLVersion_ = value; } - else if(name == "TAG") + else if(token.directive == DirectiveType.TAG) { - assert(parts.length == 3, "Tag directive stored incorrectly in a token"); - auto handle = parts[1]; + auto handle = value[0 .. token.valueDivider]; foreach(ref pair; tagDirectives_) { @@ -371,8 +368,10 @@ final class Parser enforce(h != handle, new Error("Duplicate tag handle: " ~ handle, token.startMark)); } - tagDirectives_ ~= TagDirective(handle, parts[2]); + tagDirectives_ ~= TagDirective(handle, value[token.valueDivider .. $]); } + // Any other directive type is ignored (only YAML and TAG are in YAML + // 1.1/1.2, any other directives are "reserved") } TagDirective[] value = tagDirectives_; diff --git a/source/dyaml/scanner.d b/source/dyaml/scanner.d index 4d8cd32..fc69c29 100644 --- a/source/dyaml/scanner.d +++ b/source/dyaml/scanner.d @@ -943,17 +943,28 @@ final class Scanner throwIfError(); } const name = reader_.sliceBuilder.finish(); - const value = name == "YAML" ? scanYAMLDirectiveValue(startMark): - name == "TAG" ? scanTagDirectiveValue(startMark) : ""; + // Index where tag handle ends and suffix starts in a tag directive value. + uint tagHandleEnd = uint.max; + const value = name == "YAML"d ? scanYAMLDirectiveValue(startMark): + name == "TAG"d ? scanTagDirectiveValue(startMark, tagHandleEnd) : ""; Mark endMark = reader_.mark; - if(!["YAML"d, "TAG"d].canFind(name)) { scanToNextBreak(); } + DirectiveType directive; + if(name == "YAML"d) { directive = DirectiveType.YAML; } + else if(name == "TAG"d) { directive = DirectiveType.TAG; } + else + { + directive = DirectiveType.Reserved; + scanToNextBreak(); + } + scanDirectiveIgnoredLine(startMark); throwIfError(); //Storing directive name and value in a single string, separated by zero. - return directiveToken(startMark, endMark, utf32To8(name ~ '\0' ~ value)); + return directiveToken(startMark, endMark, utf32To8(value), + directive, tagHandleEnd); } /// Scan name of a directive token. @@ -1010,12 +1021,14 @@ final class Scanner } /// Scan value of a tag directive. - dstring scanTagDirectiveValue(const Mark startMark) @safe pure + dstring scanTagDirectiveValue(const Mark startMark, ref uint handleLength) + @safe pure { findNextNonSpace(); const handle = scanTagDirectiveHandle(startMark); findNextNonSpace(); - return handle ~ '\0' ~ scanTagDirectivePrefix(startMark); + handleLength = cast(uint)handle.length; + return handle ~ scanTagDirectivePrefix(startMark); } ///Scan handle of a tag directive. diff --git a/source/dyaml/token.d b/source/dyaml/token.d index 44c29a6..8a46514 100644 --- a/source/dyaml/token.d +++ b/source/dyaml/token.d @@ -98,12 +98,15 @@ static assert(Token.sizeof <= 32, "Token has unexpected size"); /// Construct a directive token. /// -/// Params: start = Start position of the token. -/// end = End position of the token. -/// value = Value of the token. -Token directiveToken(const Mark start, const Mark end, const string value) +/// Params: start = Start position of the token. +/// end = End position of the token. +/// value = Value of the token. +/// directive = Directive type (YAML or TAG in YAML 1.1). +Token directiveToken(const Mark start, const Mark end, const string value, + DirectiveType directive, const uint nameEnd) { - return Token(value, start, end, TokenID.Directive); + return Token(value, start, end, TokenID.Directive, ScalarStyle.init, Encoding.init, + directive, nameEnd); } /// Construct a simple (no value) token with specified type.