Code determining if a func scanned anything replaced by checking slice length.

This commit is contained in:
Ferdinand Majerech 2014-07-26 02:49:52 +02:00
parent 0ce9dc0b3a
commit 6e2b9a7511

View file

@ -1722,8 +1722,10 @@ final class Scanner
spacesTransaction.commit(); spacesTransaction.commit();
spacesTransaction = Transaction(reader_.sliceBuilder); spacesTransaction = Transaction(reader_.sliceBuilder);
const bool anySpaces = scanPlainSpacesToSlice(startMark); const startLength = reader_.sliceBuilder.length;
if(!anySpaces || (flowLevel_ == 0 && reader_.column < indent)) scanPlainSpacesToSlice(startMark);
if(startLength == reader_.sliceBuilder.length ||
(flowLevel_ == 0 && reader_.column < indent))
{ {
break; break;
} }
@ -1739,7 +1741,7 @@ final class Scanner
/// ///
/// Assumes that the caller is building a slice in Reader, and puts the spaces /// Assumes that the caller is building a slice in Reader, and puts the spaces
/// into that slice. /// into that slice.
bool scanPlainSpacesToSlice(const Mark startMark) @system pure nothrow @nogc void scanPlainSpacesToSlice(const Mark startMark) @system pure nothrow @nogc
{ {
// The specification is really confusing about tabs in plain scalars. // The specification is really confusing about tabs in plain scalars.
// We just forbid them completely. Do not use tabs in YAML! // We just forbid them completely. Do not use tabs in YAML!
@ -1754,17 +1756,11 @@ final class Scanner
if(!"\n\r\u0085\u2028\u2029"d.canFind(c)) if(!"\n\r\u0085\u2028\u2029"d.canFind(c))
{ {
// We have spaces, but no newline. // We have spaces, but no newline.
if(whitespaces.length > 0) if(whitespaces.length > 0) { reader_.sliceBuilder.write(whitespaces); }
{ return;
reader_.sliceBuilder.write(whitespaces);
return true;
}
// No spaces or newline.
return false;
} }
// Newline after the spaces (if any) // Newline after the spaces (if any)
bool anySpaces = false;
const lineBreak = scanLineBreak(); const lineBreak = scanLineBreak();
allowSimpleKey_ = true; allowSimpleKey_ = true;
@ -1774,7 +1770,7 @@ final class Scanner
&& " \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3)); && " \t\0\n\r\u0085\u2028\u2029"d.canFind(reader_.peek(3));
} }
if(end(reader_)) { return false; } if(end(reader_)) { return; }
bool extraBreaks = false; bool extraBreaks = false;
@ -1789,22 +1785,14 @@ final class Scanner
const lBreak = scanLineBreak(); const lBreak = scanLineBreak();
extraBreaks = true; extraBreaks = true;
reader_.sliceBuilder.write(lBreak); reader_.sliceBuilder.write(lBreak);
if(end(reader_))
{ if(end(reader_)) { return; }
return false;
}
} }
} }
transaction.commit(); transaction.commit();
// No line breaks, only a space. // No line breaks, only a space.
if(lineBreak == '\n' && !extraBreaks) { reader_.sliceBuilder.write(' '); } if(lineBreak == '\n' && !extraBreaks) { reader_.sliceBuilder.write(' '); }
// We've written some spaces into the slice if:
// (lineBreak != '\n' || extraBreaks || lineBreak == '\n' && !extraBreaks).
// That simplifies to (lineBreak != '\n' || lineBreak == '\n') which
// simplifies to (true)
return true;
} }
/// Scan handle of a tag token. /// Scan handle of a tag token.
@ -1857,7 +1845,7 @@ final class Scanner
{ {
// Note: we do not check if URI is well-formed. // Note: we do not check if URI is well-formed.
dchar c = reader_.peek(); dchar c = reader_.peek();
bool anyChars = false; const startLen = reader_.sliceBuilder.length;
{ {
uint length = 0; uint length = 0;
while(c.isAlphaNum || "-;/?:@&=+$,_.!~*\'()[]%"d.canFind(c)) while(c.isAlphaNum || "-;/?:@&=+$,_.!~*\'()[]%"d.canFind(c))
@ -1866,9 +1854,8 @@ final class Scanner
{ {
auto chars = reader_.get(length); auto chars = reader_.get(length);
reader_.sliceBuilder.write(chars); reader_.sliceBuilder.write(chars);
anyChars = anyChars || (length > 0);
length = 0; length = 0;
anyChars = scanURIEscapesToSlice!name(startMark) || anyChars; scanURIEscapesToSlice!name(startMark);
if(error_) { return; } if(error_) { return; }
} }
else { ++length; } else { ++length; }
@ -1878,11 +1865,11 @@ final class Scanner
{ {
auto chars = reader_.get(length); auto chars = reader_.get(length);
reader_.sliceBuilder.write(chars); reader_.sliceBuilder.write(chars);
anyChars = true;
length = 0; length = 0;
} }
} }
if(anyChars) { return; } // OK if we scanned something, error otherwise.
if(reader_.sliceBuilder.length > startLen) { return; }
enum contextMsg = "While parsing a " ~ name; enum contextMsg = "While parsing a " ~ name;
setError(contextMsg, startMark, buildMsg("expected URI, but found: ", c), setError(contextMsg, startMark, buildMsg("expected URI, but found: ", c),
@ -1895,10 +1882,8 @@ final class Scanner
/// Assumes that the caller is building a slice in Reader, and puts the scanned /// Assumes that the caller is building a slice in Reader, and puts the scanned
/// characters into that slice. /// characters into that slice.
/// ///
/// Returns: true if any escapes were scanned, false otherwise.
///
/// In case of an error, error_ is set. Use throwIfError() to handle this. /// In case of an error, error_ is set. Use throwIfError() to handle this.
bool scanURIEscapesToSlice(string name)(const Mark startMark) void scanURIEscapesToSlice(string name)(const Mark startMark)
@system pure nothrow // @nogc @system pure nothrow // @nogc
{ {
// URI escapes encode a UTF-8 string. We store UTF-8 code units here for // URI escapes encode a UTF-8 string. We store UTF-8 code units here for
@ -1906,20 +1891,17 @@ final class Scanner
char[4] bytes; char[4] bytes;
size_t bytesUsed; size_t bytesUsed;
Mark mark = reader_.mark; Mark mark = reader_.mark;
// True if any characters were written to the slice.
bool anyChars;
// Get one dchar by decoding data from bytes. // Get one dchar by decoding data from bytes.
// //
// This is probably slow, but simple and URI escapes are extremely uncommon // This is probably slow, but simple and URI escapes are extremely uncommon
// in YAML. // in YAML.
static size_t getDchar(char[] bytes, Reader reader_, ref bool anyChars) static size_t getDchar(char[] bytes, Reader reader_)
{ {
import std.utf; import std.utf;
size_t nextChar; size_t nextChar;
const c = std.utf.decode(bytes[], nextChar); const c = std.utf.decode(bytes[], nextChar);
reader_.sliceBuilder.write(c); reader_.sliceBuilder.write(c);
anyChars = true;
if(bytes.length - nextChar > 0) if(bytes.length - nextChar > 0)
{ {
core.stdc.string.memmove(bytes.ptr, bytes.ptr + nextChar, core.stdc.string.memmove(bytes.ptr, bytes.ptr + nextChar,
@ -1936,7 +1918,7 @@ final class Scanner
reader_.forward(); reader_.forward();
if(bytesUsed == bytes.length) if(bytesUsed == bytes.length)
{ {
bytesUsed = getDchar(bytes[], reader_, anyChars); bytesUsed = getDchar(bytes[], reader_);
} }
char b = 0; char b = 0;
@ -1950,7 +1932,7 @@ final class Scanner
auto msg = buildMsg("expected URI escape sequence of 2 " auto msg = buildMsg("expected URI escape sequence of 2 "
"hexadecimal numbers, but found: ", c); "hexadecimal numbers, but found: ", c);
setError(contextMsg, startMark, msg, reader_.mark); setError(contextMsg, startMark, msg, reader_.mark);
return false; return;
} }
uint digit; uint digit;
@ -1966,19 +1948,17 @@ final class Scanner
reader_.forward(2); reader_.forward(2);
} }
bytesUsed = getDchar(bytes[0 .. bytesUsed], reader_, anyChars); bytesUsed = getDchar(bytes[0 .. bytesUsed], reader_);
} }
catch(UTFException e) catch(UTFException e)
{ {
setError(contextMsg, startMark, e.msg, mark); setError(contextMsg, startMark, e.msg, mark);
return false; return;
} }
catch(Exception e) catch(Exception e)
{ {
assert(false, "Unexpected exception in scanURIEscapesToSlice"); assert(false, "Unexpected exception in scanURIEscapesToSlice");
} }
return anyChars;
} }