golang.org/x/tools@v0.21.0/internal/diff/lcs/sequence.go (about)

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package lcs
     6  
     7  // This file defines the abstract sequence over which the LCS algorithm operates.
     8  
     9  // sequences abstracts a pair of sequences, A and B.
    10  type sequences interface {
    11  	lengths() (int, int)                    // len(A), len(B)
    12  	commonPrefixLen(ai, aj, bi, bj int) int // len(commonPrefix(A[ai:aj], B[bi:bj]))
    13  	commonSuffixLen(ai, aj, bi, bj int) int // len(commonSuffix(A[ai:aj], B[bi:bj]))
    14  }
    15  
    16  type stringSeqs struct{ a, b string }
    17  
    18  func (s stringSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
    19  func (s stringSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
    20  	return commonPrefixLenString(s.a[ai:aj], s.b[bi:bj])
    21  }
    22  func (s stringSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
    23  	return commonSuffixLenString(s.a[ai:aj], s.b[bi:bj])
    24  }
    25  
    26  // The explicit capacity in s[i:j:j] leads to more efficient code.
    27  
    28  type bytesSeqs struct{ a, b []byte }
    29  
    30  func (s bytesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
    31  func (s bytesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
    32  	return commonPrefixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
    33  }
    34  func (s bytesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
    35  	return commonSuffixLenBytes(s.a[ai:aj:aj], s.b[bi:bj:bj])
    36  }
    37  
    38  type runesSeqs struct{ a, b []rune }
    39  
    40  func (s runesSeqs) lengths() (int, int) { return len(s.a), len(s.b) }
    41  func (s runesSeqs) commonPrefixLen(ai, aj, bi, bj int) int {
    42  	return commonPrefixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
    43  }
    44  func (s runesSeqs) commonSuffixLen(ai, aj, bi, bj int) int {
    45  	return commonSuffixLenRunes(s.a[ai:aj:aj], s.b[bi:bj:bj])
    46  }
    47  
    48  // TODO(adonovan): optimize these functions using ideas from:
    49  // - https://go.dev/cl/408116 common.go
    50  // - https://go.dev/cl/421435 xor_generic.go
    51  
    52  // TODO(adonovan): factor using generics when available,
    53  // but measure performance impact.
    54  
    55  // commonPrefixLen* returns the length of the common prefix of a[ai:aj] and b[bi:bj].
    56  func commonPrefixLenBytes(a, b []byte) int {
    57  	n := min(len(a), len(b))
    58  	i := 0
    59  	for i < n && a[i] == b[i] {
    60  		i++
    61  	}
    62  	return i
    63  }
    64  func commonPrefixLenRunes(a, b []rune) int {
    65  	n := min(len(a), len(b))
    66  	i := 0
    67  	for i < n && a[i] == b[i] {
    68  		i++
    69  	}
    70  	return i
    71  }
    72  func commonPrefixLenString(a, b string) int {
    73  	n := min(len(a), len(b))
    74  	i := 0
    75  	for i < n && a[i] == b[i] {
    76  		i++
    77  	}
    78  	return i
    79  }
    80  
    81  // commonSuffixLen* returns the length of the common suffix of a[ai:aj] and b[bi:bj].
    82  func commonSuffixLenBytes(a, b []byte) int {
    83  	n := min(len(a), len(b))
    84  	i := 0
    85  	for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
    86  		i++
    87  	}
    88  	return i
    89  }
    90  func commonSuffixLenRunes(a, b []rune) int {
    91  	n := min(len(a), len(b))
    92  	i := 0
    93  	for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
    94  		i++
    95  	}
    96  	return i
    97  }
    98  func commonSuffixLenString(a, b string) int {
    99  	n := min(len(a), len(b))
   100  	i := 0
   101  	for i < n && a[len(a)-1-i] == b[len(b)-1-i] {
   102  		i++
   103  	}
   104  	return i
   105  }
   106  
   107  func min(x, y int) int {
   108  	if x < y {
   109  		return x
   110  	} else {
   111  		return y
   112  	}
   113  }