Esempio n. 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;
                }
            }
        }
Esempio n. 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);
        }
Esempio n. 3
0
        public override void Do()
        {
            if (seg == null)
            {
                return;
            }
            SegmentCollection tmp = new SegmentCollection();

            // use copy of segment seg to protect it from alterations
            tmp.Append(new Segment(seg.Buffer, seg.Start, seg.End));
            byteBuf.segCol.Insert(tmp, pos);
            byteBuf.size += seg.Size;
        }
Esempio n. 4
0
 ///<summary>
 /// Close the file associated with the ByteBuffer
 ///</summary>
 public void CloseFile()
 {
     lock (LockObj) {
         // close the file buffer and dispose the file watcher
         if (fileBuf != null && fileOperationsAllowed)
         {
             fileBuf.Close();
             fsw.Dispose();
             fsw    = null;
             segCol = null;
             // buffer is in an unreadable state...
             this.ReadAllowed = false;
         }
     }
 }
Esempio n. 5
0
        ///<summary>
        /// Sets the file buffer and resets the segment collection
        ///</summary>
        private void LoadWithFile(string filename)
        {
            if (fileBuf == null)
            {
                fileBuf = new FileBuffer(filename, 0xffff);         // 64KB buffer
            }
            else
            {
                fileBuf.Load(filename);
            }

            Segment s = new Segment(fileBuf, 0, fileBuf.Size - 1);

            segCol = new SegmentCollection();
            segCol.Append(s);
            size = fileBuf.Size;

            SetupFSW();
        }
Esempio n. 6
0
        public ByteBuffer()
        {
            segCol         = new SegmentCollection();
            undoDeque      = new Deque <ByteBufferAction>();
            redoDeque      = new Deque <ByteBufferAction>();
            size           = 0;
            SaveCheckpoint = null;

            // name the buffer automatically
            autoFilename = Catalog.GetString("Untitled") + " " + ByteBuffer.autoNum;
            ByteBuffer.autoNum++;

            // set default permissions
            readAllowed           = true;
            fileOperationsAllowed = true;
            modifyAllowed         = true;

            saveFinishedEvent = new AutoResetEvent(false);
            useGLibIdle       = false;
            emitEvents        = true;

            maxUndoActions = -1;     // unlimited undo
            tempDir        = Path.GetTempPath();
        }
Esempio n. 7
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;
        }
Esempio n. 8
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);
        }
Esempio n. 9
0
 public override void Do()
 {
     del           = byteBuf.segCol.DeleteRange(pos1, pos2);
     byteBuf.size -= pos2 - pos1 + 1;
 }