xref: /aosp_15_r20/external/swiftshader/tests/regres/cov/span.go (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker//
3*03ce13f7SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker//
7*03ce13f7SAndroid Build Coastguard Worker//    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker//
9*03ce13f7SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker// limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Workerpackage cov
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Workerimport (
18*03ce13f7SAndroid Build Coastguard Worker	"fmt"
19*03ce13f7SAndroid Build Coastguard Worker	"sort"
20*03ce13f7SAndroid Build Coastguard Worker)
21*03ce13f7SAndroid Build Coastguard Worker
22*03ce13f7SAndroid Build Coastguard Worker// Location describes a single line-column position in a source file.
23*03ce13f7SAndroid Build Coastguard Workertype Location struct {
24*03ce13f7SAndroid Build Coastguard Worker	Line, Column int
25*03ce13f7SAndroid Build Coastguard Worker}
26*03ce13f7SAndroid Build Coastguard Worker
27*03ce13f7SAndroid Build Coastguard Workerfunc (l Location) String() string {
28*03ce13f7SAndroid Build Coastguard Worker	return fmt.Sprintf("%v:%v", l.Line, l.Column)
29*03ce13f7SAndroid Build Coastguard Worker}
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
32*03ce13f7SAndroid Build Coastguard Workerfunc (l Location) Compare(o Location) int {
33*03ce13f7SAndroid Build Coastguard Worker	switch {
34*03ce13f7SAndroid Build Coastguard Worker	case l.Line < o.Line:
35*03ce13f7SAndroid Build Coastguard Worker		return -1
36*03ce13f7SAndroid Build Coastguard Worker	case l.Line > o.Line:
37*03ce13f7SAndroid Build Coastguard Worker		return 1
38*03ce13f7SAndroid Build Coastguard Worker	case l.Column < o.Column:
39*03ce13f7SAndroid Build Coastguard Worker		return -1
40*03ce13f7SAndroid Build Coastguard Worker	case l.Column > o.Column:
41*03ce13f7SAndroid Build Coastguard Worker		return 1
42*03ce13f7SAndroid Build Coastguard Worker	}
43*03ce13f7SAndroid Build Coastguard Worker	return 0
44*03ce13f7SAndroid Build Coastguard Worker}
45*03ce13f7SAndroid Build Coastguard Worker
46*03ce13f7SAndroid Build Coastguard Worker// Before returns true if l comes before o.
47*03ce13f7SAndroid Build Coastguard Workerfunc (l Location) Before(o Location) bool { return l.Compare(o) == -1 }
48*03ce13f7SAndroid Build Coastguard Worker
49*03ce13f7SAndroid Build Coastguard Worker// After returns true if l comes after o.
50*03ce13f7SAndroid Build Coastguard Workerfunc (l Location) After(o Location) bool { return l.Compare(o) == 1 }
51*03ce13f7SAndroid Build Coastguard Worker
52*03ce13f7SAndroid Build Coastguard Worker// Span describes a start and end interval in a source file.
53*03ce13f7SAndroid Build Coastguard Workertype Span struct {
54*03ce13f7SAndroid Build Coastguard Worker	Start, End Location
55*03ce13f7SAndroid Build Coastguard Worker}
56*03ce13f7SAndroid Build Coastguard Worker
57*03ce13f7SAndroid Build Coastguard Workerfunc (s Span) String() string {
58*03ce13f7SAndroid Build Coastguard Worker	return fmt.Sprintf("%v-%v", s.Start, s.End)
59*03ce13f7SAndroid Build Coastguard Worker}
60*03ce13f7SAndroid Build Coastguard Worker
61*03ce13f7SAndroid Build Coastguard Worker// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
62*03ce13f7SAndroid Build Coastguard Workerfunc (s Span) Compare(o Span) int {
63*03ce13f7SAndroid Build Coastguard Worker	switch {
64*03ce13f7SAndroid Build Coastguard Worker	case s.Start.Before(o.Start):
65*03ce13f7SAndroid Build Coastguard Worker		return -1
66*03ce13f7SAndroid Build Coastguard Worker	case o.Start.Before(s.Start):
67*03ce13f7SAndroid Build Coastguard Worker		return 1
68*03ce13f7SAndroid Build Coastguard Worker	case s.End.Before(o.End):
69*03ce13f7SAndroid Build Coastguard Worker		return -1
70*03ce13f7SAndroid Build Coastguard Worker	case o.End.Before(s.End):
71*03ce13f7SAndroid Build Coastguard Worker		return 1
72*03ce13f7SAndroid Build Coastguard Worker	}
73*03ce13f7SAndroid Build Coastguard Worker	return 0
74*03ce13f7SAndroid Build Coastguard Worker}
75*03ce13f7SAndroid Build Coastguard Worker
76*03ce13f7SAndroid Build Coastguard Worker// Before returns true if span s comes before o.
77*03ce13f7SAndroid Build Coastguard Workerfunc (s Span) Before(o Span) bool { return s.Compare(o) == -1 }
78*03ce13f7SAndroid Build Coastguard Worker
79*03ce13f7SAndroid Build Coastguard Worker// Inside returns true if span s fits entirely inside o.
80*03ce13f7SAndroid Build Coastguard Workerfunc (s Span) Inside(o Span) bool { return s.Start.Compare(o.Start) >= 0 && s.End.Compare(o.End) <= 0 }
81*03ce13f7SAndroid Build Coastguard Worker
82*03ce13f7SAndroid Build Coastguard Worker// SpanList is a sorted list of spans. Use SpanList.Add() to insert new spans.
83*03ce13f7SAndroid Build Coastguard Workertype SpanList []Span
84*03ce13f7SAndroid Build Coastguard Worker
85*03ce13f7SAndroid Build Coastguard Worker// Add adds the Span to the SpanList, merging and expanding overlapping spans.
86*03ce13f7SAndroid Build Coastguard Workerfunc (l *SpanList) Add(s Span) {
87*03ce13f7SAndroid Build Coastguard Worker	//          [===]
88*03ce13f7SAndroid Build Coastguard Worker	//  [0] [1]                | idxStart: 2 |  idxEnd: 2
89*03ce13f7SAndroid Build Coastguard Worker	//                [0] [1]  | idxStart: 0 |  idxEnd: 0
90*03ce13f7SAndroid Build Coastguard Worker	// [ 0 ] [ 1 ] [ 2 ] [ 3 ] | idxStart: 1 |  idxEnd: 2
91*03ce13f7SAndroid Build Coastguard Worker	// [0]  [1]  [2]  [3]  [4] | idxStart: 2 |  idxEnd: 2
92*03ce13f7SAndroid Build Coastguard Worker	idxStart := sort.Search(len(*l), func(i int) bool { return (*l)[i].End.Compare(s.Start) >= 0 })
93*03ce13f7SAndroid Build Coastguard Worker
94*03ce13f7SAndroid Build Coastguard Worker	if idxStart < len(*l) && s.Inside((*l)[idxStart]) {
95*03ce13f7SAndroid Build Coastguard Worker		return // No change.
96*03ce13f7SAndroid Build Coastguard Worker	}
97*03ce13f7SAndroid Build Coastguard Worker
98*03ce13f7SAndroid Build Coastguard Worker	idxEnd := sort.Search(len(*l), func(i int) bool { return (*l)[i].Start.Compare(s.End) > 0 })
99*03ce13f7SAndroid Build Coastguard Worker
100*03ce13f7SAndroid Build Coastguard Worker	if idxStart < idxEnd {
101*03ce13f7SAndroid Build Coastguard Worker		if first := (*l)[idxStart]; first.Start.Before(s.Start) {
102*03ce13f7SAndroid Build Coastguard Worker			s.Start = first.Start
103*03ce13f7SAndroid Build Coastguard Worker		}
104*03ce13f7SAndroid Build Coastguard Worker		if last := (*l)[idxEnd-1]; last.End.After(s.End) {
105*03ce13f7SAndroid Build Coastguard Worker			s.End = last.End
106*03ce13f7SAndroid Build Coastguard Worker		}
107*03ce13f7SAndroid Build Coastguard Worker	}
108*03ce13f7SAndroid Build Coastguard Worker
109*03ce13f7SAndroid Build Coastguard Worker	merged := append(SpanList{}, (*l)[:idxStart]...)
110*03ce13f7SAndroid Build Coastguard Worker	merged = append(merged, s)
111*03ce13f7SAndroid Build Coastguard Worker	merged = append(merged, (*l)[idxEnd:]...)
112*03ce13f7SAndroid Build Coastguard Worker	*l = merged
113*03ce13f7SAndroid Build Coastguard Worker}
114*03ce13f7SAndroid Build Coastguard Worker
115*03ce13f7SAndroid Build Coastguard Worker// Remove cuts out the Span from the SpanList, removing and trimming overlapping
116*03ce13f7SAndroid Build Coastguard Worker// spans.
117*03ce13f7SAndroid Build Coastguard Workerfunc (l *SpanList) Remove(s Span) {
118*03ce13f7SAndroid Build Coastguard Worker	if s.Start == s.End {
119*03ce13f7SAndroid Build Coastguard Worker		return // zero length == no split.
120*03ce13f7SAndroid Build Coastguard Worker	}
121*03ce13f7SAndroid Build Coastguard Worker
122*03ce13f7SAndroid Build Coastguard Worker	//          [===]
123*03ce13f7SAndroid Build Coastguard Worker	//  [0] [1]                | idxStart: 2 |  idxEnd: 2
124*03ce13f7SAndroid Build Coastguard Worker	//                [0] [1]  | idxStart: 0 |  idxEnd: 0
125*03ce13f7SAndroid Build Coastguard Worker	// [ 0 ] [ 1 ] [ 2 ] [ 3 ] | idxStart: 1 |  idxEnd: 2
126*03ce13f7SAndroid Build Coastguard Worker	// [0]  [1]  [2]  [3]  [4] | idxStart: 2 |  idxEnd: 2
127*03ce13f7SAndroid Build Coastguard Worker	idxStart := sort.Search(len(*l), func(i int) bool { return (*l)[i].End.Compare(s.Start) > 0 })
128*03ce13f7SAndroid Build Coastguard Worker	idxEnd := sort.Search(len(*l), func(i int) bool { return (*l)[i].Start.Compare(s.End) >= 0 })
129*03ce13f7SAndroid Build Coastguard Worker
130*03ce13f7SAndroid Build Coastguard Worker	merged := append(SpanList{}, (*l)[:idxStart]...)
131*03ce13f7SAndroid Build Coastguard Worker
132*03ce13f7SAndroid Build Coastguard Worker	if idxStart < idxEnd {
133*03ce13f7SAndroid Build Coastguard Worker		first, last := (*l)[idxStart], (*l)[idxEnd-1]
134*03ce13f7SAndroid Build Coastguard Worker		if first.Start.Compare(s.Start) < 0 {
135*03ce13f7SAndroid Build Coastguard Worker			merged = append(merged, Span{first.Start, s.Start})
136*03ce13f7SAndroid Build Coastguard Worker		}
137*03ce13f7SAndroid Build Coastguard Worker		if last.End.Compare(s.End) > 0 {
138*03ce13f7SAndroid Build Coastguard Worker			merged = append(merged, Span{s.End, last.End})
139*03ce13f7SAndroid Build Coastguard Worker		}
140*03ce13f7SAndroid Build Coastguard Worker	}
141*03ce13f7SAndroid Build Coastguard Worker
142*03ce13f7SAndroid Build Coastguard Worker	merged = append(merged, (*l)[idxEnd:]...)
143*03ce13f7SAndroid Build Coastguard Worker	*l = merged
144*03ce13f7SAndroid Build Coastguard Worker}
145*03ce13f7SAndroid Build Coastguard Worker
146*03ce13f7SAndroid Build Coastguard Worker// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
147*03ce13f7SAndroid Build Coastguard Workerfunc (l SpanList) Compare(o SpanList) int {
148*03ce13f7SAndroid Build Coastguard Worker	switch {
149*03ce13f7SAndroid Build Coastguard Worker	case len(l) < len(o):
150*03ce13f7SAndroid Build Coastguard Worker		return -1
151*03ce13f7SAndroid Build Coastguard Worker	case len(l) > len(o):
152*03ce13f7SAndroid Build Coastguard Worker		return 1
153*03ce13f7SAndroid Build Coastguard Worker	}
154*03ce13f7SAndroid Build Coastguard Worker	for i, a := range l {
155*03ce13f7SAndroid Build Coastguard Worker		switch a.Compare(o[i]) {
156*03ce13f7SAndroid Build Coastguard Worker		case -1:
157*03ce13f7SAndroid Build Coastguard Worker			return -1
158*03ce13f7SAndroid Build Coastguard Worker		case 1:
159*03ce13f7SAndroid Build Coastguard Worker			return 1
160*03ce13f7SAndroid Build Coastguard Worker		}
161*03ce13f7SAndroid Build Coastguard Worker	}
162*03ce13f7SAndroid Build Coastguard Worker	return 0
163*03ce13f7SAndroid Build Coastguard Worker}
164*03ce13f7SAndroid Build Coastguard Worker
165*03ce13f7SAndroid Build Coastguard Worker// NumLines returns the total number of lines covered by all spans in the list.
166*03ce13f7SAndroid Build Coastguard Workerfunc (l SpanList) NumLines() int {
167*03ce13f7SAndroid Build Coastguard Worker	seen := map[int]struct{}{}
168*03ce13f7SAndroid Build Coastguard Worker	for _, span := range l {
169*03ce13f7SAndroid Build Coastguard Worker		for s := span.Start.Line; s <= span.End.Line; s++ {
170*03ce13f7SAndroid Build Coastguard Worker			if _, ok := seen[s]; !ok {
171*03ce13f7SAndroid Build Coastguard Worker				seen[s] = struct{}{}
172*03ce13f7SAndroid Build Coastguard Worker			}
173*03ce13f7SAndroid Build Coastguard Worker		}
174*03ce13f7SAndroid Build Coastguard Worker	}
175*03ce13f7SAndroid Build Coastguard Worker	return len(seen)
176*03ce13f7SAndroid Build Coastguard Worker}
177