Example #1
0
        ///
        ///<summary>Insert (or Append) a segment collection at a given offset</summary>
        ///
        public void Insert(SegmentCollection sc, long offset)
        {
            long mapping;

            Util.List <Segment> .Node node;

            Segment s = FindSegment(offset, out mapping, out node);

            // offset not found, check if we have to append
            if (s == null)
            {
                if ((node == null && offset == 0) || (node != null && offset == mapping + node.data.Size))
                {
                    Util.List <Segment> lst = sc.List;
                    int N = lst.Count;
                    Util.List <Segment> .Node n = lst.First;
                    for (int i = 0; i < N; i++)
                    {
                        Append(n.data);
                        n = n.next;
                    }
                }
                return;
            }

            if (mapping == offset)       // start of segment?
            // insert data from the current node backwards
            {
                Util.List <Segment> lst = sc.List;
                int N = lst.Count;
                Util.List <Segment> .Node n = lst.Last;
                for (int i = 0; i < N; i++)
                {
                    node = InsertBefore(node, n.data);
                    n    = n.prev;
                }
                // update cache
                SetCache(node, mapping);
            }
            else       //middle of segment
            {
                Segment s1 = s.SplitAt(offset - mapping);
                list.InsertAfter(node, s1);

                Util.List <Segment> lst = sc.List;
                int N = lst.Count;
                Util.List <Segment> .Node n = lst.First;
                for (int i = 0; i < N; i++)
                {
                    node = InsertAfter(node, n.data);
                    n    = n.next;
                }
            }
        }
Example #2
0
        public SegmentCollection GetRange(long pos1, long pos2)
        {
            long mapping1, mapping2;

            Util.List <Segment> .Node node1;
            Util.List <Segment> .Node node2;

            // Find the segments of the end points.
            // Search for the ending point first so that we won't
            // have to invalidate the cache later
            Segment s2 = FindSegment(pos2, out mapping2, out node2);
            Segment s1 = FindSegment(pos1, out mapping1, out node1);

            if (s1 == null || s2 == null)
            {
                return(null);
            }

            if (ReferenceEquals(node1, node2))
            {
                SegmentCollection scTemp = new SegmentCollection();
                Segment           seg    = new Segment(s1.Buffer, pos1 - mapping1 + s1.Start, pos2 - mapping1 + s1.Start);
                scTemp.Append(seg);
                return(scTemp);
            }

            // try to split the ending segment
            Segment sl = new Segment(s2.Buffer, s2.Start, pos2 - mapping2 + s2.Start);

            // try to split the starting segment
            Segment sf = new Segment(s1.Buffer, pos1 - mapping1 + s1.Start, s1.End);


            SegmentCollection sc = new SegmentCollection();

            // append the first segment
            sc.Append(sf);

            Util.List <Segment> .Node n = node1.next;

            // append to new and remove from old
            // all segments up to node2
            while (ReferenceEquals(n, node2) == false)
            {
                sc.Append(new Segment(n.data.Buffer, n.data.Start, n.data.End));
                n = n.next;
            }

            sc.Append(sl);

            return(sc);
        }
Example #3
0
 ///<summary>Inserts a segment before a node
 ///and merges them if possible</summary>
 private Util.List <Segment> .Node InsertBefore(Util.List <Segment> .Node n, Segment s)
 {
     if (n != null && n.data != null)
     {
         Segment ls = n.data;
         if ((s.Buffer == ls.Buffer) && (s.End + 1 == ls.Start))
         {
             ls.Start = s.Start;
             return(n);
         }
     }
     return(list.InsertBefore(n, s));
 }
Example #4
0
 ///<summary>Append a segment to the collection</summary>
 public void Append(Segment s)
 {
     Util.List <Segment> .Node n = list.Last;
     if (n != null && n.data != null)
     {
         Segment ls = n.data;
         if ((s.Buffer == ls.Buffer) && (s.Start == ls.End + 1))
         {
             ls.End = s.End;
             return;
         }
     }
     list.Append(s);
 }
