mirror of
https://github.com/neilotoole/sq.git
synced 2024-12-18 21:52:28 +03:00
2f2dfd6e47
- Implement `sq diff --data`.
121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
// Copyright 2022 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package lcs
|
|
|
|
// This file defines the abstract sequence over which the LCS algorithm operates.
|
|
|
|
// sequences abstracts a pair of sequences, A and B.
|
|
type sequences interface {
|
|
lengths() (int, int) // len(A), len(B)
|
|
commonPrefixLen(ai, aj, bi, bj int) int // len(commonPrefix(A[ai:aj], B[bi:bj]))
|
|
commonSuffixLen(ai, aj, bi, bj int) int // len(commonSuffix(A[ai:aj], B[bi:bj]))
|
|
}
|
|
|
|
type stringSeqs struct{ a, b string }
|
|
|
|
func (s stringSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
|
|
func (s stringSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
|
|
return commonPrefixLenString(s.a[ai:aj], s.b[bi:bj])
|
|
}
|
|
|
|
func (s stringSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
|
|
return commonSuffixLenString(s.a[ai:aj], s.b[bi:bj])
|
|
}
|
|
|
|
// The explicit capacity in s[i:j:j] leads to more efficient code.
|
|
|
|
type bytesSeqs struct{ a, b []byte }
|
|
|
|
func (s bytesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
|
|
func (s bytesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
|
|
return commonPrefixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
|
|
}
|
|
|
|
func (s bytesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
|
|
return commonSuffixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
|
|
}
|
|
|
|
type runesSeqs struct{ a, b []rune }
|
|
|
|
func (s runesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
|
|
func (s runesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
|
|
return commonPrefixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
|
|
}
|
|
|
|
func (s runesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
|
|
return commonSuffixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
|
|
}
|
|
|
|
// TODO(adonovan): optimize these functions using ideas from:
|
|
// - https://go.dev/cl/408116 common.go
|
|
// - https://go.dev/cl/421435 xor_generic.go
|
|
|
|
// TODO(adonovan): factor using generics when available,
|
|
// but measure performance impact.
|
|
|
|
// commonPrefixLen* returns the length of the common prefix of a[ai:aj] and b[bi:bj].
|
|
func commonPrefixLenBytes(a, b []byte) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[i] == b[i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
func commonPrefixLenRunes(a, b []rune) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[i] == b[i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
func commonPrefixLenString(a, b string) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[i] == b[i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
// commonSuffixLen* returns the length of the common suffix of a[ai:aj] and b[bi:bj].
|
|
func commonSuffixLenBytes(a, b []byte) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
func commonSuffixLenRunes(a, b []rune) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
func commonSuffixLenString(a, b string) int {
|
|
n := min(len(a), len(b))
|
|
i := 0
|
|
for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
|
|
i++
|
|
}
|
|
return i
|
|
}
|
|
|
|
func min(x, y int) int {
|
|
if x < y {
|
|
return x
|
|
} else {
|
|
return y
|
|
}
|
|
}
|