1
0
mirror of https://github.com/golang/go synced 2024-10-04 14:21:21 -06:00
go/src/lib/reflect/tostring.go

223 lines
5.2 KiB
Go
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Reflection library.
// Formatting of types and values for debugging.
package reflect
import (
"reflect";
"strconv";
)
export func TypeToString(typ Type, expand bool) string
export func ValueToString(val Value) string
func DoubleQuote(s string) string {
out := "\"";
for i := 0; i < len(s); i++ {
c := s[i];
switch c {
case '\n':
out += `\n`;
case '\t':
out += `\t`;
case '\x00':
out += `\x00`;
case '"':
out += `\"`;
case '\\':
out += `\\`;
default:
out += string(c);
}
}
out += "\"";
return out;
}
type HasFields interface {
Field(i int) (name string, typ Type, tag string, offset int);
Len() int;
}
func TypeFieldsToString(t HasFields, sep string) string {
var str string;
for i := 0; i < t.Len(); i++ {
str1, typ, tag, offset := t.Field(i);
if str1 != "" {
str1 += " "
}
str1 += TypeToString(typ, false);
if tag != "" {
str1 += " " + DoubleQuote(tag);
}
if i < t.Len() - 1 {
str1 += sep + " ";
}
str += str1;
}
return str;
}
func TypeToString(typ Type, expand bool) string {
var str string;
if name := typ.Name(); !expand && name != "" {
return name
}
switch(typ.Kind()) {
case MissingKind:
return "$missing$";
case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
FloatKind, Float32Kind, Float64Kind, Float80Kind,
StringKind,
DotDotDotKind:
return typ.Name();
case PtrKind:
p := typ.(PtrType);
return "*" + TypeToString(p.Sub(), false);
case ArrayKind:
a := typ.(ArrayType);
if a.Open() {
str = "[]"
} else {
str = "[" + strconv.itoa64(int64(a.Len())) + "]"
}
return str + TypeToString(a.Elem(), false);
case MapKind:
m := typ.(MapType);
str = "map[" + TypeToString(m.Key(), false) + "]";
return str + TypeToString(m.Elem(), false);
case ChanKind:
c := typ.(ChanType);
switch c.Dir() {
case RecvDir:
str = "<-chan";
case SendDir:
str = "chan<-";
case BothDir:
str = "chan";
default:
panicln("reflect.TypeToString: unknown chan direction");
}
return str + TypeToString(c.Elem(), false);
case StructKind:
return "struct{" + TypeFieldsToString(typ, ";") + "}";
case InterfaceKind:
return "interface{" + TypeFieldsToString(typ, ";") + "}";
case FuncKind:
f := typ.(FuncType);
str = "(" + TypeFieldsToString(f.In(), ",") + ")";
if f.Out() != nil {
str += "(" + TypeFieldsToString(f.Out(), ",") + ")";
}
return str;
default:
panicln("reflect.TypeToString: can't print type ", typ.Kind());
}
return "reflect.TypeToString: can't happen";
}
// TODO: want an unsigned one too
func integer(v int64) string {
return strconv.itoa64(v);
}
func ValueToString(val Value) string {
var str string;
typ := val.Type();
switch(val.Kind()) {
case MissingKind:
return "missing";
case IntKind:
return integer(int64(val.(IntValue).Get()));
case Int8Kind:
return integer(int64(val.(Int8Value).Get()));
case Int16Kind:
return integer(int64(val.(Int16Value).Get()));
case Int32Kind:
return integer(int64(val.(Int32Value).Get()));
case Int64Kind:
return integer(int64(val.(Int64Value).Get()));
case UintKind:
return integer(int64(val.(UintValue).Get()));
case Uint8Kind:
return integer(int64(val.(Uint8Value).Get()));
case Uint16Kind:
return integer(int64(val.(Uint16Value).Get()));
case Uint32Kind:
return integer(int64(val.(Uint32Value).Get()));
case Uint64Kind:
return integer(int64(val.(Uint64Value).Get()));
case FloatKind:
if strconv.floatsize == 32 {
return strconv.ftoa32(float32(val.(FloatValue).Get()), 'g', -1);
} else {
return strconv.ftoa64(float64(val.(FloatValue).Get()), 'g', -1);
}
case Float32Kind:
return strconv.ftoa32(val.(Float32Value).Get(), 'g', -1);
case Float64Kind:
return strconv.ftoa64(val.(Float64Value).Get(), 'g', -1);
case Float80Kind:
return "float80";
case StringKind:
return val.(StringValue).Get();
case BoolKind:
if val.(BoolValue).Get() {
return "true"
} else {
return "false"
}
case PtrKind:
v := val.(PtrValue);
return TypeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")";
case ArrayKind:
t := typ.(ArrayType);
v := val.(ArrayValue);
str += TypeToString(t, false);
str += "{";
for i := 0; i < v.Len(); i++ {
if i > 0 {
str += ", "
}
str += ValueToString(v.Elem(i));
}
str += "}";
return str;
case MapKind:
t := typ.(MapType);
v := val.(ArrayValue);
str = TypeToString(t, false);
str += "{";
str += "<can't iterate on maps>";
str += "}";
return str;
case ChanKind:
return "can't print chans yet";
case StructKind:
t := typ.(StructType);
v := val.(StructValue);
str += TypeToString(t, false);
str += "{";
for i := 0; i < v.Len(); i++ {
if i > 0 {
str += ", "
}
str += ValueToString(v.Field(i));
}
str += "}";
return str;
case InterfaceKind:
return "can't print interfaces yet";
case FuncKind:
return "can't print funcs yet";
default:
panicln("reflect.ValueToString: can't print type ", val.Kind());
}
return "reflect.ValueToString: can't happen";
}