github.com/hedzr/evendeep@v0.4.8/internal/tool/tool.go (about)

     1  package tool
     2  
     3  // tool.go - tools functions here
     4  
     5  import (
     6  	"fmt"
     7  	"log"
     8  	"reflect"
     9  	"strings"
    10  	"unsafe"
    11  
    12  	"github.com/hedzr/evendeep/dbglog"
    13  	"github.com/hedzr/evendeep/typ"
    14  )
    15  
    16  func PtrOf(tgt reflect.Value) reflect.Value {
    17  	ret := reflect.NewAt(tgt.Type(), unsafe.Pointer(tgt.UnsafeAddr()))
    18  	return ret
    19  }
    20  
    21  // func ptr(tgt reflect.Value, want reflect.Type) (r reflect.Value) {
    22  //	//return reflect.PtrTo(tgt)
    23  //	//for tgt.Kind() != reflect.Ptr {
    24  //	//Log("tgt: %v, get pointer", tgt.Kind())
    25  //	//r = reflect.NewAt(tgt.Type(), unsafe.Pointer(tgt.Pointer()))
    26  //	//}
    27  //	if tgt.CanAddr() {
    28  //		r = tgt.Addr()
    29  //	} else {
    30  //		// in hard way
    31  //		if tgt.IsNil() {
    32  //			tmp := reflect.New(want)
    33  //			tgt.Set(tmp)
    34  //			r = tmp
    35  //		} else {
    36  //			var v = tgt.Interface()
    37  //			Log("     v: %v", v)
    38  //			r = reflect.ValueOf(&v)
    39  //			Log("   ret: %v, *%v", r.Kind(), r.Elem().Kind())
    40  //		}
    41  //	}
    42  //	if r.Type() == want {
    43  //		Log("ret: %v, *%v", r.Kind(), r.Elem().Kind())
    44  //		return
    45  //	}
    46  //
    47  //	Log("NOTE an temp pointer was created as *%v", want.Kind())
    48  //	return reflect.New(want)
    49  // }
    50  
    51  func testFieldValue(valueField reflect.Value) (v reflect.Value, addrStr string) {
    52  	addrStr = "not-addressable"
    53  	if valueField.Kind() == reflect.Interface && !valueField.IsNil() {
    54  		elm := valueField.Elem()
    55  		if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
    56  			valueField = elm
    57  		}
    58  	}
    59  	if valueField.Kind() == reflect.Ptr {
    60  		valueField = valueField.Elem()
    61  	}
    62  	if valueField.CanAddr() {
    63  		addrStr = fmt.Sprintf("0x%X", valueField.Addr().Pointer())
    64  	}
    65  	v = valueField
    66  	return
    67  }
    68  
    69  func inspectStructV(val reflect.Value, level int) {
    70  	if val.Kind() == reflect.Interface && !val.IsNil() {
    71  		elm := val.Elem()
    72  		if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
    73  			val = elm
    74  		}
    75  	}
    76  	if val.Kind() == reflect.Ptr {
    77  		val = val.Elem()
    78  	}
    79  
    80  	padding := strings.Repeat("  ", level)
    81  	for i, count := 0, val.NumField(); i < count; i++ {
    82  		valField := val.Field(i)
    83  		typeField := val.Type().Field(i)
    84  		valueField, address := testFieldValue(valField)
    85  
    86  		var v typ.Any
    87  		if valueField.IsValid() && !IsZero(valueField) && valueField.CanInterface() {
    88  			v = valueField.Interface()
    89  		}
    90  		log.Printf("%s%d/%d. Field Name: %s, Field Value: %v,\t Address: %v, Field type: %v [%s]\n",
    91  			padding, i, count, typeField.Name, v, address, typeField.Type, valueField.Kind())
    92  
    93  		if valueField.Kind() == reflect.Struct {
    94  			inspectStructV(valueField, level+1)
    95  		}
    96  	}
    97  }
    98  
    99  // InspectStruct dumps wach field in a struct with its reflect information.
   100  func InspectStruct(v typ.Any) {
   101  	inspectStructV(reflect.ValueOf(v), 0)
   102  }
   103  
   104  // MinInt returns min-value of a and b.
   105  func MinInt(a, b int) int {
   106  	if a < b {
   107  		return a
   108  	}
   109  	return b
   110  }
   111  
   112  // Contains checks if name is in names.
   113  func Contains(names []string, name string) bool {
   114  	for _, n := range names {
   115  		if strings.EqualFold(n, name) {
   116  			return true
   117  		}
   118  	}
   119  	return false
   120  }
   121  
   122  // ContainsPartialsOnly checks if testedString has a part of in partialNames list.
   123  func ContainsPartialsOnly(partialNames []string, testedString string) (contains bool) {
   124  	for _, n := range partialNames {
   125  		if strings.Contains(testedString, n) {
   126  			return true
   127  		}
   128  	}
   129  	return
   130  }
   131  
   132  // PartialContainsShort checks if one of names has partialNeedle as a part.
   133  func PartialContainsShort(names []string, partialNeedle string) (contains bool) {
   134  	for _, n := range names {
   135  		if strings.Contains(n, partialNeedle) {
   136  			return true
   137  		}
   138  	}
   139  	return
   140  }
   141  
   142  // PartialContains checks if one of names has partialNeedle as a part.
   143  func PartialContains(names []string, partialNeedle string) (index int, matched string, contains bool) {
   144  	for ix, n := range names {
   145  		if strings.Contains(n, partialNeedle) {
   146  			return ix, n, true
   147  		}
   148  	}
   149  	return -1, "", false
   150  }
   151  
   152  // ReverseAnySlice reverse any slice/array.
   153  func ReverseAnySlice(s typ.Any) {
   154  	n := reflect.ValueOf(s).Len()
   155  	swap := reflect.Swapper(s)
   156  	for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
   157  		swap(i, j)
   158  	}
   159  }
   160  
   161  // FindInSlice finds a value elv is in array ns.
   162  func FindInSlice(ns reflect.Value, elv typ.Any, i int) (found bool) {
   163  	for j := 0; j < ns.Len(); j++ {
   164  		tev := ns.Index(j).Interface()
   165  		// dbglog.Log("  testing tgt[%v](%v) and src[%v](%v)", j, tev, i, elv)
   166  		if reflect.DeepEqual(tev, elv) {
   167  			found = true
   168  			dbglog.Log("found an exists el at tgt[%v], for src[%v], value is: %v", j, i, elv)
   169  			break
   170  		}
   171  	}
   172  	return
   173  }
   174  
   175  // EqualClassical tests lhs and rhs is equal.
   176  func EqualClassical(lhs, rhs reflect.Value) bool {
   177  	lv, rv := lhs.IsValid(), rhs.IsValid()
   178  	if !lv {
   179  		return !rv
   180  	}
   181  	if !rv {
   182  		return !lv
   183  	}
   184  
   185  	return reflect.DeepEqual(lhs.Interface(), rhs.Interface())
   186  }