diff options
Diffstat (limited to 'src/pkg/reflect/tostring.go')
-rw-r--r-- | src/pkg/reflect/tostring.go | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/src/pkg/reflect/tostring.go b/src/pkg/reflect/tostring.go new file mode 100644 index 000000000..43be4b9e8 --- /dev/null +++ b/src/pkg/reflect/tostring.go @@ -0,0 +1,234 @@ +// 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 reflection types and values for debugging. +// Not defined as methods so they do not need to be linked into most binaries; +// the functions are not used by the library itself, only in tests. + +package reflect + +import ( + "reflect"; + "strconv"; +) + +func typeToString(typ Type, expand bool) string +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, iface bool) string { + var str string; + for i := 0; i < t.Len(); i++ { + str1, typ, tag, offset := t.Field(i); + if str1 != "" { + str1 += " " + } + str2 := typeToString(typ, false); + if iface && str2[0:4] == "func" { + str2 = str2[4:len(str2)] + } + str1 += str2; + if tag != "" { + str1 += " " + doubleQuote(tag); + } + if i < t.Len() - 1 { + str1 += sep + " "; + } + str += str1; + } + return str; +} + +// typeToString returns a textual representation of typ. The expand +// flag specifies whether to expand the contents of type names; if false, +// the name itself is used as the representation. +// Meant for debugging only; typ.String() serves for most purposes. +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, + StringKind, + DotDotDotKind: + return typ.Name(); + case PtrKind: + p := typ.(PtrType); + return "*" + typeToString(p.Sub(), false); + case ArrayKind: + a := typ.(ArrayType); + if a.IsSlice() { + 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.(StructType), ";", false) + "}"; + case InterfaceKind: + return "interface{" + typeFieldsToString(typ.(InterfaceType), ";", true) + "}"; + case FuncKind: + f := typ.(FuncType); + str = "func(" + typeFieldsToString(f.In(), ",", false) + ")"; + if f.Out() != nil { + str += "(" + typeFieldsToString(f.Out(), ",", false) + ")"; + } + 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); +} + +// valueToString returns a textual representation of the reflection value val. +// For debugging only. +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 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.(MapValue); + str = typeToString(t, false); + str += "{"; + str += "<can't iterate on maps>"; + str += "}"; + return str; + case ChanKind: + str = typeToString(typ, false); + return str; + 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: + v := val.(FuncValue); + return typeToString(typ, false) + "(" + integer(int64(uintptr(v.Get()))) + ")"; + default: + panicln("reflect.valueToString: can't print type ", val.Kind()); + } + return "reflect.valueToString: can't happen"; +} |