mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.6 KiB
152 lines
3.6 KiB
// Copyright 2011 Aaron Jacobs. All Rights Reserved. |
|
// Author: aaronjjacobs@gmail.com (Aaron Jacobs) |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
|
|
package oglematchers |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"math" |
|
"reflect" |
|
) |
|
|
|
// LessThan returns a matcher that matches integer, floating point, or strings |
|
// values v such that v < x. Comparison is not defined between numeric and |
|
// string types, but is defined between all integer and floating point types. |
|
// |
|
// x must itself be an integer, floating point, or string type; otherwise, |
|
// LessThan will panic. |
|
func LessThan(x interface{}) Matcher { |
|
v := reflect.ValueOf(x) |
|
kind := v.Kind() |
|
|
|
switch { |
|
case isInteger(v): |
|
case isFloat(v): |
|
case kind == reflect.String: |
|
|
|
default: |
|
panic(fmt.Sprintf("LessThan: unexpected kind %v", kind)) |
|
} |
|
|
|
return &lessThanMatcher{v} |
|
} |
|
|
|
type lessThanMatcher struct { |
|
limit reflect.Value |
|
} |
|
|
|
func (m *lessThanMatcher) Description() string { |
|
// Special case: make it clear that strings are strings. |
|
if m.limit.Kind() == reflect.String { |
|
return fmt.Sprintf("less than \"%s\"", m.limit.String()) |
|
} |
|
|
|
return fmt.Sprintf("less than %v", m.limit.Interface()) |
|
} |
|
|
|
func compareIntegers(v1, v2 reflect.Value) (err error) { |
|
err = errors.New("") |
|
|
|
switch { |
|
case isSignedInteger(v1) && isSignedInteger(v2): |
|
if v1.Int() < v2.Int() { |
|
err = nil |
|
} |
|
return |
|
|
|
case isSignedInteger(v1) && isUnsignedInteger(v2): |
|
if v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() { |
|
err = nil |
|
} |
|
return |
|
|
|
case isUnsignedInteger(v1) && isSignedInteger(v2): |
|
if v1.Uint() <= math.MaxInt64 && int64(v1.Uint()) < v2.Int() { |
|
err = nil |
|
} |
|
return |
|
|
|
case isUnsignedInteger(v1) && isUnsignedInteger(v2): |
|
if v1.Uint() < v2.Uint() { |
|
err = nil |
|
} |
|
return |
|
} |
|
|
|
panic(fmt.Sprintf("compareIntegers: %v %v", v1, v2)) |
|
} |
|
|
|
func getFloat(v reflect.Value) float64 { |
|
switch { |
|
case isSignedInteger(v): |
|
return float64(v.Int()) |
|
|
|
case isUnsignedInteger(v): |
|
return float64(v.Uint()) |
|
|
|
case isFloat(v): |
|
return v.Float() |
|
} |
|
|
|
panic(fmt.Sprintf("getFloat: %v", v)) |
|
} |
|
|
|
func (m *lessThanMatcher) Matches(c interface{}) (err error) { |
|
v1 := reflect.ValueOf(c) |
|
v2 := m.limit |
|
|
|
err = errors.New("") |
|
|
|
// Handle strings as a special case. |
|
if v1.Kind() == reflect.String && v2.Kind() == reflect.String { |
|
if v1.String() < v2.String() { |
|
err = nil |
|
} |
|
return |
|
} |
|
|
|
// If we get here, we require that we are dealing with integers or floats. |
|
v1Legal := isInteger(v1) || isFloat(v1) |
|
v2Legal := isInteger(v2) || isFloat(v2) |
|
if !v1Legal || !v2Legal { |
|
err = NewFatalError("which is not comparable") |
|
return |
|
} |
|
|
|
// Handle the various comparison cases. |
|
switch { |
|
// Both integers |
|
case isInteger(v1) && isInteger(v2): |
|
return compareIntegers(v1, v2) |
|
|
|
// At least one float32 |
|
case v1.Kind() == reflect.Float32 || v2.Kind() == reflect.Float32: |
|
if float32(getFloat(v1)) < float32(getFloat(v2)) { |
|
err = nil |
|
} |
|
return |
|
|
|
// At least one float64 |
|
case v1.Kind() == reflect.Float64 || v2.Kind() == reflect.Float64: |
|
if getFloat(v1) < getFloat(v2) { |
|
err = nil |
|
} |
|
return |
|
} |
|
|
|
// We shouldn't get here. |
|
panic(fmt.Sprintf("lessThanMatcher.Matches: Shouldn't get here: %v %v", v1, v2)) |
|
}
|
|
|