Иван обнови решението на 06.11.2018 23:49 (преди 9 месеца)
+package main
+
+type Editor interface {
+ // String returns complete representation of what a file looks
+ // like after all manipulations.
+ String() string
+
+ // Insert text starting from given position.
+ Insert(position uint, text string) Editor
+
+ // Delete length items from offset.
+ Delete(offset, length uint) Editor
+}
+
+type CustomEditor struct {
+ Origin []byte
+ Add []byte
+ CurrOffsetAdd uint
+ Table []Piece
+ CurrLengthFile uint
+}
+
+type Piece struct {
+ Origin bool
+ Offset uint
+ Length uint
+}
+
+func (f CustomEditor) String() (result string) {
+ for _, piece := range f.Table {
+ if piece.Origin == true {
+ result += string(f.Origin[piece.Offset:piece.Length])
+ } else {
+ result += string(f.Add[piece.Offset : piece.Offset+piece.Length])
+ }
+ }
+
+ return
+}
+
+func NewEditor(s string) (e Editor) {
+ origin := []byte(s)
+ add := make([]byte, 0)
+ table := make([]Piece, 0)
+ table = append(table, Piece{Origin: true, Offset: 0, Length: uint(len(s))})
+ e = &CustomEditor{Origin: origin, CurrOffsetAdd: 0, Add: add, Table: table, CurrLengthFile: uint(len(s))}
+
+ return
+}
+
+func (f CustomEditor) Delete(offset uint, length uint) Editor {
+ if offset >= f.CurrLengthFile {
+ //do nothing
+ } else if offset+length >= f.CurrLengthFile {
+ if offset == 0 {
+ f.Table = f.Table[:0]
+ } else {
+ var currLength uint
+ var idxDelete int
+ var lastLength uint
+ for i, piece := range f.Table {
+ currLength += piece.Length
+ if offset < currLength {
+ idxDelete = i
+ lastLength = piece.Length
+ break
+ }
+
+ }
+
+ f.Table = f.Table[0 : idxDelete+1]
+ del := offset - currLength + lastLength
+ f.Table[idxDelete].Length = del
+ }
+ } else {
+ var currLength uint
+ var idxFirstDelete int
+ var idxSecondDelete int
+ var firstDelete uint
+ var secondDelete uint
+ var gone bool
+ var isSameBuf bool
+
+ var secondDeleteStart uint
+
+ for i, piece := range f.Table {
+ currLength += piece.Length
+ if !isSameBuf && offset < currLength && offset+length < currLength {
+ isSameBuf = true
+ idxFirstDelete = i
+ idxSecondDelete = i
+ firstDelete = offset - currLength + piece.Length
+ secondDelete = firstDelete + length
+ break
+ }
+ if !gone && offset < currLength {
+ idxFirstDelete = i
+ firstDelete = offset - currLength + piece.Length
+ gone = true
+ }
+
+ if gone && offset+length < currLength {
+ idxSecondDelete = i
+ secondDeleteStart = offset + length - currLength + piece.Length
+ secondDelete = currLength - length - offset
+ break
+ }
+
+ }
+
+ if isSameBuf {
+ cLength := f.Table[idxFirstDelete].Length
+ f.Table[idxFirstDelete].Length = firstDelete
+ newPieceInAdd := Piece{Origin: f.Table[idxFirstDelete].Origin, Offset: secondDelete, Length: cLength - secondDelete}
+ f.Table = append(f.Table, Piece{})
+
+ copy(f.Table[idxFirstDelete+1:], f.Table[idxFirstDelete:])
+
+ f.Table[idxFirstDelete+1] = newPieceInAdd
+
+ } else {
+ //handle first
+ f.Table[idxFirstDelete].Length = firstDelete
+
+ //handle second
+ f.Table[idxSecondDelete].Offset += secondDeleteStart
+ f.Table[idxSecondDelete].Length = secondDelete
+ f.Table = append(f.Table[0:idxFirstDelete+1], f.Table[idxSecondDelete:]...)
+ }
+
+ }
+
+ return f
+}
+
+func (f CustomEditor) Insert(position uint, text string) Editor {
+ //append new string to add slice
+ f.Add = append(f.Add, text...)
+ //create new piece for add,
+ //offset is calcualted by add buffer
+ newPieceInAdd := Piece{Origin: false, Offset: f.CurrOffsetAdd, Length: uint(len(text))}
+ f.CurrOffsetAdd += uint(len(text)) //+ 1
+
+ if position > f.CurrLengthFile {
+ if f.Table[len(f.Table)-1].Origin == false {
+ position = f.CurrLengthFile
+ //append to curr file
+ f.Table[len(f.Table)-1].Length += uint(len(text))
+ //f.Table = append(f.Table, newPieceInAdd)
+ } else {
+ position = f.CurrLengthFile
+ //append to curr file
+ f.Table = append(f.Table, newPieceInAdd)
+ }
+
+ } else {
+ //find before piece
+ var idx int
+ for i, piece := range f.Table {
+ if piece.Offset <= position && position <= piece.Length {
+ idx = i
+ break
+ }
+ }
+
+ f.CurrLengthFile += uint(len(text))
+
+ //modify before piece
+ oldLength := f.Table[idx].Length
+ f.Table[idx].Length = position
+
+ //create afterPiece
+ newPieceAfterAdded := Piece{Origin: f.Table[idx].Origin, Offset: f.Table[idx].Length, Length: oldLength}
+
+ //add new piece
+ //add after added piece
+
+ if len(f.Table) == 1 {
+ f.Table = append(f.Table, newPieceInAdd, newPieceAfterAdded)
+ } else {
+ f.Table = append(f.Table, Piece{}, Piece{})
+ copy(f.Table[idx+3:], f.Table[idx+1:])
+ f.Table[idx+1] = newPieceInAdd
+ f.Table[idx+2] = newPieceAfterAdded
+ }
+ }
+
+ return f
+}