diff options
author | n-peugnet <n.peugnet@free.fr> | 2021-09-21 16:29:44 +0200 |
---|---|---|
committer | n-peugnet <n.peugnet@free.fr> | 2021-09-21 16:29:44 +0200 |
commit | 2887d66a939b3b8d7e84d9c71c0a86d5132b5e54 (patch) | |
tree | 763fcf337d7729e894f2f331dca7cbad52298b50 /slice/slice.go | |
parent | e3ba94744ed4f22e4a05f0757b624936602b70db (diff) | |
download | dna-backup-2887d66a939b3b8d7e84d9c71c0a86d5132b5e54.tar.gz dna-backup-2887d66a939b3b8d7e84d9c71c0a86d5132b5e54.zip |
change recipe into a generic slice patch/diff package
Diffstat (limited to 'slice/slice.go')
-rw-r--r-- | slice/slice.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/slice/slice.go b/slice/slice.go new file mode 100644 index 0000000..15be5dd --- /dev/null +++ b/slice/slice.go @@ -0,0 +1,74 @@ +package slice + +import "reflect" + +type Slice []interface{} + +type SliceDel int + +type SliceIns struct { + Idx int + Value []interface{} +} + +type SlicePatch struct { + Del []SliceDel + Ins []SliceIns +} + +func PatchSlice(source Slice, patch SlicePatch) (target Slice) { + // apply Del part from patch to source into temp + size := len(source) - len(patch.Del) + temp := make(Slice, size) + fill := 0 + prev := 0 + for _, del := range patch.Del { + di := int(del) + copy(temp[fill:], source[prev:di]) + fill += di - prev + prev = di + 1 + } + copy(temp[fill:], source[prev:]) + // apply Ins part from patch to temp into target + for _, ins := range patch.Ins { + size += len(ins.Value) + } + target = make(Slice, size) + fill = 0 + prev = 0 + tpos := 0 + for _, ins := range patch.Ins { + offset := ins.Idx - prev + copy(target[fill:], temp[tpos:tpos+offset]) + fill += offset + tpos += offset + copy(target[fill:], ins.Value) + fill += len(ins.Value) + prev = ins.Idx + len(ins.Value) + } + return +} + +func DiffSlice(source Slice, target Slice) (patch SlicePatch) { + var si, ti int + var found bool + for ; si < len(source); si++ { + for i := ti; i < len(target); i++ { + found = reflect.DeepEqual(target[i], source[si]) + if found { + if i != ti { + patch.Ins = append(patch.Ins, SliceIns{ti, target[ti:i]}) + } + ti = i + 1 + break + } + } + if !found { + patch.Del = append(patch.Del, SliceDel(si)) + } + } + if ti < len(target) { + patch.Ins = append(patch.Ins, SliceIns{ti, target[ti:]}) + } + return +} |