make SliceBuilder safer to use.

This commit is contained in:
Cameron Ross 2018-04-17 00:17:10 -03:00
parent 4cad68f924
commit 568acb832a
No known key found for this signature in database
GPG key ID: 777897D98DC91C54
2 changed files with 17 additions and 17 deletions

View file

@ -531,15 +531,17 @@ public:
/// end of the slice being built, the slice is extended (trivial operation). /// end of the slice being built, the slice is extended (trivial operation).
/// ///
/// See_Also: begin /// See_Also: begin
void write(char[] str) @trusted pure nothrow @nogc void write(char[] str) @safe pure nothrow @nogc
{ {
assert(inProgress, "write called without begin"); assert(inProgress, "write called without begin");
assert(end_ <= reader_.bufferOffset_, assert(end_ <= reader_.bufferOffset_,
"AT START: Slice ends after buffer position"); "AT START: Slice ends after buffer position");
// Nothing? Already done.
if (str.length == 0) { return; }
// If str starts at the end of the slice (is a string returned by a Reader // If str starts at the end of the slice (is a string returned by a Reader
// method), just extend the slice to contain str. // method), just extend the slice to contain str.
if(str.ptr == reader_.buffer_.ptr + end_) if(&str[0] == &reader_.buffer_[end_])
{ {
end_ += str.length; end_ += str.length;
} }
@ -547,8 +549,7 @@ public:
// by a Reader method and point to buffer. So we need to memmove. // by a Reader method and point to buffer. So we need to memmove.
else else
{ {
core.stdc.string.memmove(reader_.buffer_.ptr + end_, cast(char*)str.ptr, copy(str, reader_.buffer_[end_..end_ + str.length * char.sizeof]);
str.length * char.sizeof);
end_ += str.length; end_ += str.length;
} }
} }
@ -585,7 +586,7 @@ public:
/// position = Position to insert the character at in code units, not code points. /// position = Position to insert the character at in code units, not code points.
/// Must be less than slice length(); a previously returned length() /// Must be less than slice length(); a previously returned length()
/// can be used. /// can be used.
void insert(const dchar c, const size_t position) @system pure nothrow @nogc void insert(const dchar c, const size_t position) @safe pure nothrow @nogc
{ {
assert(inProgress, "insert called without begin"); assert(inProgress, "insert called without begin");
assert(start_ + position <= end_, "Trying to insert after the end of the slice"); assert(start_ + position <= end_, "Trying to insert after the end of the slice");
@ -600,9 +601,8 @@ public:
if(movedLength > 0) if(movedLength > 0)
{ {
core.stdc.string.memmove(reader_.buffer_.ptr + point + bytes, copy(reader_.buffer_[point..point + movedLength * char.sizeof],
reader_.buffer_.ptr + point, reader_.buffer_[point + bytes..point + bytes + movedLength * char.sizeof]);
movedLength * char.sizeof);
} }
reader_.buffer_[point .. point + bytes] = encodeBuf[0 .. bytes]; reader_.buffer_[point .. point + bytes] = encodeBuf[0 .. bytes];
end_ += bytes; end_ += bytes;
@ -635,9 +635,9 @@ public:
/// ended either by commit()-ing or reverting through the destructor. /// ended either by commit()-ing or reverting through the destructor.
/// ///
/// Saves the current state of a slice. /// Saves the current state of a slice.
this(ref SliceBuilder builder) @system pure nothrow @nogc this(SliceBuilder* builder) @safe pure nothrow @nogc
{ {
builder_ = &builder; builder_ = builder;
stackLevel_ = builder_.endStackUsed_; stackLevel_ = builder_.endStackUsed_;
builder_.push(); builder_.push();
} }

View file

@ -1210,7 +1210,7 @@ final class Scanner
/// Scan a block scalar token with specified style. /// Scan a block scalar token with specified style.
/// ///
/// 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.
Token scanBlockScalar(const ScalarStyle style) @trusted Token scanBlockScalar(const ScalarStyle style) @safe
{ {
const startMark = reader_.mark; const startMark = reader_.mark;
@ -1233,7 +1233,7 @@ final class Scanner
alias Transaction = SliceBuilder.Transaction; alias Transaction = SliceBuilder.Transaction;
// Used to strip the last line breaks written to the slice at the end of the // Used to strip the last line breaks written to the slice at the end of the
// scalar, which may be needed based on chomping. // scalar, which may be needed based on chomping.
Transaction breaksTransaction = Transaction(reader_.sliceBuilder); Transaction breaksTransaction = Transaction(&reader_.sliceBuilder);
// Read the first indentation/line breaks before the scalar. // Read the first indentation/line breaks before the scalar.
size_t startLen = reader_.sliceBuilder.length; size_t startLen = reader_.sliceBuilder.length;
if(increment == int.min) if(increment == int.min)
@ -1263,7 +1263,7 @@ final class Scanner
// This transaction serves to rollback data read in the // This transaction serves to rollback data read in the
// scanBlockScalarBreaksToSlice() call. // scanBlockScalarBreaksToSlice() call.
breaksTransaction = Transaction(reader_.sliceBuilder); breaksTransaction = Transaction(&reader_.sliceBuilder);
startLen = reader_.sliceBuilder.length; startLen = reader_.sliceBuilder.length;
// The line breaks should actually be written _after_ the if() block // The line breaks should actually be written _after_ the if() block
// below. We work around that by inserting // below. We work around that by inserting
@ -1712,7 +1712,7 @@ final class Scanner
/// Scan plain scalar token (no block, no quotes). /// Scan plain scalar token (no block, no quotes).
/// ///
/// 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.
Token scanPlain() @trusted Token scanPlain() @safe
{ {
// We keep track of the allowSimpleKey_ flag here. // We keep track of the allowSimpleKey_ flag here.
// Indentation rules are loosed for the flow context // Indentation rules are loosed for the flow context
@ -1788,7 +1788,7 @@ final class Scanner
endMark = reader_.mark; endMark = reader_.mark;
spacesTransaction.commit(); spacesTransaction.commit();
spacesTransaction = Transaction(reader_.sliceBuilder); spacesTransaction = Transaction(&reader_.sliceBuilder);
const startLength = reader_.sliceBuilder.length; const startLength = reader_.sliceBuilder.length;
scanPlainSpacesToSlice(startMark); scanPlainSpacesToSlice(startMark);
@ -1809,7 +1809,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.
void scanPlainSpacesToSlice(const Mark startMark) @system void scanPlainSpacesToSlice(const Mark startMark) @safe
{ {
// 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!
@ -1847,7 +1847,7 @@ final class Scanner
bool extraBreaks = false; bool extraBreaks = false;
alias Transaction = SliceBuilder.Transaction; alias Transaction = SliceBuilder.Transaction;
auto transaction = Transaction(reader_.sliceBuilder); auto transaction = Transaction(&reader_.sliceBuilder);
if(lineBreak != '\n') { reader_.sliceBuilder.write(lineBreak); } if(lineBreak != '\n') { reader_.sliceBuilder.write(lineBreak); }
while(search.canFind(reader_.peek())) while(search.canFind(reader_.peek()))
{ {