Хакан обнови решението на 06.11.2018 17:56 (преди 9 месеца)
+package main
+
+import (
+ "math"
+)
+
+type Editor interface {
+ Insert(position uint, text string) Editor
+ Delete(offset, length uint) Editor
+ Undo() Editor
+ Redo() Editor
+ String() string
+}
+
+type Piece struct {
+ origin bool
+ offset int
+ length int
+}
+
+type HistoryItem struct {
+ typeOfModif uint
+ offset int
+ length int
+}
+type History struct {
+ changes []HistoryItem
+ position uint
+}
+
+type MyEditor struct {
+ originBuffer string
+ addBuffer string
+ pTable []Piece
+ changeLog History
+}
+
+func NewEditor(str string) MyEditor {
+ var chLog History
+ arrOfP := make([]Piece, 1)
+ arrOfP[0] = Piece{true, 0, len(str)}
+ var val = MyEditor{str, "", arrOfP, chLog}
+ return val
+}
+
+func (m MyEditor) String() string {
+ var res string
+ for i := 0; i < len(m.pTable); i++ {
+ if m.pTable[i].origin == true {
+ res += m.originBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
+ } else {
+ res += m.addBuffer[m.pTable[i].offset : m.pTable[i].offset+m.pTable[i].length]
+ }
+ }
+ return res
+}
+
+func (i MyEditor) Insert(position uint, text string) MyEditor {
+ addPiece := make([]Piece, 1)
+ addPiece[0] = Piece{false, len(i.addBuffer), len(text)}
+ indexSaver := len(i.addBuffer)
+ if position == 0 {
+ i.pTable = append(addPiece, i.pTable...)
+ } else if position > 0 && (int(position) < len(i.originBuffer)) { //mid insert
+ for key, val := range i.pTable {
+ if int(position) >= val.offset && int(position) <= val.offset+val.length {
+ newPieces := make([]Piece, 0)
+ newPieceTable1 := Piece{origin: true, offset: val.offset, length: int(position) - val.offset}
+ newPieceTable2 := Piece{origin: true, offset: newPieceTable1.offset + newPieceTable1.length,
+ length: val.length - newPieceTable1.length}
+ newPieces = append(newPieces, newPieceTable1, addPiece[0], newPieceTable2)
+ if len(i.pTable) == 1 {
+ i.pTable = newPieces
+ } else {
+ temp := make([]Piece, len(i.pTable[key+1:]))
+ copy(temp, i.pTable[key+1:])
+ i.pTable = append(i.pTable[:key], newPieces...)
+ i.pTable = append(i.pTable, temp...)
+ }
+ break
+ }
+ }
+ } else {
+ i.pTable = append(i.pTable, Piece{false, len(i.addBuffer), len(text)})
+ }
+ i.addBuffer += text
+ temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
+ if i.changeLog.position != 0 {
+ copy(temp, i.changeLog.changes[:i.changeLog.position])
+ i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
+ HistoryItem{1, int(indexSaver), len(text)})
+ i.changeLog.changes = append(i.changeLog.changes, temp...)
+ } else {
+ copy(temp, i.changeLog.changes[i.changeLog.position:])
+ newChLog := make([]HistoryItem, len(temp)+1)
+ newChLog[0] = HistoryItem{1, int(indexSaver), len(text)}
+ newChLog = append(newChLog[:1], temp...)
+ i.changeLog.changes = newChLog
+ }
+ i.changeLog.position++
+ return i
+}
+
+func (i MyEditor) Delete(offset, length uint) MyEditor {
+ if int(offset) > len(i.originBuffer)-1 {
+ return i
+ }
+ if int(length) > len(i.originBuffer) {
+ length = uint(len(i.originBuffer) - int(offset))
+ }
+ for key, val := range i.pTable {
+ if int(offset) >= val.offset && int(offset) <= int(val.offset+val.length) {
+ newPieces := make([]Piece, 0)
+ newPieceTable1 := Piece{origin: true, offset: val.offset,
+ length: int(math.Abs(float64((int(offset) - int(val.offset)))))}
+ newPieceTable2 := Piece{origin: true, offset: int(offset + length), length: val.length + val.offset - int(offset+length)}
+ newPieces = append(newPieces, newPieceTable1, newPieceTable2)
+ if len(i.pTable) == 1 {
+ i.pTable = newPieces
+ } else {
+ temp := make([]Piece, len(i.pTable[key+1:]))
+ copy(temp, i.pTable[key+1:])
+ i.pTable = append(i.pTable[:key], newPieces...)
+ i.pTable = append(i.pTable, temp...)
+ }
+ break
+ }
+ }
+ temp := make([]HistoryItem, len(i.changeLog.changes[i.changeLog.position:]))
+ if i.changeLog.position != 0 {
+ copy(temp, i.changeLog.changes[:i.changeLog.position])
+ i.changeLog.changes = append(i.changeLog.changes[:i.changeLog.position],
+ HistoryItem{0, int(offset), int(length)})
+ i.changeLog.changes = append(i.changeLog.changes, temp...)
+ } else {
+ copy(temp, i.changeLog.changes[i.changeLog.position:])
+ newChLog := make([]HistoryItem, len(temp)+1)
+ newChLog[0] = HistoryItem{0, int(offset), int(length)}
+ newChLog = append(newChLog[:1], temp...)
+ i.changeLog.changes = newChLog
+ }
+ i.changeLog.position++
+ return i
+}
+
+func (i MyEditor) Undo() MyEditor {
+ if i.changeLog.position == 0 {
+ return i
+ }
+ sOffset := i.changeLog.changes[i.changeLog.position-1].offset
+ sLength := i.changeLog.changes[i.changeLog.position-1].length
+ modType := i.changeLog.changes[i.changeLog.position-1].typeOfModif
+ if modType == 1 {
+ for j := 0; j < len(i.pTable); j++ {
+ if i.pTable[j].origin == false {
+ if i.pTable[j].offset == sOffset && i.pTable[j].length == sLength {
+ i.pTable[j].length = 0
+ }
+ }
+ }
+ } else {
+ for key, value := range i.pTable {
+ if value.origin == true {
+ if key+1 < len(i.pTable) {
+ if value.length+value.offset == sOffset && i.pTable[key+1].offset == sOffset+sLength {
+ i.pTable[key].length = i.pTable[key+1].offset - value.offset
+ break
+ }
+ }
+ }
+ }
+ }
+ i.changeLog.position--
+ return i
+}
+
+func (i MyEditor) Redo() MyEditor {
+ if int(i.changeLog.position) == len(i.changeLog.changes) {
+ return i
+ }
+ sOffset := i.changeLog.changes[i.changeLog.position].offset
+ sLength := i.changeLog.changes[i.changeLog.position].length
+ modType := i.changeLog.changes[i.changeLog.position].typeOfModif
+ if modType == 1 {
+ for key, value := range i.pTable {
+ if value.origin == false {
+ if value.offset == sOffset {
+ i.pTable[key].length = sLength
+ break
+ }
+ }
+ }
+ } else {
+ for key, value := range i.pTable {
+ if value.origin == true {
+ if key+1 < len(i.pTable) {
+ if value.length+value.offset == i.pTable[key+1].offset {
+ i.pTable[key].length = sOffset - value.offset
+ break
+ }
+ }
+ }
+ }
+ }
+ i.changeLog.position++
+ return i
+}