github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/samples/go/nomdex/query_range.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "sort" 12 13 "github.com/attic-labs/noms/go/types" 14 ) 15 16 type bound struct { 17 value types.Value 18 include bool 19 infinity int8 20 } 21 22 func (b bound) isLessThanOrEqual(o bound) (res bool) { 23 return b.equals(o) || b.isLessThan(o) 24 } 25 26 func (b bound) isLessThan(o bound) (res bool) { 27 if b.infinity < o.infinity { 28 return true 29 } 30 31 if b.infinity > o.infinity { 32 return false 33 } 34 35 if b.infinity == o.infinity && b.infinity != 0 { 36 return false 37 } 38 39 if b.value.Less(o.value) { 40 return true 41 } 42 43 if b.value.Equals(o.value) { 44 if !b.include && o.include { 45 return true 46 } 47 } 48 return false 49 } 50 51 func (b bound) isGreaterThanOrEqual(o bound) (res bool) { 52 return !b.isLessThan(o) 53 } 54 55 func (b bound) isGreaterThan(o bound) (res bool) { 56 return !b.equals(o) || !b.isLessThan(o) 57 } 58 59 func (b bound) equals(o bound) bool { 60 return b.infinity == o.infinity && b.include == o.include && 61 (b.value == nil && o.value == nil || (b.value != nil && o.value != nil && b.value.Equals(o.value))) 62 } 63 64 func (b bound) String() string { 65 var s1 string 66 if b.value == nil { 67 s1 = "<nil>" 68 } else { 69 buf := bytes.Buffer{} 70 types.WriteEncodedValue(&buf, b.value) 71 s1 = buf.String() 72 } 73 return fmt.Sprintf("bound{v: %s, include: %t, infinity: %d}", s1, b.include, b.infinity) 74 } 75 76 func (b bound) minValue(o bound) (res bound) { 77 if b.isLessThan(o) { 78 return b 79 } 80 return o 81 } 82 83 func (b bound) maxValue(o bound) (res bound) { 84 if b.isLessThan(o) { 85 return o 86 } 87 return b 88 } 89 90 type queryRange struct { 91 lower bound 92 upper bound 93 } 94 95 func (r queryRange) and(o queryRange) (rangeDescs queryRangeSlice) { 96 if !r.intersects(o) { 97 return []queryRange{} 98 } 99 100 lower := r.lower.maxValue(o.lower) 101 upper := r.upper.minValue(o.upper) 102 return []queryRange{{lower, upper}} 103 } 104 105 func (r queryRange) or(o queryRange) (rSlice queryRangeSlice) { 106 if r.intersects(o) { 107 v1 := r.lower.minValue(o.lower) 108 v2 := r.upper.maxValue(o.upper) 109 return queryRangeSlice{queryRange{v1, v2}} 110 } 111 rSlice = queryRangeSlice{r, o} 112 sort.Sort(rSlice) 113 return rSlice 114 } 115 116 func (r queryRange) intersects(o queryRange) (res bool) { 117 if r.lower.isGreaterThanOrEqual(o.lower) && r.lower.isLessThanOrEqual(o.upper) { 118 return true 119 } 120 if r.upper.isGreaterThanOrEqual(o.lower) && r.upper.isLessThanOrEqual(o.upper) { 121 return true 122 } 123 if o.lower.isGreaterThanOrEqual(r.lower) && o.lower.isLessThanOrEqual(r.upper) { 124 return true 125 } 126 if o.upper.isGreaterThanOrEqual(r.lower) && o.upper.isLessThanOrEqual(r.upper) { 127 return true 128 } 129 return false 130 } 131 132 func (r queryRange) String() string { 133 return fmt.Sprintf("queryRange{lower: %s, upper: %s", r.lower, r.upper) 134 } 135 136 // queryRangeSlice defines the sort.Interface. This implementation sorts queryRanges by 137 // the lower bound in ascending order. 138 type queryRangeSlice []queryRange 139 140 func (rSlice queryRangeSlice) Len() int { 141 return len(rSlice) 142 } 143 144 func (rSlice queryRangeSlice) Swap(i, j int) { 145 rSlice[i], rSlice[j] = rSlice[j], rSlice[i] 146 } 147 148 func (rSlice queryRangeSlice) Less(i, j int) bool { 149 return !rSlice[i].lower.equals(rSlice[j].lower) && rSlice[i].lower.isLessThanOrEqual(rSlice[j].lower) 150 } 151 152 func (rSlice queryRangeSlice) dbgPrint(w io.Writer) { 153 for i, rd := range rSlice { 154 if i == 0 { 155 fmt.Fprintf(w, "\n#################\n") 156 } 157 fmt.Fprintf(w, "queryRange %d: %s\n", i, rd) 158 } 159 if len(rSlice) > 0 { 160 fmt.Fprintf(w, "\n") 161 } 162 }