...
1
2
3
4
5
6
7
8 package main
9
10 import (
11 "fmt"
12 "sort"
13 )
14
15
16 type Buffer struct {
17 old []byte
18 q edits
19 }
20
21
22 type edit struct {
23 start int
24 end int
25 new string
26 }
27
28
29 type edits []edit
30
31 func (x edits) Len() int { return len(x) }
32 func (x edits) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
33 func (x edits) Less(i, j int) bool {
34 if x[i].start != x[j].start {
35 return x[i].start < x[j].start
36 }
37 return x[i].end < x[j].end
38 }
39
40
41
42
43 func NewBuffer(data []byte) *Buffer {
44 return &Buffer{old: data}
45 }
46
47 func (b *Buffer) Insert(pos int, new string) {
48 if pos < 0 || pos > len(b.old) {
49 panic("invalid edit position")
50 }
51 b.q = append(b.q, edit{pos, pos, new})
52 }
53
54 func (b *Buffer) Delete(start, end int) {
55 if end < start || start < 0 || end > len(b.old) {
56 panic("invalid edit position")
57 }
58 b.q = append(b.q, edit{start, end, ""})
59 }
60
61 func (b *Buffer) Replace(start, end int, new string) {
62 if end < start || start < 0 || end > len(b.old) {
63 panic("invalid edit position")
64 }
65 b.q = append(b.q, edit{start, end, new})
66 }
67
68
69
70 func (b *Buffer) Bytes() []byte {
71
72
73
74 sort.Stable(b.q)
75
76 var new []byte
77 offset := 0
78 for i, e := range b.q {
79 if e.start < offset {
80 e0 := b.q[i-1]
81 panic(fmt.Sprintf("overlapping edits: [%d,%d)->%q, [%d,%d)->%q", e0.start, e0.end, e0.new, e.start, e.end, e.new))
82 }
83 new = append(new, b.old[offset:e.start]...)
84 offset = e.end
85 new = append(new, e.new...)
86 }
87 new = append(new, b.old[offset:]...)
88 return new
89 }
90
91
92
93 func (b *Buffer) String() string {
94 return string(b.Bytes())
95 }
96
View as plain text