public override void Write(byte[] buffer, int offset, int count) { //If there is no way to write or nothing to write then do nothing. if (IsDisposed || count <= 0) { return; } //Keep a counter for how much we can copy or move. long len; //If the buffer is null or empty return for now (dead space)... if (ArrayExtensions.IsNullOrEmpty(buffer, out len)) { return; } //If more data was specified than exists use len if (count > len) { count = (int)len; } //While there is count and the position is less than the end while (count > 0) { //How much can be copied to the current segment with respect to count. len = Binary.Binary.Min(WorkingSegment.m_Length - m_Cursor, count); //Copy len from the buffer at the offset to the working segment's array at the offset + the cursor Array.Copy(buffer, offset, WorkingSegment.m_Array, WorkingSegment.m_Offset + m_Cursor, len); //Move the cursor m_Cursor += len; //Move the position m_Position += len; //Move the offset offset += (int)len; //Adjust count for len copied. //If there is nothing left to do return. if (0 == (count -= (int)len)) { return; } //If at the end of the current segment and not at the end of the stream if (m_Cursor >= WorkingSegment.m_Length && m_Position < m_Count) { //Advance the segment WorkingSegment = Segments[++m_Index]; //Set the cursor to 0 m_Cursor = 0; //Do another iteration continue; } //m_Position is >= m_Count //Add a copy of the memory which remains and set the WorkingSegment (could give via out) WritePersisted(buffer, offset, count); //Get the next segment and account for the segment added WorkingSegment = Segments[++m_Index]; //Set the cursor m_Cursor = count; //Move the position m_Position += count; //Increase for the bytes written. m_Count += count; //Set count to 0; //count -= count; //Done break; } }
public override long Seek(long offset, System.IO.SeekOrigin origin) { if (IsDisposed) { return(-1); } switch (origin) { case System.IO.SeekOrigin.Begin: { //Nothing to do? if (m_Position.Equals(offset)) { return(m_Position); } //If the offset past or at the end (Could goto End) if (offset >= m_Count) { offset = Binary.Binary.LongZero; goto case System.IO.SeekOrigin.End; } else if (offset <= 0) { //Should use End style when offset < 0 but not == 0... WorkingSegment = Segments[(m_Index = 0)]; return(m_Cursor = m_Position = Binary.Binary.LongZero); } //Check for data within the current segment if (offset < m_Position) { //If at the first byte in a new segment go to the last segment if (m_Cursor.Equals(Binary.Binary.LongZero)) { WorkingSegment = Segments[--m_Index]; m_Cursor = WorkingSegment.m_Length; } ////Determine the amount of movement relative to the position //long diff = m_Position - offset; ////If the offset is within the current segment then there is no change of index //if ((m_Cursor -= diff) >= 0) //{ // m_Cursor -= diff; // //return m_Position -= diff; // return m_Position = offset; //} //Combined for performance, if the data is not wihin the segment we search from the beginning anyway. //This could be optomized by searching backward but current should handle that, this implies the locations will always be somewhere in the segment or at the beginning of the stream. //If the offset is within the current segment then there is no change of index if ((m_Cursor -= m_Position - offset) >= Binary.Binary.LongZero) { return(m_Position = offset); } //Seek forward from 0 to find the segment m_Position = m_Index = 0; WorkingSegment = Segments[m_Index]; } else //offset > m_Position { //Determine the amount of movement relative to the position long diff = offset - m_Position; //If the offset is within the current segment then there is no change of index if ((m_Cursor += diff) < WorkingSegment.m_Length) { return(m_Position = offset); } //The position must be moved to the end of the segment with respect to where the cursor was previously. //Keep the same offset for a greater position //Account for where we are already. //The position is added to for the length of the remaining data in the WorkingSegment. //The offset is modified to account for the position in the stream offset -= (m_Position += WorkingSegment.m_Length - (m_Cursor - diff)); //Move to the next segment WorkingSegment = Segments[++m_Index]; //Set the cursor to 0 m_Cursor = Binary.Binary.LongZero; } //Seek forward to find the offset. do { m_Cursor = Binary.Binary.Min(ref WorkingSegment.m_Length, ref offset); m_Position += m_Cursor; offset -= m_Cursor; if (m_Cursor >= WorkingSegment.m_Length) { WorkingSegment = Segments[++m_Index]; m_Cursor = Binary.Binary.LongZero; } }while (offset > Binary.Binary.LongZero); return(m_Position); } case System.IO.SeekOrigin.Current: { //If there is no change in offset return the position if (offset.Equals(Binary.Binary.LongZero)) { return(m_Position); } //When offset < 0 if (offset < Binary.Binary.LongZero) { //Make the offset based on the position offset += m_Position; goto case System.IO.SeekOrigin.Begin; } return(m_Position); } case System.IO.SeekOrigin.End: { //If the offset is referring to a index <= 0 goto the 0th position if (-offset >= m_Count) { //<= 0 offset mean 0 to begin. goto case System.IO.SeekOrigin.Begin; //////If the offset desired is within the working segment no index change is required. ////if (m_Cursor > 0 && offset <= m_Cursor) ////{ //// m_Cursor -= offset; //// return m_Position -= offset; ////} //////Seek backward to find the segment. ////do ////{ //// m_Cursor = Binary.Binary.Min(ref m_Cursor, ref offset); //// m_Position -= m_Cursor; //// offset -= m_Cursor; //// if (offset > 0) //// { //// WorkingSegment = Segments[--m_Index]; //// m_Cursor = WorkingSegment.m_Length; //// } ////} ////while (offset > 0); } //Move to the end position WorkingSegment = Segments[(m_Index = Segments.Count - 1)]; //Set the cursor m_Cursor = WorkingSegment.m_Length; //Set the position m_Position = m_Count; //If the given offset refers to any other position seek from the end if (offset < 0) { goto case System.IO.SeekOrigin.Current; } //position is now equal to given offset >= 0 from the end. return(m_Position); } default: return(m_Position); } //x86 may benefit from break and return //return m_Position }
public void InsertPersistedMemory(int index, MemorySegment toInsert) { InsertPersistedMemory(ref index, toInsert); }