| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | // 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 oglematchersimport (	"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))}
 |