Example #5
0
        protected override void DoOperation()
        {
            stageReached = SaveAsStage.BeforeCreate;

            if (!CheckFreeSpace(Path.GetDirectoryName(savePath), 0))
            {
                string msg = string.Format(Catalog.GetString("There is not enough free space on the device to save file '{0}'."), savePath);
                throw new IOException(msg);
            }

            // try to open in append mode first, so that a sharing violation
            // doesn't end up with the file truncated (as opposed
            // to using FileMode.Create)
            fs = new FileStream(savePath, FileMode.Append, FileAccess.Write);
            fs.Close();

            // do the actual create
            fs = new FileStream(savePath, FileMode.Create, FileAccess.Write);

            stageReached = SaveAsStage.BeforeWrite;

            const int blockSize = 0xffff;

            byte[] baTemp = new byte[blockSize];

            // for every node
            Util.List <Segment> .Node node = byteBuffer.segCol.List.First;

            while (node != null && !cancelled)
            {
                // Save the data in the node
                // in blocks of blockSize each
                Segment s       = node.data;
                long    len     = s.Size;
                long    nBlocks = len / blockSize;
                int     last    = (int)(len % blockSize);  // bytes in last block
                long    i;

                // for every full block
                for (i = 0; i < nBlocks; i++)
                {
                    s.Buffer.Read(baTemp, 0, s.Start + i * blockSize, blockSize);
                    fs.Write(baTemp, 0, blockSize);
                    bytesSaved = (i + 1) * blockSize;

                    if (cancelled)
                    {
                        break;
                    }
                }

                // if last non-full block is not empty
                if (last != 0 && !cancelled)
                {
                    s.Buffer.Read(baTemp, 0, s.Start + i * blockSize, last);
                    fs.Write(baTemp, 0, last);
                }

                node = node.next;
            }

            fs.Close();
            fs = null;
        }
Example #6
0
        protected override void DoOperation()
        {
            stageReached = SaveInPlaceStage.BeforeClose;

            // hold a reference to the bytebuffer's segment collection
            // because it is lost when the file is closed
            SegmentCollection segCol = byteBuffer.segCol;

            // close file
            if (!cancelled)
            {
                // close the file, make sure that File Operations
                // are temporarily allowed
                lock (byteBuffer.LockObj) {
                    // CloseFile invalidates the file buffer,
                    // so make sure undo/redo data stays valid
                    byteBuffer.MakePrivateCopyOfUndoRedo();
                    byteBuffer.FileOperationsAllowed = true;
                    byteBuffer.CloseFile();
                    byteBuffer.FileOperationsAllowed = false;
                }
            }

            // Open the file for editing
            fs = new FileStream(savePath, FileMode.Open, FileAccess.Write);

            stageReached = SaveInPlaceStage.BeforeWrite;

            const int blockSize = 0xffff;

            byte[] baTemp = new byte[blockSize];

            //
            // Just save the changed parts...
            //

            Util.List <Segment> .Node node = segCol.List.First;

            // hold the mapping of the start of the current segment
            // (at which offset in the file it is mapped)
            long mapping = 0;

            while (node != null && !cancelled)
            {
                // Save the data in the node
                // in blocks of blockSize each
                Segment s = node.data;

                // if the segment belongs to the original buffer, skip it
                if (s.Buffer.GetType() == typeof(FileBuffer))
                {
                    mapping += s.Size;
                    node     = node.next;
                    continue;
                }

                long len     = s.Size;
                long nBlocks = len / blockSize;
                int  last    = (int)(len % blockSize);     // bytes in last block
                long i;

                // move the file cursor to the current mapping
                fs.Seek(mapping, SeekOrigin.Begin);

                bytesSaved = mapping;

                // for every full block
                for (i = 0; i < nBlocks; i++)
                {
                    s.Buffer.Read(baTemp, 0, s.Start + i * blockSize, blockSize);
                    fs.Write(baTemp, 0, blockSize);
                    bytesSaved = (i + 1) * blockSize;

                    if (cancelled)
                    {
                        break;
                    }
                }

                // if last non-full block is not empty
                if (last != 0 && !cancelled)
                {
                    s.Buffer.Read(baTemp, 0, s.Start + i * blockSize, last);
                    fs.Write(baTemp, 0, last);
                }

                mapping += s.Size;
                node     = node.next;
            }

            fs.Close();
            fs = null;
        }
Example #7
0
 private void SetCache(Util.List <Segment> .Node n, long map)
 {
     cachedNode    = n;
     cachedMapping = map;
 }
Example #8
0
 private void InvalidateCache()
 {
     cachedNode    = null;
     cachedMapping = 0;
 }
Example #9
0
 public SegmentCollection()
 {
     list = new Util.List <Segment>();
 }
