github.com/bookerzzz/grok@v0.0.0/value.go (about)

     1  package grok
     2  
     3  import (
     4  	"reflect"
     5  	"fmt"
     6  	"sort"
     7  	"sync"
     8  )
     9  
    10  type Values []reflect.Value
    11  
    12  // Len implements sort.Interface
    13  func (s Values) Len() int {
    14  	return len(s)
    15  }
    16  
    17  // Swap implements sort.Interface
    18  func (s Values) Swap(i, j int) {
    19  	s[i], s[j] = s[j], s[i]
    20  }
    21  
    22  // Less implements sort.Interface
    23  func (s Values) Less(i, j int) bool {
    24  	return fmt.Sprintf("%v", s[i]) < fmt.Sprintf("%v", s[j])
    25  }
    26  
    27  var (
    28  	dumpMutex = sync.Mutex{}
    29  )
    30  
    31  // V aliases Value
    32  func V(value interface{}, options ...Option) {
    33  	Value(value, options...)
    34  }
    35  
    36  // Value prints a more human readable representation of any value
    37  func Value(value interface{}, options ...Option) {
    38  	c := defaults
    39  	for _, o := range options {
    40  		o(&c)
    41  	}
    42  
    43  	// only dump one value at a time to avoid overlap
    44  	dumpMutex.Lock()
    45  	defer dumpMutex.Unlock()
    46  
    47  	// dump it like you mean it
    48  	dump("value", reflect.ValueOf(value), c)
    49  }
    50  
    51  func dump(name string, v reflect.Value, c Conf) {
    52  	out := outer(c)
    53  	colour := colourer(c)
    54  
    55  	if !v.IsValid() {
    56  		out(indent(c) + "<invalid>\n")
    57  		return
    58  	}
    59  	t := v.Type()
    60  
    61  	tn := ""
    62  	switch t.Kind() {
    63  	case reflect.Interface:
    64  		name := t.Name()
    65  		tn = colour("interface{}", colourBlue) + colour(name, colourBlue)
    66  		if !v.IsNil() {
    67  			v = v.Elem()
    68  			t = v.Type()
    69  		}
    70  		if t.Kind() == reflect.Ptr {
    71  			v = v.Elem()
    72  			t = v.Type()
    73  		}
    74  		if t.Name() != name {
    75  			tn = colour(t.Name(), colourBlue) + colour(" as ", colourRed) + tn
    76  		}
    77  	case reflect.Ptr:
    78  		v = v.Elem()
    79  		t = t.Elem()
    80  		tn = colour("*", colourRed) + colour(t.Name(), colourBlue)
    81  	case reflect.Slice:
    82  		tn = colour("[]", colourRed)
    83  		switch t.Elem().Kind() {
    84  		case reflect.Interface:
    85  			tn = tn + colour(t.Elem().Name(), colourBlue)
    86  		case reflect.Ptr:
    87  			tn = tn + colour("*", colourRed)
    88  			tn = tn + colour(t.Elem().Elem().Name(), colourBlue)
    89  		default:
    90  			tn = tn + colour(t.Elem().Name(), colourBlue)
    91  		}
    92  	case reflect.Map:
    93  		tn = colour("map[", colourRed)
    94  		switch t.Key().Kind() {
    95  		case reflect.Interface:
    96  			tn = tn + colour(t.Key().Name(), colourBlue)
    97  		case reflect.Ptr:
    98  			tn = tn + colour("*", colourRed)
    99  			tn = tn + colour(t.Key().Elem().Name(), colourBlue)
   100  		default:
   101  			tn = tn + colour(t.Key().Name(), colourBlue)
   102  		}
   103  		tn = tn + colour("]", colourRed)
   104  		switch t.Elem().Kind() {
   105  		case reflect.Interface:
   106  			tn = tn + colour("interface{}", colourBlue)
   107  		case reflect.Ptr:
   108  			tn = tn + colour("*", colourRed)
   109  			tn = tn + colour(t.Elem().Elem().Name(), colourBlue)
   110  		default:
   111  			tn = tn + colour(t.Elem().Name(), colourBlue)
   112  		}
   113  	case reflect.Chan:
   114  		tn = colour(t.ChanDir().String(), colourRed)
   115  		tn = tn + " " + colour(t.Elem().Name(), colourBlue)
   116  	case reflect.Func:
   117  		tn = colour("func", colourRed)
   118  	case reflect.UnsafePointer:
   119  		tn = colour("unsafe*", colourRed) + colour(t.Name(), colourBlue)
   120  	default:
   121  		tn = colour(t.Name(), colourBlue)
   122  	}
   123  
   124  	if len(name) > 0 {
   125  		out(indent(c) + "%s %s = ", colour(name, colourYellow), tn)
   126  	} else {
   127  		out(indent(c))
   128  	}
   129  
   130  	switch v.Kind() {
   131  	case reflect.Bool:
   132  		out(colour("%v", colourGreen), v.Bool())
   133  	case reflect.Uintptr:
   134  		fallthrough
   135  	case reflect.Int:
   136  		fallthrough
   137  	case reflect.Int8:
   138  		fallthrough
   139  	case reflect.Int16:
   140  		fallthrough
   141  	case reflect.Int32:
   142  		fallthrough
   143  	case reflect.Int64:
   144  		fallthrough
   145  	case reflect.Uint:
   146  		fallthrough
   147  	case reflect.Uint8:
   148  		fallthrough
   149  	case reflect.Uint16:
   150  		fallthrough
   151  	case reflect.Uint32:
   152  		fallthrough
   153  	case reflect.Uint64:
   154  		fallthrough
   155  	case reflect.Float32:
   156  		fallthrough
   157  	case reflect.Float64:
   158  		fallthrough
   159  	case reflect.Complex64:
   160  		fallthrough
   161  	case reflect.Complex128:
   162  		out(colour("%v", colourGreen), v)
   163  	case reflect.Array:
   164  		fallthrough
   165  	case reflect.Slice:
   166  		if v.Len() == 0 {
   167  			out("[]\n")
   168  			return
   169  		}
   170  		out("[\n")
   171  		c.depth = c.depth + 1
   172  		if c.maxDepth > 0 && c.depth >= c.maxDepth {
   173  			out(indent(c) + colour("... max depth reached\n", colourGrey))
   174  		} else {
   175  			for i := 0; i < v.Len(); i++ {
   176  				dump(colour(fmt.Sprintf("%d", i), colourRed), v.Index(i), c)
   177  			}
   178  		}
   179  		c.depth = c.depth - 1
   180  		out(indent(c) + "]")
   181  	case reflect.Chan:
   182  		if v.IsNil() {
   183  			out(colour("<nil>", colourGrey))
   184  		} else {
   185  			out(colour("%v", colourGreen), v)
   186  		}
   187  	case reflect.Func:
   188  		if v.IsNil() {
   189  			out(colour("<nil>", colourGrey))
   190  		} else {
   191  			out(colour("%v", colourGreen), v)
   192  		}
   193  	case reflect.Map:
   194  		if !v.IsValid() {
   195  			out(colour("<nil>", colourGrey))
   196  		} else {
   197  			if v.Len() == 0 {
   198  				out("[]\n")
   199  				return
   200  			}
   201  			out("[\n")
   202  			c.depth = c.depth + 1
   203  			if c.maxDepth > 0 && c.depth >= c.maxDepth {
   204  				out(indent(c) + colour("... max depth reached\n", colourGrey))
   205  			} else {
   206  				keys := v.MapKeys();
   207  				sort.Sort(Values(keys))
   208  				for _, k := range v.MapKeys() {
   209  					dump(fmt.Sprintf("%v", k), v.MapIndex(k), c)
   210  				}
   211  			}
   212  			c.depth = c.depth - 1
   213  			out(indent(c) + "]")
   214  		}
   215  	case reflect.String:
   216  		s := v.String()
   217  		slen := len(s)
   218  		if c.maxLength > 0 && slen > c.maxLength {
   219  			s = fmt.Sprintf("%s...", string([]byte(s)[0:c.maxLength]))
   220  		}
   221  		out(colour("%q ", colourGreen), s)
   222  		out(colour("%d", colourGrey), slen)
   223  	case reflect.Struct:
   224  		if v.NumField() == 0 {
   225  			out("{}\n")
   226  			return
   227  		}
   228  		out("{\n")
   229  		c.depth = c.depth + 1
   230  		if c.maxDepth > 0 && c.depth >= c.maxDepth {
   231  			out(indent(c) + colour("... max depth reached\n", colourGrey))
   232  		} else {
   233  			for i := 0; i < v.NumField(); i++ {
   234  				dump(t.Field(i).Name, v.Field(i), c)
   235  			}
   236  		}
   237  		c.depth = c.depth - 1
   238  		out(indent(c) + "}")
   239  	case reflect.UnsafePointer:
   240  		out(colour("%v", colourGreen), v)
   241  	case reflect.Invalid:
   242  		out(colour("<nil>", colourGrey))
   243  	case reflect.Interface:
   244  		if v.IsNil() {
   245  			out(colour("<nil>", colourGrey))
   246  		} else {
   247  			out(colour("%v", colourGreen), v)
   248  		}
   249  	default:
   250  		out(colour("??? %s", colourRed), v.Kind().String())
   251  	}
   252  	out("\n")
   253  }