/// <summary> /// Store the given tokenized line buffer. /// </summary> private void StoreLine(Stream stream) { if (_protected) { throw new ReplRuntimeException(ReplExceptionCode.IllegalFunctionCall); } stream.Seek(1, SeekOrigin.Begin); var scanLine = stream.ReadLineNumber(); // check if stream is an empty line after the line number var nextNonWhitespace = stream.SkipWhitespace(); var empty = nextNonWhitespace == -1 || nextNonWhitespace == '\0'; var codePosition = FindCodePosition(scanLine, scanLine); if (empty && codePosition.Deleteable.Length == 0) { throw new ReplRuntimeException(ReplExceptionCode.UndefinedLineNumber); } // read the remainder of the program into a buffer to be pasted back after the write Bytecode.Seek(codePosition.AfterPosition, SeekOrigin.Begin); var rest = Bytecode.ReadToEnd(); Bytecode.Seek(codePosition.StartPosition, SeekOrigin.Begin); var length = 0; // write the line buffer to the program buffer if (!empty) { // set offsets length = stream.ReadToEnd().Length; stream.Seek(0, SeekOrigin.Begin); // pass \x00\xC0\xDE Bytecode.WriteByte(0); Bytecode.Write(((int)(Position + 1 + codePosition.StartPosition + length)).ToBasicUnsignedInteger()); Bytecode.WriteByte((byte)stream.ReadByte()); } // write back the remainder of the program Truncate(rest); // update all next offsets by shifting them by the length of the added line UpdateLineMap(codePosition, length); if (!empty) { _lineNumberMap[scanLine] = codePosition.StartPosition; } _lastStored = scanLine; }
/// <summary> /// Deletes the stored program within specified range /// </summary> /// <param name="startLine">Starting line</param> /// <param name="lastLine">Ending line</param> public void Delete(int startLine, int lastLine) { var codePosition = FindCodePosition(startLine, lastLine); if (codePosition.Deleteable.Length == 0) // no lines selected { throw new ReplRuntimeException(ReplExceptionCode.IllegalFunctionCall); } Bytecode.Seek(codePosition.AfterPosition, SeekOrigin.Begin); var rest = Bytecode.ReadToEnd(); Bytecode.Seek(codePosition.StartPosition, SeekOrigin.Begin); Truncate(rest); UpdateLineMap(codePosition, 0); }