Example #10
0
        ///<summary>Delete a range from the collection</summary>
        public SegmentCollection DeleteRange(long pos1, long pos2)
        {
            long mapping1, mapping2;

            Util.List <Segment> .Node node1;
            Util.List <Segment> .Node node2;

            // Find the segments of the end points.
            // Search for the ending point first so that we won't
            // have to invalidate the cache later
            Segment s2 = FindSegment(pos2, out mapping2, out node2);
            Segment s1 = FindSegment(pos1, out mapping1, out node1);

            if (s1 == null || s2 == null)
            {
                return(null);
            }

            // ending segment == starting segment
            // needs special handling
            #region Special Handling if node1==node2
            if (ReferenceEquals(node1, node2))
            {
                bool remove_flag = false;

                // try to split segment at pos1
                Segment s_f = s1.SplitAt(pos1 - mapping1);
                // if we can't, this means that pos1 is
                // at the beginning of the segment
                if (s_f == null)
                {
                    s_f         = s1;
                    remove_flag = true;
                }

                // try to split s_f at pos2+1
                // s_l is the ending part of s1 that we
                // should keep
                Segment s_l = s_f.SplitAt(pos2 - pos1 + 1);

                // if we can't split, this means that pos2 is
                // at the end of the segment,
                // otherwise add s_l after node1 (which contains s1)
                if (s_l != null)
                {
                    list.InsertAfter(node1, s_l);
                }

                // if we should remove s1
                if (remove_flag)
                {
                    // try to set the cache
                    if (node1.next != null)
                    {
                        SetCache(node1.next, mapping1);
                    }
                    else if (node1.prev != null)
                    {
                        Segment s = node1.prev.data;
                        SetCache(node1.prev, mapping1 - s.Size);
                    }
                    else
                    {
                        InvalidateCache();
                    }

                    list.Remove(node1);
                }
                //else leave the cache set as is (node1, mapping1)

                SegmentCollection s_c = new SegmentCollection();
                s_c.Append(s_f);

                return(s_c);
            }
            #endregion
            // try to split the ending segment
            Segment sl = s2.SplitAt(pos2 - mapping2 + 1);

            // if we can't, this means that pos2 is the
            // at the end of the ending segment
            if (sl == null)
            {
                sl = s2;                // set the whole segment for removal
            }
            else
            {
                list.InsertAfter(node2, sl);
            }


            Util.List <Segment> .Node n = node1.next;

            // try to split the starting segment
            Segment sf = s1.SplitAt(pos1 - mapping1);

            // if we can't, this means that pos1 is
            // at the beginning of the starting segment
            if (sf == null)
            {
                sf = s1;
                // try to set the cache
                if (node1.prev != null)
                {
                    Segment s = node1.prev.data;
                    SetCache(node1.prev, mapping1 - s.Size);
                }
                else
                {
                    InvalidateCache();
                }

                list.Remove(node1);         // remove the whole segment
            }

            SegmentCollection sc = new SegmentCollection();

            // append the first segment
            sc.Append(sf);

            // append to new and remove from old
            // all segments up to node2
            while (ReferenceEquals(n, node2) == false)
            {
                sc.Append(n.data);
                Util.List <Segment> .Node p = n;
                n = n.next;
                // Remove() must be placed after n.next
                // because it sets n.next=null
                list.Remove(p);
            }
            // append and remove node2
            list.Remove(n);
            sc.Append(n.data);

            return(sc);
        }
Example #11
0
        ///
        ///<summary>Find the segment that the given offset is mapped into</summary>
        ///
        public Segment FindSegment(long offset, out long OutMapping, out Util.List <Segment> .Node OutNode)
        {
            OutMapping = 0;
            OutNode    = null;

            // if this is the first search
            // set up things
            if (cachedNode == null)
            {
                if (list.First == null)
                {
                    return(null);
                }
                SetCache(list.First, 0);
            }

            Segment s          = cachedNode.data;
            long    curMapping = cachedMapping;

            Util.List <Segment> .Node curNode = cachedNode;

            // is the cached node the one we want?
            if (s.Contains(offset, curMapping) == true)
            {
                OutMapping = curMapping;
                OutNode    = curNode;
                return(s);
            }

            // search towards the beginning
            if (offset < curMapping)
            {
                while (curNode.prev != null)
                {
                    curNode     = curNode.prev;
                    s           = curNode.data;
                    curMapping -= s.Size;
                    if (s.Contains(offset, curMapping) == true)
                    {
                        SetCache(curNode, curMapping);
                        OutMapping = curMapping;
                        OutNode    = curNode;
                        return(s);
                    }
                }
            }
            else       // search towards the end
            {
                while (curNode.next != null)
                {
                    curMapping += s.Size;
                    curNode     = curNode.next;
                    s           = curNode.data;
                    if (s.Contains(offset, curMapping) == true)
                    {
                        SetCache(curNode, curMapping);
                        OutMapping = curMapping;
                        OutNode    = curNode;
                        return(s);
                    }
                }
            }

            // offset not found but return last accessed node info
            OutMapping = curMapping;
            OutNode    = curNode;
            return(null);
        }