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  }