mirror of
https://github.com/golang/go
synced 2024-11-20 05:04:43 -07:00
datafmt: use new reflect interface (CL 31107)
R=gri DELTA=70 (7 added, 17 deleted, 46 changed) OCL=31113 CL=31283
This commit is contained in:
parent
f3ec39d1ea
commit
b9b32cab58
@ -416,16 +416,16 @@ func (s *State) error(msg string) {
|
||||
//
|
||||
func getField(val reflect.Value, fieldname string) (reflect.Value, int) {
|
||||
// do we have a struct in the first place?
|
||||
if val.Kind() != reflect.StructKind {
|
||||
sval, ok := val.(*reflect.StructValue);
|
||||
if !ok {
|
||||
return nil, 0;
|
||||
}
|
||||
|
||||
sval, styp := val.(reflect.StructValue), val.Type().(reflect.StructType);
|
||||
styp := sval.Type().(*reflect.StructType);
|
||||
|
||||
// look for field at the top level
|
||||
for i := 0; i < styp.Len(); i++ {
|
||||
name, typ, tag, offset := styp.Field(i);
|
||||
if name == fieldname || name == "" && strings.HasSuffix(typ.Name(), "." + fieldname) /* anonymous field */ {
|
||||
for i := 0; i < styp.NumField(); i++ {
|
||||
f := styp.Field(i);
|
||||
if f.Name == fieldname {
|
||||
return sval.Field(i), 0;
|
||||
}
|
||||
}
|
||||
@ -433,9 +433,9 @@ func getField(val reflect.Value, fieldname string) (reflect.Value, int) {
|
||||
// look for field in anonymous fields
|
||||
var field reflect.Value;
|
||||
level := 1000; // infinity (no struct has that many levels)
|
||||
for i := 0; i < styp.Len(); i++ {
|
||||
name, typ, tag, offset := styp.Field(i);
|
||||
if name == "" {
|
||||
for i := 0; i < styp.NumField(); i++ {
|
||||
f := styp.Field(i);
|
||||
if f.Anonymous {
|
||||
f, l := getField(sval.Field(i), fieldname);
|
||||
// keep the most shallow field
|
||||
if f != nil {
|
||||
@ -461,45 +461,29 @@ func getField(val reflect.Value, fieldname string) (reflect.Value, int) {
|
||||
// 'array' which is not really sufficient. Eventually one may want
|
||||
// to be able to specify rules for say an unnamed slice of T.
|
||||
//
|
||||
var defaultNames = map[int]string {
|
||||
reflect.ArrayKind: "array",
|
||||
reflect.BoolKind: "bool",
|
||||
reflect.ChanKind: "chan",
|
||||
reflect.DotDotDotKind: "ellipsis",
|
||||
reflect.FloatKind: "float",
|
||||
reflect.Float32Kind: "float32",
|
||||
reflect.Float64Kind: "float64",
|
||||
reflect.FuncKind: "func",
|
||||
reflect.IntKind: "int",
|
||||
reflect.Int16Kind: "int16",
|
||||
reflect.Int32Kind: "int32",
|
||||
reflect.Int64Kind: "int64",
|
||||
reflect.Int8Kind: "int8",
|
||||
reflect.InterfaceKind: "interface",
|
||||
reflect.MapKind: "map",
|
||||
reflect.PtrKind: "ptr",
|
||||
reflect.StringKind: "string",
|
||||
reflect.StructKind: "struct",
|
||||
reflect.UintKind: "uint",
|
||||
reflect.Uint16Kind: "uint16",
|
||||
reflect.Uint32Kind: "uint32",
|
||||
reflect.Uint64Kind: "uint64",
|
||||
reflect.Uint8Kind: "uint8",
|
||||
reflect.UintptrKind: "uintptr",
|
||||
}
|
||||
|
||||
|
||||
func typename(value reflect.Value) string {
|
||||
name := value.Type().Name();
|
||||
if name == "" {
|
||||
if defaultName, found := defaultNames[value.Kind()]; found {
|
||||
name = defaultName;
|
||||
}
|
||||
func typename(typ reflect.Type) string {
|
||||
switch t := typ.(type) {
|
||||
case *reflect.ArrayType:
|
||||
return "array";
|
||||
case *reflect.SliceType:
|
||||
return "array";
|
||||
case *reflect.ChanType:
|
||||
return "chan";
|
||||
case *reflect.DotDotDotType:
|
||||
return "ellipsis";
|
||||
case *reflect.FuncType:
|
||||
return "func";
|
||||
case *reflect.InterfaceType:
|
||||
return "interface";
|
||||
case *reflect.MapType:
|
||||
return "map";
|
||||
case *reflect.PtrType:
|
||||
return "ptr";
|
||||
}
|
||||
return name;
|
||||
return typ.String();
|
||||
}
|
||||
|
||||
|
||||
func (s *State) getFormat(name string) expr {
|
||||
if fexpr, found := s.fmt[name]; found {
|
||||
return fexpr;
|
||||
@ -593,35 +577,41 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
|
||||
case "*":
|
||||
// indirection: operation is type-specific
|
||||
switch v := value.(type) {
|
||||
case reflect.ArrayValue:
|
||||
case *reflect.ArrayValue:
|
||||
if v.Len() <= index {
|
||||
return false;
|
||||
}
|
||||
value = v.Elem(index);
|
||||
|
||||
case *reflect.SliceValue:
|
||||
if v.IsNil() || v.Len() <= index {
|
||||
return false;
|
||||
}
|
||||
value = v.Elem(index);
|
||||
|
||||
case reflect.MapValue:
|
||||
case *reflect.MapValue:
|
||||
s.error("reflection support for maps incomplete");
|
||||
|
||||
case reflect.PtrValue:
|
||||
case *reflect.PtrValue:
|
||||
if v.IsNil() {
|
||||
return false;
|
||||
}
|
||||
value = v.Sub();
|
||||
value = v.Elem();
|
||||
|
||||
case reflect.InterfaceValue:
|
||||
case *reflect.InterfaceValue:
|
||||
if v.IsNil() {
|
||||
return false;
|
||||
}
|
||||
value = v.Value();
|
||||
value = v.Elem();
|
||||
|
||||
case reflect.ChanValue:
|
||||
case *reflect.ChanValue:
|
||||
s.error("reflection support for chans incomplete");
|
||||
|
||||
case reflect.FuncValue:
|
||||
case *reflect.FuncValue:
|
||||
s.error("reflection support for funcs incomplete");
|
||||
|
||||
default:
|
||||
s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type().Name()));
|
||||
s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type()));
|
||||
}
|
||||
|
||||
default:
|
||||
@ -629,7 +619,7 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
|
||||
field, _ := getField(value, t.fieldName);
|
||||
if field == nil {
|
||||
// TODO consider just returning false in this case
|
||||
s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type().Name()));
|
||||
s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type()));
|
||||
}
|
||||
value = field;
|
||||
}
|
||||
@ -638,7 +628,7 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
|
||||
ruleName := t.ruleName;
|
||||
if ruleName == "" {
|
||||
// no alternate rule name, value type determines rule
|
||||
ruleName = typename(value)
|
||||
ruleName = typename(value.Type())
|
||||
}
|
||||
fexpr = s.getFormat(ruleName);
|
||||
|
||||
@ -734,11 +724,11 @@ func (f Format) Eval(env Environment, args ...) ([]byte, os.Error) {
|
||||
s := newState(f, env, errors);
|
||||
|
||||
go func() {
|
||||
value := reflect.NewValue(args).(reflect.StructValue);
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
value := reflect.NewValue(args).(*reflect.StructValue);
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
fld := value.Field(i);
|
||||
mark := s.save();
|
||||
if !s.eval(s.getFormat(typename(fld)), fld, 0) { // TODO is 0 index correct?
|
||||
if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct?
|
||||
s.restore(mark);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user