Got rid of most UTF-8 decoding that took a lot of time.
Removed unnecessary calls to Stream.available(), again for grat speed gain. Also various small optimizations. Overall, improved loading speed about 400%.
This commit is contained in:
parent
9d68b6fa9a
commit
97693b4417
|
@ -344,9 +344,11 @@ YAMLMerge constructMerge(Mark start, Mark end, ref Node node)
|
||||||
///Construct a boolean node.
|
///Construct a boolean node.
|
||||||
bool constructBool(Mark start, Mark end, ref Node node)
|
bool constructBool(Mark start, Mark end, ref Node node)
|
||||||
{
|
{
|
||||||
|
static yes = ["yes", "true", "on"];
|
||||||
|
static no = ["no", "false", "off"];
|
||||||
string value = node.as!string().toLower();
|
string value = node.as!string().toLower();
|
||||||
if(["yes", "true", "on"].canFind(value)) {return true;}
|
if(yes.canFind(value)){return true;}
|
||||||
if(["no", "false", "off"].canFind(value)){return false;}
|
if(no.canFind(value)) {return false;}
|
||||||
throw new Error("Unable to parse boolean value: " ~ value, start, end);
|
throw new Error("Unable to parse boolean value: " ~ value, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ module dyaml.emitter;
|
||||||
import std.algorithm;
|
import std.algorithm;
|
||||||
import std.array;
|
import std.array;
|
||||||
import std.ascii;
|
import std.ascii;
|
||||||
|
import std.container;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
import std.format;
|
import std.format;
|
||||||
|
@ -78,7 +79,7 @@ struct Emitter
|
||||||
Encoding encoding_ = Encoding.UTF_8;
|
Encoding encoding_ = Encoding.UTF_8;
|
||||||
|
|
||||||
///Stack of states.
|
///Stack of states.
|
||||||
void delegate()[] states_;
|
Array!(void delegate()) states_;
|
||||||
///Current state.
|
///Current state.
|
||||||
void delegate() state_;
|
void delegate() state_;
|
||||||
|
|
||||||
|
@ -155,6 +156,7 @@ struct Emitter
|
||||||
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
|
||||||
{
|
{
|
||||||
|
states_.reserve(32);
|
||||||
stream_ = stream;
|
stream_ = stream;
|
||||||
canonical_ = canonical;
|
canonical_ = canonical;
|
||||||
state_ = &expectStreamStart;
|
state_ = &expectStreamStart;
|
||||||
|
@ -171,7 +173,6 @@ struct Emitter
|
||||||
{
|
{
|
||||||
stream_ = null;
|
stream_ = null;
|
||||||
clear(states_);
|
clear(states_);
|
||||||
states_ = null;
|
|
||||||
clear(events_);
|
clear(events_);
|
||||||
clear(indents_);
|
clear(indents_);
|
||||||
indents_ = null;
|
indents_ = null;
|
||||||
|
@ -201,8 +202,8 @@ struct Emitter
|
||||||
{
|
{
|
||||||
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_.popBack;
|
states_.length = states_.length - 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,20 +267,12 @@ struct Emitter
|
||||||
while(!events_.iterationOver())
|
while(!events_.iterationOver())
|
||||||
{
|
{
|
||||||
immutable event = events_.next();
|
immutable event = events_.next();
|
||||||
if([EventID.DocumentStart, EventID.SequenceStart,
|
static starts = [EventID.DocumentStart, EventID.SequenceStart, EventID.MappingStart];
|
||||||
EventID.MappingStart].canFind(event.id))
|
static ends = [EventID.DocumentEnd, EventID.SequenceEnd, EventID.MappingEnd];
|
||||||
{
|
if(starts.canFind(event.id)) {++level;}
|
||||||
++level;
|
else if(ends.canFind(event.id)) {--level;}
|
||||||
}
|
else if(event.id == EventID.StreamStart){level = -1;}
|
||||||
else if([EventID.DocumentEnd, EventID.SequenceEnd,
|
|
||||||
EventID.MappingEnd].canFind(event.id))
|
|
||||||
{
|
|
||||||
--level;
|
|
||||||
}
|
|
||||||
else if(event.id == EventID.StreamStart)
|
|
||||||
{
|
|
||||||
level = -1;
|
|
||||||
}
|
|
||||||
if(level < 0)
|
if(level < 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -692,8 +685,8 @@ struct Emitter
|
||||||
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 = [EventID.MappingStart,
|
const collectionStart = id == EventID.MappingStart ||
|
||||||
EventID.SequenceStart].canFind(id);
|
id == EventID.SequenceStart;
|
||||||
|
|
||||||
if((id == EventID.Alias || scalar || collectionStart)
|
if((id == EventID.Alias || scalar || collectionStart)
|
||||||
&& !event_.anchor.isNull())
|
&& !event_.anchor.isNull())
|
||||||
|
@ -815,8 +808,8 @@ struct Emitter
|
||||||
if(analysis_.flags.isNull){analysis_ = analyzeScalar(event_.value);}
|
if(analysis_.flags.isNull){analysis_ = analyzeScalar(event_.value);}
|
||||||
|
|
||||||
const style = event_.scalarStyle;
|
const style = event_.scalarStyle;
|
||||||
const invalidOrPlain = [ScalarStyle.Invalid, ScalarStyle.Plain].canFind(style);
|
const invalidOrPlain = style == ScalarStyle.Invalid || style == ScalarStyle.Plain;
|
||||||
const block = [ScalarStyle.Literal, ScalarStyle.Folded].canFind(style);
|
const block = style == ScalarStyle.Literal || style == ScalarStyle.Folded;
|
||||||
const singleQuoted = style == ScalarStyle.SingleQuoted;
|
const singleQuoted = style == ScalarStyle.SingleQuoted;
|
||||||
const doubleQuoted = style == ScalarStyle.DoubleQuoted;
|
const doubleQuoted = style == ScalarStyle.DoubleQuoted;
|
||||||
|
|
||||||
|
@ -880,7 +873,7 @@ struct Emitter
|
||||||
|
|
||||||
if(handle.length > 1) foreach(const dchar c; handle[1 .. $ - 1])
|
if(handle.length > 1) foreach(const dchar c; handle[1 .. $ - 1])
|
||||||
{
|
{
|
||||||
enforce(isAlphaNum(c) || "-_".canFind(c),
|
enforce(isAlphaNum(c) || "-_"d.canFind(c),
|
||||||
new Error("Invalid character: " ~ to!string(c) ~
|
new Error("Invalid character: " ~ to!string(c) ~
|
||||||
" in tag handle " ~ handle));
|
" in tag handle " ~ handle));
|
||||||
}
|
}
|
||||||
|
@ -901,7 +894,7 @@ struct Emitter
|
||||||
foreach(const size_t i, const dchar c; prefix)
|
foreach(const size_t i, const dchar c; prefix)
|
||||||
{
|
{
|
||||||
const size_t idx = i + offset;
|
const size_t idx = i + offset;
|
||||||
if(isAlphaNum(c) || "-;/?:@&=+$,_.!~*\'()[]%".canFind(c))
|
if(isAlphaNum(c) || "-;/?:@&=+$,_.!~*\'()[]%"d.canFind(c))
|
||||||
{
|
{
|
||||||
end = idx + 1;
|
end = idx + 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -947,7 +940,7 @@ struct Emitter
|
||||||
size_t end = 0;
|
size_t end = 0;
|
||||||
foreach(const dchar c; suffix)
|
foreach(const dchar c; suffix)
|
||||||
{
|
{
|
||||||
if(isAlphaNum(c) || "-;/?:@&=+$,_.~*\'()[]".canFind(c) ||
|
if(isAlphaNum(c) || "-;/?:@&=+$,_.~*\'()[]"d.canFind(c) ||
|
||||||
(c == '!' && handle != "!"))
|
(c == '!' && handle != "!"))
|
||||||
{
|
{
|
||||||
++end;
|
++end;
|
||||||
|
@ -973,7 +966,7 @@ struct Emitter
|
||||||
const str = anchor.get;
|
const str = anchor.get;
|
||||||
foreach(const dchar c; str)
|
foreach(const dchar c; str)
|
||||||
{
|
{
|
||||||
enforce(isAlphaNum(c) || "-_".canFind(c),
|
enforce(isAlphaNum(c) || "-_"d.canFind(c),
|
||||||
new Error("Invalid character: " ~ to!string(c) ~ " in anchor: " ~ str));
|
new Error("Invalid character: " ~ to!string(c) ~ " in anchor: " ~ str));
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -1017,7 +1010,7 @@ struct Emitter
|
||||||
|
|
||||||
//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".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).
|
||||||
bool previousSpace, previousBreak;
|
bool previousSpace, previousBreak;
|
||||||
|
@ -1028,11 +1021,11 @@ struct Emitter
|
||||||
if(index == 0)
|
if(index == 0)
|
||||||
{
|
{
|
||||||
//Leading indicators are special characters.
|
//Leading indicators are special characters.
|
||||||
if("#,[]{}&*!|>\'\"%@`".canFind(c))
|
if("#,[]{}&*!|>\'\"%@`"d.canFind(c))
|
||||||
{
|
{
|
||||||
flowIndicators = blockIndicators = true;
|
flowIndicators = blockIndicators = true;
|
||||||
}
|
}
|
||||||
if("?:".canFind(c))
|
if("?:"d.canFind(c))
|
||||||
{
|
{
|
||||||
flowIndicators = true;
|
flowIndicators = true;
|
||||||
if(followedByWhitespace){blockIndicators = true;}
|
if(followedByWhitespace){blockIndicators = true;}
|
||||||
|
@ -1045,7 +1038,7 @@ struct Emitter
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Some indicators cannot appear within a scalar as well.
|
//Some indicators cannot appear within a scalar as well.
|
||||||
if(",?[]{}".canFind(c)){flowIndicators = true;}
|
if(",?[]{}"d.canFind(c)){flowIndicators = true;}
|
||||||
if(c == ':')
|
if(c == ':')
|
||||||
{
|
{
|
||||||
flowIndicators = true;
|
flowIndicators = true;
|
||||||
|
@ -1058,7 +1051,7 @@ struct Emitter
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for line breaks, special, and unicode characters.
|
//Check for line breaks, special, and unicode characters.
|
||||||
if("\n\u0085\u2028\u2029".canFind(c)){lineBreaks = true;}
|
if("\n\u0085\u2028\u2029"d.canFind(c)){lineBreaks = true;}
|
||||||
if(!(c == '\n' || (c >= '\x20' && c <= '\x7E')) &&
|
if(!(c == '\n' || (c >= '\x20' && c <= '\x7E')) &&
|
||||||
!((c == '\u0085' || (c >= '\xA0' && c <= '\uD7FF') ||
|
!((c == '\u0085' || (c >= '\xA0' && c <= '\uD7FF') ||
|
||||||
(c >= '\uE000' && c <= '\uFFFD')) && c != '\uFEFF'))
|
(c >= '\uE000' && c <= '\uFFFD')) && c != '\uFEFF'))
|
||||||
|
@ -1075,7 +1068,7 @@ struct Emitter
|
||||||
previousSpace = true;
|
previousSpace = true;
|
||||||
previousBreak = false;
|
previousBreak = false;
|
||||||
}
|
}
|
||||||
else if("\n\u0085\u2028\u2029".canFind(c))
|
else if("\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
if(index == 0){leadingBreak = true;}
|
if(index == 0){leadingBreak = true;}
|
||||||
if(index == scalar.length - 1){trailingBreak = true;}
|
if(index == scalar.length - 1){trailingBreak = true;}
|
||||||
|
@ -1089,9 +1082,9 @@ struct Emitter
|
||||||
}
|
}
|
||||||
|
|
||||||
//Prepare for the next character.
|
//Prepare for the next character.
|
||||||
preceededByWhitespace = "\0\n\r\u0085\u2028\u2029 \t".canFind(c);
|
preceededByWhitespace = "\0\n\r\u0085\u2028\u2029 \t"d.canFind(c);
|
||||||
followedByWhitespace = index + 2 >= scalar.length ||
|
followedByWhitespace = index + 2 >= scalar.length ||
|
||||||
"\0\n\r\u0085\u2028\u2029 \t".canFind(scalar[index + 2]);
|
"\0\n\r\u0085\u2028\u2029 \t"d.canFind(scalar[index + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
with(analysis.flags)
|
with(analysis.flags)
|
||||||
|
@ -1317,14 +1310,14 @@ struct ScalarWriter
|
||||||
}
|
}
|
||||||
else if(breaks_)
|
else if(breaks_)
|
||||||
{
|
{
|
||||||
if(!"\n\u0085\u2028\u2029".canFind(c))
|
if(!"\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeStartLineBreak();
|
writeStartLineBreak();
|
||||||
writeLineBreaks();
|
writeLineBreaks();
|
||||||
emitter_.writeIndent();
|
emitter_.writeIndent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if((c == dcharNone || "\' \n\u0085\u2028\u2029".canFind(c))
|
else if((c == dcharNone || "\' \n\u0085\u2028\u2029"d.canFind(c))
|
||||||
&& startChar_ < endChar_)
|
&& startChar_ < endChar_)
|
||||||
{
|
{
|
||||||
writeCurrentRange(Flag!"UpdateColumn".yes);
|
writeCurrentRange(Flag!"UpdateColumn".yes);
|
||||||
|
@ -1350,7 +1343,7 @@ struct ScalarWriter
|
||||||
{
|
{
|
||||||
const dchar c = nextChar();
|
const dchar c = nextChar();
|
||||||
//handle special characters
|
//handle special characters
|
||||||
if(c == dcharNone || "\"\\\u0085\u2028\u2029\uFEFF".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'))))
|
||||||
{
|
{
|
||||||
|
@ -1417,7 +1410,7 @@ struct ScalarWriter
|
||||||
const dchar c = nextChar();
|
const dchar c = nextChar();
|
||||||
if(breaks_)
|
if(breaks_)
|
||||||
{
|
{
|
||||||
if(!"\n\u0085\u2028\u2029".canFind(c))
|
if(!"\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
if(!leadingSpace && c != dcharNone && c != ' ')
|
if(!leadingSpace && c != dcharNone && c != ' ')
|
||||||
{
|
{
|
||||||
|
@ -1440,7 +1433,7 @@ struct ScalarWriter
|
||||||
writeCurrentRange(Flag!"UpdateColumn".yes);
|
writeCurrentRange(Flag!"UpdateColumn".yes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(c == dcharNone || " \n\u0085\u2028\u2029".canFind(c))
|
else if(c == dcharNone || " \n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeCurrentRange(Flag!"UpdateColumn".yes);
|
writeCurrentRange(Flag!"UpdateColumn".yes);
|
||||||
if(c == dcharNone){emitter_.writeLineBreak();}
|
if(c == dcharNone){emitter_.writeLineBreak();}
|
||||||
|
@ -1461,13 +1454,13 @@ struct ScalarWriter
|
||||||
const dchar c = nextChar();
|
const dchar c = nextChar();
|
||||||
if(breaks_)
|
if(breaks_)
|
||||||
{
|
{
|
||||||
if(!"\n\u0085\u2028\u2029".canFind(c))
|
if(!"\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeLineBreaks();
|
writeLineBreaks();
|
||||||
if(c != dcharNone){emitter_.writeIndent();}
|
if(c != dcharNone){emitter_.writeIndent();}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(c == dcharNone || "\n\u0085\u2028\u2029".canFind(c))
|
else if(c == dcharNone || "\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeCurrentRange(Flag!"UpdateColumn".no);
|
writeCurrentRange(Flag!"UpdateColumn".no);
|
||||||
if(c == dcharNone){emitter_.writeLineBreak();}
|
if(c == dcharNone){emitter_.writeLineBreak();}
|
||||||
|
@ -1507,14 +1500,14 @@ struct ScalarWriter
|
||||||
}
|
}
|
||||||
else if(breaks_)
|
else if(breaks_)
|
||||||
{
|
{
|
||||||
if(!"\n\u0085\u2028\u2029".canFind(c))
|
if(!"\n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeStartLineBreak();
|
writeStartLineBreak();
|
||||||
writeLineBreaks();
|
writeLineBreaks();
|
||||||
writeIndent(Flag!"ResetSpace".yes);
|
writeIndent(Flag!"ResetSpace".yes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(c == dcharNone || " \n\u0085\u2028\u2029".canFind(c))
|
else if(c == dcharNone || " \n\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
writeCurrentRange(Flag!"UpdateColumn".yes);
|
writeCurrentRange(Flag!"UpdateColumn".yes);
|
||||||
}
|
}
|
||||||
|
@ -1562,16 +1555,16 @@ struct ScalarWriter
|
||||||
const last = lastChar(text_, end);
|
const last = lastChar(text_, end);
|
||||||
const secondLast = end > 0 ? lastChar(text_, end) : 0;
|
const secondLast = end > 0 ? lastChar(text_, end) : 0;
|
||||||
|
|
||||||
if(" \n\u0085\u2028\u2029".canFind(text_[0]))
|
if(" \n\u0085\u2028\u2029"d.canFind(text_[0]))
|
||||||
{
|
{
|
||||||
hints[hintsIdx++] = cast(char)('0' + bestIndent);
|
hints[hintsIdx++] = cast(char)('0' + bestIndent);
|
||||||
}
|
}
|
||||||
if(!"\n\u0085\u2028\u2029".canFind(last))
|
if(!"\n\u0085\u2028\u2029"d.canFind(last))
|
||||||
{
|
{
|
||||||
hints[hintsIdx++] = '-';
|
hints[hintsIdx++] = '-';
|
||||||
}
|
}
|
||||||
else if(std.utf.count(text_) == 1 ||
|
else if(std.utf.count(text_) == 1 ||
|
||||||
"\n\u0085\u2028\u2029".canFind(secondLast))
|
"\n\u0085\u2028\u2029"d.canFind(secondLast))
|
||||||
{
|
{
|
||||||
hints[hintsIdx++] = '+';
|
hints[hintsIdx++] = '+';
|
||||||
}
|
}
|
||||||
|
@ -1643,7 +1636,7 @@ struct ScalarWriter
|
||||||
void updateBreaks(in dchar c, in Flag!"UpdateSpaces" updateSpaces)
|
void updateBreaks(in dchar c, in Flag!"UpdateSpaces" updateSpaces)
|
||||||
{
|
{
|
||||||
if(c == dcharNone){return;}
|
if(c == dcharNone){return;}
|
||||||
breaks_ = "\n\u0085\u2028\u2029".canFind(c);
|
breaks_ = "\n\u0085\u2028\u2029"d.canFind(c);
|
||||||
if(updateSpaces){spaces_ = c == ' ';}
|
if(updateSpaces){spaces_ = c == ' ';}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ struct Loader
|
||||||
/**
|
/**
|
||||||
* Construct a Loader to load YAML from a _stream.
|
* Construct a Loader to load YAML from a _stream.
|
||||||
*
|
*
|
||||||
* Params: stream = Stream to read from. Must be readable.
|
* Params: stream = Stream to read from. Must be readable and seekable.
|
||||||
*
|
*
|
||||||
* Throws: YAMLException if stream could not be read.
|
* Throws: YAMLException if stream could not be read.
|
||||||
*/
|
*/
|
||||||
|
|
38
dyaml/node.d
38
dyaml/node.d
|
@ -666,11 +666,11 @@ struct Node
|
||||||
Node k3 = Node("13");
|
Node k3 = Node("13");
|
||||||
Node k4 = Node("14");
|
Node k4 = Node("14");
|
||||||
|
|
||||||
Node narray = Node(Value([n1, n2, n3, n4]));
|
Node narray = Node([n1, n2, n3, n4]);
|
||||||
Node nmap = Node(Value([Pair(k1, n1),
|
Node nmap = Node([Pair(k1, n1),
|
||||||
Pair(k2, n2),
|
Pair(k2, n2),
|
||||||
Pair(k3, n3),
|
Pair(k3, n3),
|
||||||
Pair(k4, n4)]));
|
Pair(k4, n4)]);
|
||||||
|
|
||||||
assert(narray[0].as!int == 11);
|
assert(narray[0].as!int == 11);
|
||||||
assert(null !is collectException(narray[42]));
|
assert(null !is collectException(narray[42]));
|
||||||
|
@ -793,7 +793,7 @@ struct Node
|
||||||
Node n2 = Node(Value(cast(long)12));
|
Node n2 = Node(Value(cast(long)12));
|
||||||
Node n3 = Node(Value(cast(long)13));
|
Node n3 = Node(Value(cast(long)13));
|
||||||
Node n4 = Node(Value(cast(long)14));
|
Node n4 = Node(Value(cast(long)14));
|
||||||
Node narray = Node(Value([n1, n2, n3, n4]));
|
Node narray = Node([n1, n2, n3, n4]);
|
||||||
|
|
||||||
int[] array, array2;
|
int[] array, array2;
|
||||||
foreach(int value; narray)
|
foreach(int value; narray)
|
||||||
|
@ -858,20 +858,20 @@ struct Node
|
||||||
alias Node.Value Value;
|
alias Node.Value Value;
|
||||||
alias Node.Pair Pair;
|
alias Node.Pair Pair;
|
||||||
|
|
||||||
Node n1 = Node(Value(cast(long)11));
|
Node n1 = Node(cast(long)11);
|
||||||
Node n2 = Node(Value(cast(long)12));
|
Node n2 = Node(cast(long)12);
|
||||||
Node n3 = Node(Value(cast(long)13));
|
Node n3 = Node(cast(long)13);
|
||||||
Node n4 = Node(Value(cast(long)14));
|
Node n4 = Node(cast(long)14);
|
||||||
|
|
||||||
Node k1 = Node(Value("11"));
|
Node k1 = Node("11");
|
||||||
Node k2 = Node(Value("12"));
|
Node k2 = Node("12");
|
||||||
Node k3 = Node(Value("13"));
|
Node k3 = Node("13");
|
||||||
Node k4 = Node(Value("14"));
|
Node k4 = Node("14");
|
||||||
|
|
||||||
Node nmap1 = Node(Value([Pair(k1, n1),
|
Node nmap1 = Node([Pair(k1, n1),
|
||||||
Pair(k2, n2),
|
Pair(k2, n2),
|
||||||
Pair(k3, n3),
|
Pair(k3, n3),
|
||||||
Pair(k4, n4)]));
|
Pair(k4, n4)]);
|
||||||
|
|
||||||
int[string] expected = ["11" : 11,
|
int[string] expected = ["11" : 11,
|
||||||
"12" : 12,
|
"12" : 12,
|
||||||
|
@ -884,10 +884,10 @@ struct Node
|
||||||
}
|
}
|
||||||
assert(array == expected);
|
assert(array == expected);
|
||||||
|
|
||||||
Node nmap2 = Node(Value([Pair(k1, Node(Value(cast(long)5))),
|
Node nmap2 = Node([Pair(k1, Node(cast(long)5)),
|
||||||
Pair(k2, Node(Value(true))),
|
Pair(k2, Node(true)),
|
||||||
Pair(k3, Node(Value(cast(real)1.0))),
|
Pair(k3, Node(cast(real)1.0)),
|
||||||
Pair(k4, Node(Value("yarly")))]));
|
Pair(k4, Node("yarly"))]);
|
||||||
|
|
||||||
foreach(string key, Node value; nmap2)
|
foreach(string key, Node value; nmap2)
|
||||||
{
|
{
|
||||||
|
@ -1073,7 +1073,7 @@ struct Node
|
||||||
auto idx = findPair(index);
|
auto idx = findPair(index);
|
||||||
if(idx >= 0)
|
if(idx >= 0)
|
||||||
{
|
{
|
||||||
auto pairs = as!(Node.Pair[])();
|
auto pairs = get!(Node.Pair[])();
|
||||||
moveAll(pairs[idx + 1 .. $], pairs[idx .. $ - 1]);
|
moveAll(pairs[idx + 1 .. $], pairs[idx .. $ - 1]);
|
||||||
pairs.length = pairs.length - 1;
|
pairs.length = pairs.length - 1;
|
||||||
value_ = Value(pairs);
|
value_ = Value(pairs);
|
||||||
|
|
|
@ -122,7 +122,7 @@ final class Parser
|
||||||
///YAML version string.
|
///YAML version string.
|
||||||
string YAMLVersion_ = null;
|
string YAMLVersion_ = null;
|
||||||
///Tag handle shortcuts and replacements.
|
///Tag handle shortcuts and replacements.
|
||||||
tagDirective[] tagHandles_;
|
tagDirective[] tagDirectives_;
|
||||||
|
|
||||||
///Stack of states.
|
///Stack of states.
|
||||||
Array!(Event delegate()) states_;
|
Array!(Event delegate()) states_;
|
||||||
|
@ -146,8 +146,8 @@ final class Parser
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
clear(currentEvent_);
|
clear(currentEvent_);
|
||||||
clear(tagHandles_);
|
clear(tagDirectives_);
|
||||||
tagHandles_ = null;
|
tagDirectives_ = null;
|
||||||
clear(states_);
|
clear(states_);
|
||||||
clear(marks_);
|
clear(marks_);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ final class Parser
|
||||||
if(!scanner_.checkToken(TokenID.Directive, TokenID.DocumentStart,
|
if(!scanner_.checkToken(TokenID.Directive, TokenID.DocumentStart,
|
||||||
TokenID.StreamEnd))
|
TokenID.StreamEnd))
|
||||||
{
|
{
|
||||||
tagHandles_ = defaultTagDirectives_;
|
tagDirectives_ = defaultTagDirectives_;
|
||||||
immutable token = scanner_.peekToken();
|
immutable token = scanner_.peekToken();
|
||||||
|
|
||||||
states_ ~= &parseDocumentEnd;
|
states_ ~= &parseDocumentEnd;
|
||||||
|
@ -339,7 +339,7 @@ final class Parser
|
||||||
{
|
{
|
||||||
//Destroy version and tag handles from previous document.
|
//Destroy version and tag handles from previous document.
|
||||||
YAMLVersion_ = null;
|
YAMLVersion_ = null;
|
||||||
tagHandles_.length = 0;
|
tagDirectives_.length = 0;
|
||||||
|
|
||||||
//Process directives.
|
//Process directives.
|
||||||
while(scanner_.checkToken(TokenID.Directive))
|
while(scanner_.checkToken(TokenID.Directive))
|
||||||
|
@ -363,7 +363,7 @@ final class Parser
|
||||||
assert(parts.length == 3, "Tag directive stored incorrectly in a token");
|
assert(parts.length == 3, "Tag directive stored incorrectly in a token");
|
||||||
auto handle = parts[1];
|
auto handle = parts[1];
|
||||||
|
|
||||||
foreach(ref pair; tagHandles_)
|
foreach(ref pair; tagDirectives_)
|
||||||
{
|
{
|
||||||
//handle
|
//handle
|
||||||
auto h = pair[0];
|
auto h = pair[0];
|
||||||
|
@ -371,17 +371,17 @@ final class Parser
|
||||||
enforce(h != handle, new Error("Duplicate tag handle: " ~ handle,
|
enforce(h != handle, new Error("Duplicate tag handle: " ~ handle,
|
||||||
token.startMark));
|
token.startMark));
|
||||||
}
|
}
|
||||||
tagHandles_ ~= tagDirective(handle, parts[2]);
|
tagDirectives_ ~= tagDirective(handle, parts[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TagDirectives value = tagHandles_.length == 0 ? TagDirectives() : TagDirectives(tagHandles_);
|
TagDirectives value = tagDirectives_.length == 0 ? TagDirectives() : TagDirectives(tagDirectives_);
|
||||||
|
|
||||||
//Add any default tag handles that haven't been overridden.
|
//Add any default tag handles that haven't been overridden.
|
||||||
foreach(ref defaultPair; defaultTagDirectives_)
|
foreach(ref defaultPair; defaultTagDirectives_)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach(ref pair; tagHandles_)
|
foreach(ref pair; tagDirectives_)
|
||||||
{
|
{
|
||||||
if(defaultPair[0] == pair[0] )
|
if(defaultPair[0] == pair[0] )
|
||||||
{
|
{
|
||||||
|
@ -389,7 +389,7 @@ final class Parser
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!found){tagHandles_ ~= defaultPair;}
|
if(!found){tagDirectives_ ~= defaultPair;}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -541,7 +541,7 @@ final class Parser
|
||||||
if(handle.length > 0)
|
if(handle.length > 0)
|
||||||
{
|
{
|
||||||
string replacement = null;
|
string replacement = null;
|
||||||
foreach(ref pair; tagHandles_)
|
foreach(ref pair; tagDirectives_)
|
||||||
{
|
{
|
||||||
//pair[0] is handle, pair[1] replacement.
|
//pair[0] is handle, pair[1] replacement.
|
||||||
if(pair[0] == handle)
|
if(pair[0] == handle)
|
||||||
|
@ -550,7 +550,7 @@ final class Parser
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//handle must be in tagHandles_
|
//handle must be in tagDirectives_
|
||||||
enforce(replacement !is null,
|
enforce(replacement !is null,
|
||||||
new Error("While parsing a node", startMark,
|
new Error("While parsing a node", startMark,
|
||||||
"found undefined tag handle: " ~ handle, tagMark));
|
"found undefined tag handle: " ~ handle, tagMark));
|
||||||
|
|
|
@ -51,6 +51,8 @@ final class Reader
|
||||||
uint line_;
|
uint line_;
|
||||||
///Current column in file.
|
///Current column in file.
|
||||||
uint column_;
|
uint column_;
|
||||||
|
///Number of bytes still available (not read) in the stream.
|
||||||
|
size_t available_;
|
||||||
|
|
||||||
///Capacity of raw buffers.
|
///Capacity of raw buffers.
|
||||||
static immutable bufferLength8_ = 8;
|
static immutable bufferLength8_ = 8;
|
||||||
|
@ -60,9 +62,9 @@ final class Reader
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
///Buffer to hold UTF-8 data before decoding.
|
///Buffer to hold UTF-8 data before decoding.
|
||||||
char[bufferLength8_] rawBuffer8_;
|
char[bufferLength8_ + 1] rawBuffer8_;
|
||||||
///Buffer to hold UTF-16 data before decoding.
|
///Buffer to hold UTF-16 data before decoding.
|
||||||
wchar[bufferLength16_] rawBuffer16_;
|
wchar[bufferLength16_ + 1] rawBuffer16_;
|
||||||
}
|
}
|
||||||
///Number of elements held in the used raw buffer.
|
///Number of elements held in the used raw buffer.
|
||||||
uint rawUsed_ = 0;
|
uint rawUsed_ = 0;
|
||||||
|
@ -71,18 +73,23 @@ final class Reader
|
||||||
/**
|
/**
|
||||||
* Construct a Reader.
|
* Construct a Reader.
|
||||||
*
|
*
|
||||||
* Params: stream = Input stream. Must be readable.
|
* Params: stream = Input stream. Must be readable and seekable.
|
||||||
*
|
*
|
||||||
* Throws: ReaderException if the stream is invalid.
|
* Throws: ReaderException if the stream is invalid.
|
||||||
*/
|
*/
|
||||||
this(Stream stream)
|
this(Stream stream)
|
||||||
in{assert(stream.readable, "Can't read YAML from a non-readable stream");}
|
in
|
||||||
|
{
|
||||||
|
assert(stream.readable && stream.seekable,
|
||||||
|
"Can't read YAML from a stream that is not readable and seekable");
|
||||||
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
stream_ = new EndianStream(stream);
|
stream_ = new EndianStream(stream);
|
||||||
|
available_ = stream_.available;
|
||||||
|
|
||||||
//handle files short enough not to have a BOM
|
//handle files short enough not to have a BOM
|
||||||
if(stream_.available < 2)
|
if(available_ < 2)
|
||||||
{
|
{
|
||||||
encoding_ = Encoding.UTF_8;
|
encoding_ = Encoding.UTF_8;
|
||||||
return;
|
return;
|
||||||
|
@ -104,16 +111,17 @@ final class Reader
|
||||||
encoding_ = Encoding.UTF_16;
|
encoding_ = Encoding.UTF_16;
|
||||||
rawBuffer16_[0] = stream_.getcw();
|
rawBuffer16_[0] = stream_.getcw();
|
||||||
rawUsed_ = 1;
|
rawUsed_ = 1;
|
||||||
enforce(stream_.available % 2 == 0,
|
enforce(available_ % 2 == 0,
|
||||||
new ReaderException("Odd byte count in an UTF-16 stream"));
|
new ReaderException("Odd byte count in an UTF-16 stream"));
|
||||||
break;
|
break;
|
||||||
case 3, 4:
|
case 3, 4:
|
||||||
enforce(stream_.available % 4 == 0,
|
enforce(available_ % 4 == 0,
|
||||||
new ReaderException("Byte count in an UTF-32 stream not divisible by 4"));
|
new ReaderException("Byte count in an UTF-32 stream not divisible by 4"));
|
||||||
encoding_ = Encoding.UTF_32;
|
encoding_ = Encoding.UTF_32;
|
||||||
break;
|
break;
|
||||||
default: assert(false, "Unknown UTF BOM");
|
default: assert(false, "Unknown UTF BOM");
|
||||||
}
|
}
|
||||||
|
available_ = stream_.available;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Destroy the Reader.
|
///Destroy the Reader.
|
||||||
|
@ -209,7 +217,7 @@ final class Reader
|
||||||
void forward(size_t length = 1)
|
void forward(size_t length = 1)
|
||||||
{
|
{
|
||||||
//This is here due to optimization.
|
//This is here due to optimization.
|
||||||
static newlines = "\n\u0085\u2028\u2029";
|
static newlines = "\n\u0085\u2028\u2029"d;
|
||||||
updateBuffer(length + 1);
|
updateBuffer(length + 1);
|
||||||
|
|
||||||
while(length > 0)
|
while(length > 0)
|
||||||
|
@ -294,16 +302,10 @@ final class Reader
|
||||||
* if nonprintable characters are detected, or
|
* if nonprintable characters are detected, or
|
||||||
* if there is an error reading from the stream.
|
* if there is an error reading from the stream.
|
||||||
*/
|
*/
|
||||||
void loadChars(uint chars)
|
void loadChars(size_t chars)
|
||||||
{
|
{
|
||||||
/**
|
///Get next character from the stream.
|
||||||
* Get next character from the stream.
|
dchar getDChar()
|
||||||
*
|
|
||||||
* Params: available = Bytes available in the stream.
|
|
||||||
*
|
|
||||||
* Returns: Next character in the stream.
|
|
||||||
*/
|
|
||||||
dchar getDChar(in size_t available)
|
|
||||||
{
|
{
|
||||||
switch(encoding_)
|
switch(encoding_)
|
||||||
{
|
{
|
||||||
|
@ -317,13 +319,14 @@ final class Reader
|
||||||
const dchar result = rawBuffer8_[0];
|
const dchar result = rawBuffer8_[0];
|
||||||
--rawUsed_;
|
--rawUsed_;
|
||||||
//Move the data.
|
//Move the data.
|
||||||
temp[0 .. rawUsed_] = rawBuffer8_[1 .. rawUsed_ + 1];
|
*(cast(ulong*)temp.ptr) = *(cast(ulong*)(rawBuffer8_.ptr + 1));
|
||||||
rawBuffer8_[0 .. rawUsed_] = temp[0 .. rawUsed_];
|
*(cast(ulong*)rawBuffer8_.ptr) = *(cast(ulong*)temp.ptr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bytes to read.
|
//Bytes to read.
|
||||||
const readBytes = min(available, bufferLength8_ - rawUsed_);
|
const readBytes = min(available_, bufferLength8_ - rawUsed_);
|
||||||
|
available_ -= readBytes;
|
||||||
//Length of data in rawBuffer8_ after reading.
|
//Length of data in rawBuffer8_ after reading.
|
||||||
const len = rawUsed_ + readBytes;
|
const len = rawUsed_ + readBytes;
|
||||||
//Read the data.
|
//Read the data.
|
||||||
|
@ -342,7 +345,8 @@ final class Reader
|
||||||
//Temp buffer for moving data in rawBuffer8_.
|
//Temp buffer for moving data in rawBuffer8_.
|
||||||
wchar[bufferLength16_] temp;
|
wchar[bufferLength16_] temp;
|
||||||
//Words to read.
|
//Words to read.
|
||||||
size_t readWords = min(available / 2, bufferLength16_ - rawUsed_);
|
size_t readWords = min(available_ / 2, bufferLength16_ - rawUsed_);
|
||||||
|
available_ -= readWords * 2;
|
||||||
//Length of data in rawBuffer16_ after reading.
|
//Length of data in rawBuffer16_ after reading.
|
||||||
size_t len = rawUsed_;
|
size_t len = rawUsed_;
|
||||||
//Read the data.
|
//Read the data.
|
||||||
|
@ -365,6 +369,7 @@ final class Reader
|
||||||
return result;
|
return result;
|
||||||
case Encoding.UTF_32:
|
case Encoding.UTF_32:
|
||||||
dchar result;
|
dchar result;
|
||||||
|
available_ -= 4;
|
||||||
stream_.read(result);
|
stream_.read(result);
|
||||||
return result;
|
return result;
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
|
@ -374,13 +379,11 @@ final class Reader
|
||||||
const oldLength = buffer_.length;
|
const oldLength = buffer_.length;
|
||||||
const oldPosition = stream_.position;
|
const oldPosition = stream_.position;
|
||||||
|
|
||||||
|
|
||||||
//Preallocating memory to limit GC reallocations.
|
//Preallocating memory to limit GC reallocations.
|
||||||
buffer_.length = buffer_.length + chars;
|
buffer_.length = buffer_.length + chars;
|
||||||
scope(exit)
|
scope(exit)
|
||||||
{
|
{
|
||||||
buffer_.length = buffer_.length - chars;
|
buffer_.length = buffer_.length - chars;
|
||||||
|
|
||||||
enforce(printable(buffer_[oldLength .. $]),
|
enforce(printable(buffer_[oldLength .. $]),
|
||||||
new ReaderException("Special unicode characters are not allowed"));
|
new ReaderException("Special unicode characters are not allowed"));
|
||||||
}
|
}
|
||||||
|
@ -388,8 +391,7 @@ final class Reader
|
||||||
try for(uint c = 0; chars; --chars, ++c)
|
try for(uint c = 0; chars; --chars, ++c)
|
||||||
{
|
{
|
||||||
if(done){break;}
|
if(done){break;}
|
||||||
const available = stream_.available;
|
buffer_[oldLength + c] = getDChar();
|
||||||
buffer_[oldLength + c] = getDChar(available);
|
|
||||||
}
|
}
|
||||||
catch(UtfException e)
|
catch(UtfException e)
|
||||||
{
|
{
|
||||||
|
@ -428,7 +430,7 @@ final class Reader
|
||||||
///Are we done reading?
|
///Are we done reading?
|
||||||
@property bool done()
|
@property bool done()
|
||||||
{
|
{
|
||||||
return (stream_.available == 0 &&
|
return (available_ == 0 &&
|
||||||
((encoding_ == Encoding.UTF_8 && rawUsed_ == 0) ||
|
((encoding_ == Encoding.UTF_8 && rawUsed_ == 0) ||
|
||||||
(encoding_ == Encoding.UTF_16 && rawUsed_ == 0) ||
|
(encoding_ == Encoding.UTF_16 && rawUsed_ == 0) ||
|
||||||
encoding_ == Encoding.UTF_32));
|
encoding_ == Encoding.UTF_32));
|
||||||
|
|
102
dyaml/scanner.d
102
dyaml/scanner.d
|
@ -690,7 +690,7 @@ final class Scanner
|
||||||
return reader_.column == 0 &&
|
return reader_.column == 0 &&
|
||||||
reader_.peek() == '-' &&
|
reader_.peek() == '-' &&
|
||||||
reader_.prefix(3) == "---" &&
|
reader_.prefix(3) == "---" &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Check if the next token is DOCUMENT-END: ^ '...' (' '|'\n')
|
///Check if the next token is DOCUMENT-END: ^ '...' (' '|'\n')
|
||||||
|
@ -700,14 +700,14 @@ final class Scanner
|
||||||
return reader_.column == 0 &&
|
return reader_.column == 0 &&
|
||||||
reader_.peek() == '.' &&
|
reader_.peek() == '.' &&
|
||||||
reader_.prefix(3) == "..." &&
|
reader_.prefix(3) == "..." &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
///Check if the next token is BLOCK-ENTRY: '-' (' '|'\n')
|
///Check if the next token is BLOCK-ENTRY: '-' (' '|'\n')
|
||||||
bool checkBlockEntry()
|
bool checkBlockEntry()
|
||||||
{
|
{
|
||||||
return reader_.peek() == '-' &&
|
return reader_.peek() == '-' &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(1));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -719,7 +719,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
return reader_.peek() == '?' &&
|
return reader_.peek() == '?' &&
|
||||||
(flowLevel_ > 0 ||
|
(flowLevel_ > 0 ||
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(1)));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -731,7 +731,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
return reader_.peek() == ':' &&
|
return reader_.peek() == ':' &&
|
||||||
(flowLevel_ > 0 ||
|
(flowLevel_ > 0 ||
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(1)));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -753,9 +753,9 @@ final class Scanner
|
||||||
bool checkPlain()
|
bool checkPlain()
|
||||||
{
|
{
|
||||||
const c = reader_.peek();
|
const c = reader_.peek();
|
||||||
return !("-?:,[]{}#&*!|>\'\"%@` \t\0\n\r\u0085\u2028\u2029".canFind(c)) ||
|
return !("-?:,[]{}#&*!|>\'\"%@` \t\0\n\r\u0085\u2028\u2029"d.canFind(c)) ||
|
||||||
(!" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(1)) &&
|
(!" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(1)) &&
|
||||||
(c == '-' || (flowLevel_ == 0 && "?:".canFind(c))));
|
(c == '-' || (flowLevel_ == 0 && "?:"d.canFind(c))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -770,7 +770,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
uint length = 0;
|
uint length = 0;
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
while(isAlphaNum(c) || "-_".canFind(c))
|
while(isAlphaNum(c) || "-_"d.canFind(c))
|
||||||
{
|
{
|
||||||
++length;
|
++length;
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
|
@ -788,7 +788,7 @@ final class Scanner
|
||||||
dstring scanToNextBreak()
|
dstring scanToNextBreak()
|
||||||
{
|
{
|
||||||
uint length = 0;
|
uint length = 0;
|
||||||
while(!"\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(length))){++length;}
|
while(!"\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(length))){++length;}
|
||||||
return reader_.get(length);
|
return reader_.get(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,7 +855,7 @@ final class Scanner
|
||||||
//Scan directive name.
|
//Scan directive name.
|
||||||
const name = scanAlphaNumeric!"a directive"(startMark);
|
const name = scanAlphaNumeric!"a directive"(startMark);
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected alphanumeric, - or _, but found "
|
"expected alphanumeric, - or _, but found "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
|
@ -876,7 +876,7 @@ final class Scanner
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
|
|
||||||
result ~= '.' ~ scanYAMLDirectiveNumber(startMark);
|
result ~= '.' ~ scanYAMLDirectiveNumber(startMark);
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected a digit or '.', but found: "
|
"expected a digit or '.', but found: "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
|
@ -922,7 +922,7 @@ final class Scanner
|
||||||
dstring scanTagDirectivePrefix(in Mark startMark)
|
dstring scanTagDirectivePrefix(in Mark startMark)
|
||||||
{
|
{
|
||||||
const value = scanTagURI("directive", startMark);
|
const value = scanTagURI("directive", startMark);
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a directive prefix", startMark,
|
new Error("While scanning a directive prefix", startMark,
|
||||||
"expected ' ', but found" ~ to!string(reader_.peek()),
|
"expected ' ', but found" ~ to!string(reader_.peek()),
|
||||||
reader_.mark));
|
reader_.mark));
|
||||||
|
@ -935,7 +935,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
findNextNonSpace();
|
findNextNonSpace();
|
||||||
if(reader_.peek() == '#'){scanToNextBreak();}
|
if(reader_.peek() == '#'){scanToNextBreak();}
|
||||||
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce("\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected comment or a line break, but found"
|
"expected comment or a line break, but found"
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
|
@ -964,7 +964,7 @@ final class Scanner
|
||||||
dstring value = i == '*' ? scanAlphaNumeric!("an alias")(startMark)
|
dstring value = i == '*' ? scanAlphaNumeric!("an alias")(startMark)
|
||||||
: scanAlphaNumeric!("an anchor")(startMark);
|
: scanAlphaNumeric!("an anchor")(startMark);
|
||||||
|
|
||||||
enforce((" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()) ||
|
enforce((" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()) ||
|
||||||
("?:,]}%@").canFind(reader_.peek())),
|
("?:,]}%@").canFind(reader_.peek())),
|
||||||
new Error("While scanning an " ~ (i == '*') ? "alias" : "anchor",
|
new Error("While scanning an " ~ (i == '*') ? "alias" : "anchor",
|
||||||
startMark, "expected alphanumeric, - or _, but found "~
|
startMark, "expected alphanumeric, - or _, but found "~
|
||||||
|
@ -999,7 +999,7 @@ final class Scanner
|
||||||
reader_.mark));
|
reader_.mark));
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
}
|
}
|
||||||
else if(" \t\0\n\r\u0085\u2028\u2029".canFind(c))
|
else if(" \t\0\n\r\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
suffix = "!";
|
suffix = "!";
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
|
@ -1009,7 +1009,7 @@ final class Scanner
|
||||||
uint length = 1;
|
uint length = 1;
|
||||||
bool useHandle = false;
|
bool useHandle = false;
|
||||||
|
|
||||||
while(!" \0\n\r\u0085\u2028\u2029".canFind(c))
|
while(!" \0\n\r\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
if(c == '!')
|
if(c == '!')
|
||||||
{
|
{
|
||||||
|
@ -1030,7 +1030,7 @@ final class Scanner
|
||||||
suffix = scanTagURI("tag", startMark);
|
suffix = scanTagURI("tag", startMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a tag", startMark,
|
new Error("While scanning a tag", startMark,
|
||||||
"expected ' ' but found" ~ to!string(reader_.peek()),
|
"expected ' ' but found" ~ to!string(reader_.peek()),
|
||||||
reader_.mark));
|
reader_.mark));
|
||||||
|
@ -1078,7 +1078,7 @@ final class Scanner
|
||||||
while(reader_.column == indent && reader_.peek() != '\0')
|
while(reader_.column == indent && reader_.peek() != '\0')
|
||||||
{
|
{
|
||||||
appender_.put(breaks);
|
appender_.put(breaks);
|
||||||
const bool leadingNonSpace = !" \t".canFind(reader_.peek());
|
const bool leadingNonSpace = !" \t"d.canFind(reader_.peek());
|
||||||
appender_.put(scanToNextBreak());
|
appender_.put(scanToNextBreak());
|
||||||
lineBreak = ""d ~ scanLineBreak();
|
lineBreak = ""d ~ scanLineBreak();
|
||||||
|
|
||||||
|
@ -1092,7 +1092,7 @@ final class Scanner
|
||||||
|
|
||||||
//This is the folding according to the specification:
|
//This is the folding according to the specification:
|
||||||
if(style == ScalarStyle.Folded && lineBreak == "\n" &&
|
if(style == ScalarStyle.Folded && lineBreak == "\n" &&
|
||||||
leadingNonSpace && !" \t".canFind(reader_.peek()))
|
leadingNonSpace && !" \t"d.canFind(reader_.peek()))
|
||||||
{
|
{
|
||||||
if(breaks.length == 0){appender_.put(' ');}
|
if(breaks.length == 0){appender_.put(' ');}
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1128,7 @@ final class Scanner
|
||||||
///Get chomping indicator, if detected. Return false otherwise.
|
///Get chomping indicator, if detected. Return false otherwise.
|
||||||
bool getChomping()
|
bool getChomping()
|
||||||
{
|
{
|
||||||
if(!"+-".canFind(c)){return false;}
|
if(!"+-"d.canFind(c)){return false;}
|
||||||
chomping = c == '+' ? Chomping.Keep : Chomping.Strip;
|
chomping = c == '+' ? Chomping.Keep : Chomping.Strip;
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
c = reader_.peek();
|
c = reader_.peek();
|
||||||
|
@ -1153,7 +1153,7 @@ final class Scanner
|
||||||
if(getChomping()) {getIncrement();}
|
if(getChomping()) {getIncrement();}
|
||||||
else if(getIncrement()){getChomping();}
|
else if(getIncrement()){getChomping();}
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(c),
|
enforce(" \0\n\r\u0085\u2028\u2029"d.canFind(c),
|
||||||
new Error("While scanning a block scalar", startMark,
|
new Error("While scanning a block scalar", startMark,
|
||||||
"expected chomping or indentation indicator, but found "
|
"expected chomping or indentation indicator, but found "
|
||||||
~ to!string(c), reader_.mark));
|
~ to!string(c), reader_.mark));
|
||||||
|
@ -1167,7 +1167,7 @@ final class Scanner
|
||||||
findNextNonSpace();
|
findNextNonSpace();
|
||||||
if(reader_.peek == '#'){scanToNextBreak();}
|
if(reader_.peek == '#'){scanToNextBreak();}
|
||||||
|
|
||||||
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce("\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()),
|
||||||
new Error("While scanning a block scalar", startMark,
|
new Error("While scanning a block scalar", startMark,
|
||||||
"expected a comment or a line break, but found "
|
"expected a comment or a line break, but found "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
|
@ -1181,7 +1181,7 @@ final class Scanner
|
||||||
uint maxIndent;
|
uint maxIndent;
|
||||||
Mark endMark = reader_.mark;
|
Mark endMark = reader_.mark;
|
||||||
|
|
||||||
while(" \n\r\u0085\u2028\u2029".canFind(reader_.peek()))
|
while(" \n\r\u0085\u2028\u2029"d.canFind(reader_.peek()))
|
||||||
{
|
{
|
||||||
if(reader_.peek() != ' ')
|
if(reader_.peek() != ' ')
|
||||||
{
|
{
|
||||||
|
@ -1205,7 +1205,7 @@ final class Scanner
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
while(reader_.column < indent && reader_.peek() == ' '){reader_.forward();}
|
while(reader_.column < indent && reader_.peek() == ' '){reader_.forward();}
|
||||||
if(!"\n\r\u0085\u2028\u2029".canFind(reader_.peek())){break;}
|
if(!"\n\r\u0085\u2028\u2029"d.canFind(reader_.peek())){break;}
|
||||||
chunks ~= scanLineBreak();
|
chunks ~= scanLineBreak();
|
||||||
endMark = reader_.mark;
|
endMark = reader_.mark;
|
||||||
}
|
}
|
||||||
|
@ -1242,7 +1242,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
uint length = 0;
|
uint length = 0;
|
||||||
while(!(" \t\0\n\r\u0085\u2028\u2029".canFind(c) || "\'\"\\".canFind(c)))
|
while(!(" \t\0\n\r\u0085\u2028\u2029\'\"\\"d.canFind(c)))
|
||||||
{
|
{
|
||||||
++length;
|
++length;
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
|
@ -1258,7 +1258,7 @@ final class Scanner
|
||||||
reader_.forward(2);
|
reader_.forward(2);
|
||||||
}
|
}
|
||||||
else if((quotes == ScalarStyle.DoubleQuoted && c == '\'') ||
|
else if((quotes == ScalarStyle.DoubleQuoted && c == '\'') ||
|
||||||
(quotes == ScalarStyle.SingleQuoted && "\"\\".canFind(c)))
|
(quotes == ScalarStyle.SingleQuoted && "\"\\"d.canFind(c)))
|
||||||
{
|
{
|
||||||
appender_.put(c);
|
appender_.put(c);
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
|
@ -1290,17 +1290,16 @@ final class Scanner
|
||||||
dstring hex = reader_.get(length);
|
dstring hex = reader_.get(length);
|
||||||
appender_.put(cast(dchar)parse!int(hex, 16));
|
appender_.put(cast(dchar)parse!int(hex, 16));
|
||||||
}
|
}
|
||||||
else if("\n\r\u0085\u2028\u2029".canFind(c))
|
else if("\n\r\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
scanLineBreak();
|
scanLineBreak();
|
||||||
appender_.put(scanFlowScalarBreaks(startMark));
|
appender_.put(scanFlowScalarBreaks(startMark));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Error("While scanning a double quoted scalar",
|
throw new Error("While scanning a double quoted scalar", startMark,
|
||||||
startMark,
|
"found unknown escape character: " ~ to!string(c),
|
||||||
"found unknown escape character: " ~
|
reader_.mark);
|
||||||
to!string(c), reader_.mark);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1314,15 +1313,14 @@ final class Scanner
|
||||||
void scanFlowScalarSpaces(in Mark startMark)
|
void scanFlowScalarSpaces(in Mark startMark)
|
||||||
{
|
{
|
||||||
uint length = 0;
|
uint length = 0;
|
||||||
while(" \t".canFind(reader_.peek(length))){++length;}
|
while(" \t"d.canFind(reader_.peek(length))){++length;}
|
||||||
const whitespaces = reader_.get(length);
|
const whitespaces = reader_.get(length);
|
||||||
|
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
enforce(c != '\0',
|
enforce(c != '\0', new Error("While scanning a quoted scalar", startMark,
|
||||||
new Error("While scanning a quoted scalar", startMark,
|
|
||||||
"found unexpected end of stream", reader_.mark));
|
"found unexpected end of stream", reader_.mark));
|
||||||
|
|
||||||
if("\n\r\u0085\u2028\u2029".canFind(c))
|
if("\n\r\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
const lineBreak = scanLineBreak();
|
const lineBreak = scanLineBreak();
|
||||||
const breaks = scanFlowScalarBreaks(startMark);
|
const breaks = scanFlowScalarBreaks(startMark);
|
||||||
|
@ -1343,15 +1341,15 @@ final class Scanner
|
||||||
//Instead of checking indentation, we check for document separators.
|
//Instead of checking indentation, we check for document separators.
|
||||||
const prefix = reader_.prefix(3);
|
const prefix = reader_.prefix(3);
|
||||||
if((prefix == "---" || prefix == "...") &&
|
if((prefix == "---" || prefix == "...") &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3)))
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3)))
|
||||||
{
|
{
|
||||||
throw new Error("While scanning a quoted scalar", startMark,
|
throw new Error("While scanning a quoted scalar", startMark,
|
||||||
"found unexpected document separator", reader_.mark);
|
"found unexpected document separator", reader_.mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(" \t".canFind(reader_.peek())){reader_.forward();}
|
while(" \t"d.canFind(reader_.peek())){reader_.forward();}
|
||||||
|
|
||||||
if("\n\r\u0085\u2028\u2029".canFind(reader_.peek()))
|
if("\n\r\u0085\u2028\u2029"d.canFind(reader_.peek()))
|
||||||
{
|
{
|
||||||
appender.put(scanLineBreak());
|
appender.put(scanLineBreak());
|
||||||
}
|
}
|
||||||
|
@ -1384,18 +1382,18 @@ final class Scanner
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
bool done = " \t\0\n\r\u0085\u2028\u2029".canFind(c) ||
|
bool done = " \t\0\n\r\u0085\u2028\u2029"d.canFind(c) ||
|
||||||
(flowLevel_ == 0 && c == ':' &&
|
(flowLevel_ == 0 && c == ':' &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(length + 1))) ||
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(length + 1))) ||
|
||||||
(flowLevel_ > 0 && ",:?[]{}".canFind(c));
|
(flowLevel_ > 0 && ",:?[]{}"d.canFind(c));
|
||||||
if(done){break;}
|
if(done){break;}
|
||||||
++length;
|
++length;
|
||||||
}
|
}
|
||||||
|
|
||||||
//It's not clear what we should do with ':' in the flow context.
|
//It's not clear what we should do with ':' in the flow context.
|
||||||
if(flowLevel_ > 0 && c == ':' &&
|
if(flowLevel_ > 0 && c == ':' &&
|
||||||
!" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(length + 1)) &&
|
!" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(length + 1)) &&
|
||||||
!",[]{}".canFind(reader_.peek(length + 1)))
|
!",[]{}"d.canFind(reader_.peek(length + 1)))
|
||||||
{
|
{
|
||||||
reader_.forward(length);
|
reader_.forward(length);
|
||||||
throw new Error("While scanning a plain scalar", startMark,
|
throw new Error("While scanning a plain scalar", startMark,
|
||||||
|
@ -1434,7 +1432,7 @@ final class Scanner
|
||||||
dstring whitespaces = reader_.get(length);
|
dstring whitespaces = reader_.get(length);
|
||||||
|
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
if("\n\r\u0085\u2028\u2029".canFind(c))
|
if("\n\r\u0085\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
const lineBreak = scanLineBreak();
|
const lineBreak = scanLineBreak();
|
||||||
allowSimpleKey_ = true;
|
allowSimpleKey_ = true;
|
||||||
|
@ -1442,13 +1440,13 @@ final class Scanner
|
||||||
bool end()
|
bool end()
|
||||||
{
|
{
|
||||||
return ["---"d, "..."d].canFind(reader_.prefix(3)) &&
|
return ["---"d, "..."d].canFind(reader_.prefix(3)) &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3));
|
" \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(end()){return "";}
|
if(end()){return "";}
|
||||||
|
|
||||||
dstring breaks;
|
dstring breaks;
|
||||||
while(" \n\r\u0085\u2028\u2029".canFind(reader_.peek()))
|
while(" \n\r\u0085\u2028\u2029"d.canFind(reader_.peek()))
|
||||||
{
|
{
|
||||||
if(reader_.peek() == ' '){reader_.forward();}
|
if(reader_.peek() == ' '){reader_.forward();}
|
||||||
else
|
else
|
||||||
|
@ -1482,7 +1480,7 @@ final class Scanner
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
if(c != ' ')
|
if(c != ' ')
|
||||||
{
|
{
|
||||||
while(isAlphaNum(c) || "-_".canFind(c))
|
while(isAlphaNum(c) || "-_"d.canFind(c))
|
||||||
{
|
{
|
||||||
++length;
|
++length;
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
|
@ -1508,7 +1506,7 @@ final class Scanner
|
||||||
uint length = 0;
|
uint length = 0;
|
||||||
|
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
while(isAlphaNum(c) || "-;/?:@&=+$,_.!~*\'()[]%".canFind(c))
|
while(isAlphaNum(c) || "-;/?:@&=+$,_.!~*\'()[]%"d.canFind(c))
|
||||||
{
|
{
|
||||||
if(c == '%')
|
if(c == '%')
|
||||||
{
|
{
|
||||||
|
@ -1594,13 +1592,13 @@ final class Scanner
|
||||||
{
|
{
|
||||||
const c = reader_.peek();
|
const c = reader_.peek();
|
||||||
|
|
||||||
if("\r\n\u0085".canFind(c))
|
if("\r\n\u0085"d.canFind(c))
|
||||||
{
|
{
|
||||||
if(reader_.prefix(2) == "\r\n"){reader_.forward(2);}
|
if(reader_.prefix(2) == "\r\n"d){reader_.forward(2);}
|
||||||
else{reader_.forward();}
|
else{reader_.forward();}
|
||||||
return '\n';
|
return '\n';
|
||||||
}
|
}
|
||||||
if("\u2028\u2029".canFind(c))
|
if("\u2028\u2029"d.canFind(c))
|
||||||
{
|
{
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
return c;
|
return c;
|
||||||
|
|
Loading…
Reference in a new issue