github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/reflect.go (about)

     1  package f
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  )
     8  
     9  /*************************************************************
    10   * Reflection:
    11   * From package(go 1.13) "reflect" -> reflect/value.go
    12   *************************************************************/
    13  
    14  // IsZero reports whether v is the zero value for its type.
    15  // It panics if the argument is invalid.
    16  // NOTICE: this's an built-in method in reflect/value.go since go 1.13
    17  func IsZero(v reflect.Value) bool {
    18  	switch v.Kind() {
    19  	case reflect.Bool:
    20  		return !v.Bool()
    21  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    22  		return v.Int() == 0
    23  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    24  		return v.Uint() == 0
    25  	case reflect.Float32, reflect.Float64:
    26  		return math.Float64bits(v.Float()) == 0
    27  	case reflect.Complex64, reflect.Complex128:
    28  		c := v.Complex()
    29  		return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
    30  	case reflect.Array:
    31  		for i := 0; i < v.Len(); i++ {
    32  			// if !v.Index(i).IsZero() {
    33  			if !IsZero(v.Index(i)) {
    34  				return false
    35  			}
    36  		}
    37  		return true
    38  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
    39  		return v.IsNil()
    40  	case reflect.String:
    41  		return v.Len() == 0
    42  	case reflect.Struct:
    43  		for i := 0; i < v.NumField(); i++ {
    44  			// if !v.Index(i).IsZero() {
    45  			if !IsZero(v.Field(i)) {
    46  				return false
    47  			}
    48  		}
    49  		return true
    50  	default:
    51  		// This should never happens, but will act as a safeguard for
    52  		// later, as a default value doesn't makes sense here.
    53  		panic(&reflect.ValueError{Method: "cannot check reflect.Value.IsZero", Kind: v.Kind()})
    54  	}
    55  }
    56  
    57  // IsEmpty Is the variable empty.
    58  func IsEmpty(val interface{}) bool {
    59  	if val == nil {
    60  		return true
    61  	}
    62  
    63  	v := reflect.ValueOf(val)
    64  	switch v.Kind() {
    65  	case reflect.String, reflect.Array, reflect.Chan:
    66  		return v.Len() == 0
    67  	case reflect.Map, reflect.Slice:
    68  		return v.Len() == 0 || v.IsNil()
    69  	case reflect.Bool:
    70  		return !v.Bool()
    71  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    72  		return v.Int() == 0
    73  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    74  		return v.Uint() == 0
    75  	case reflect.Float32, reflect.Float64:
    76  		return v.Float() == 0
    77  	case reflect.Interface, reflect.Ptr:
    78  		if v.IsNil() {
    79  			return true
    80  		}
    81  		return IsEmpty(v.Elem().Interface())
    82  	}
    83  
    84  	return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
    85  }
    86  
    87  // IsNil checks if a specified object is nil or not, without Failing.
    88  func IsNil(object interface{}) bool {
    89  	if object == nil {
    90  		return true
    91  	}
    92  
    93  	value := reflect.ValueOf(object)
    94  	kind := value.Kind()
    95  	isNilKind := containsKind(
    96  		[]reflect.Kind{
    97  			reflect.Chan, reflect.Func,
    98  			reflect.Interface, reflect.Map,
    99  			reflect.Ptr, reflect.Slice},
   100  		kind)
   101  
   102  	if isNilKind && value.IsNil() {
   103  		return true
   104  	}
   105  
   106  	return false
   107  }
   108  
   109  // Eq evaluates the comparison a == b
   110  // Support:
   111  // 	bool, int(X), uint(X), string, float(X)
   112  func Eq(arg1 reflect.Value, arg2 reflect.Value) (bool, error) {
   113  	v1 := indirectInterface(arg1)
   114  	k1, err := basicKind(v1)
   115  	if err != nil {
   116  		return false, err
   117  	}
   118  
   119  	v2 := indirectInterface(arg2)
   120  	k2, err := basicKind(v2)
   121  	if err != nil {
   122  		return false, err
   123  	}
   124  
   125  	truth := false
   126  	if k1 != k2 {
   127  		// Special case: Can compare integer values regardless of type's sign.
   128  		switch {
   129  		case k1 == intKind && k2 == uintKind:
   130  			truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
   131  		case k1 == uintKind && k2 == intKind:
   132  			truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
   133  		}
   134  		return truth, nil
   135  	}
   136  
   137  	switch k1 {
   138  	case boolKind:
   139  		truth = v1.Bool() == v2.Bool()
   140  	case complexKind:
   141  		truth = v1.Complex() == v2.Complex()
   142  	case floatKind:
   143  		truth = v1.Float() == v2.Float()
   144  	case intKind:
   145  		truth = v1.Int() == v2.Int()
   146  	case stringKind:
   147  		truth = v1.String() == v2.String()
   148  	case uintKind:
   149  		truth = v1.Uint() == v2.Uint()
   150  	}
   151  
   152  	return truth, nil
   153  }
   154  
   155  // ValueLen returns v's length.
   156  func ValueLen(v reflect.Value) int {
   157  	k := v.Kind()
   158  
   159  	// (u)int use width.
   160  	switch k {
   161  	case reflect.Map, reflect.Array, reflect.Chan, reflect.Slice, reflect.String:
   162  		return v.Len()
   163  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   164  		return len(fmt.Sprint(v.Uint()))
   165  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   166  		return len(fmt.Sprint(v.Int()))
   167  	case reflect.Float32, reflect.Float64:
   168  		return len(fmt.Sprint(v.Interface()))
   169  	}
   170  
   171  	// cannot get length
   172  	return -1
   173  }
   174  
   175  // TypeElem returns the underlying type if the given type is a pointer.
   176  func TypeElem(t reflect.Type) reflect.Type {
   177  	for t != nil && t.Kind() == reflect.Ptr {
   178  		t = t.Elem()
   179  	}
   180  	return t
   181  }
   182  
   183  /*************************************************************
   184   * Reflection Kind Extensions
   185   *************************************************************/
   186  
   187  type kind int
   188  
   189  const (
   190  	invalidKind kind = iota
   191  	boolKind
   192  	complexKind
   193  	intKind
   194  	floatKind
   195  	stringKind
   196  	uintKind
   197  )
   198  
   199  func basicKind(v reflect.Value) (kind, error) {
   200  	switch v.Kind() {
   201  	case reflect.Bool:
   202  		return boolKind, nil
   203  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   204  		return intKind, nil
   205  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   206  		return uintKind, nil
   207  	case reflect.Float32, reflect.Float64:
   208  		return floatKind, nil
   209  	case reflect.Complex64, reflect.Complex128:
   210  		return complexKind, nil
   211  	case reflect.String:
   212  		return stringKind, nil
   213  	}
   214  
   215  	// like: slice, array, map ...
   216  	return invalidKind, ErrBadComparisonType
   217  }
   218  
   219  // indirectInterface returns the concrete value in an interface value,
   220  // or else the zero reflect.Value.
   221  // That is, if v represents the interface value x, the result is the same as reflect.ValueOf(x):
   222  // the fact that x was an interface value is forgotten.
   223  func indirectInterface(v reflect.Value) reflect.Value {
   224  	if v.Kind() != reflect.Interface {
   225  		return v
   226  	}
   227  
   228  	if v.IsNil() {
   229  		return emptyValue
   230  	}
   231  
   232  	return v.Elem()
   233  }
   234  
   235  // containsKind checks if a specified kind in the slice of kinds.
   236  func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
   237  	for i := 0; i < len(kinds); i++ {
   238  		if kind == kinds[i] {
   239  			return true
   240  		}
   241  	}
   242  
   243  	return false
   244  }