diff options
author | Rémy Oudompheng <oudomphe@phare.normalesup.org> | 2013-06-02 15:40:32 +0200 |
---|---|---|
committer | Rémy Oudompheng <oudomphe@phare.normalesup.org> | 2013-06-02 15:40:32 +0200 |
commit | 5a810f7c0a53c11a135fb527f18c31372c552011 (patch) | |
tree | 94d6d1cd478f37459529fb3a3a088f02547fe519 /src/cmd/fix | |
parent | 57d89fb6598046a41b1690dec1222257a3c21bf6 (diff) | |
download | go-5a810f7c0a53c11a135fb527f18c31372c552011.tar.gz go-5a810f7c0a53c11a135fb527f18c31372c552011.zip |
cmd/fix: remove obsolete testdata.
The corresponding rules have been removed for Go 1.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/9940044
Diffstat (limited to 'src/cmd/fix')
30 files changed, 0 insertions, 19227 deletions
diff --git a/src/cmd/fix/testdata/reflect.asn1.go.in b/src/cmd/fix/testdata/reflect.asn1.go.in deleted file mode 100644 index 43128f6b26..0000000000 --- a/src/cmd/fix/testdata/reflect.asn1.go.in +++ /dev/null @@ -1,814 +0,0 @@ -// 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. - -// The asn1 package implements parsing of DER-encoded ASN.1 data structures, -// as defined in ITU-T Rec X.690. -// -// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' -// http://luca.ntop.org/Teaching/Appunti/asn1.html. -package asn1 - -// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc -// are different encoding formats for those objects. Here, we'll be dealing -// with DER, the Distinguished Encoding Rules. DER is used in X.509 because -// it's fast to parse and, unlike BER, has a unique encoding for every object. -// When calculating hashes over objects, it's important that the resulting -// bytes be the same at both ends and DER removes this margin of error. -// -// ASN.1 is very complex and this package doesn't attempt to implement -// everything by any means. - -import ( - "fmt" - "os" - "reflect" - "time" -) - -// A StructuralError suggests that the ASN.1 data is valid, but the Go type -// which is receiving it doesn't match. -type StructuralError struct { - Msg string -} - -func (e StructuralError) String() string { return "ASN.1 structure error: " + e.Msg } - -// A SyntaxError suggests that the ASN.1 data is invalid. -type SyntaxError struct { - Msg string -} - -func (e SyntaxError) String() string { return "ASN.1 syntax error: " + e.Msg } - -// We start by dealing with each of the primitive types in turn. - -// BOOLEAN - -func parseBool(bytes []byte) (ret bool, err os.Error) { - if len(bytes) != 1 { - err = SyntaxError{"invalid boolean"} - return - } - - return bytes[0] != 0, nil -} - -// INTEGER - -// parseInt64 treats the given bytes as a big-endian, signed integer and -// returns the result. -func parseInt64(bytes []byte) (ret int64, err os.Error) { - if len(bytes) > 8 { - // We'll overflow an int64 in this case. - err = StructuralError{"integer too large"} - return - } - for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { - ret <<= 8 - ret |= int64(bytes[bytesRead]) - } - - // Shift up and down in order to sign extend the result. - ret <<= 64 - uint8(len(bytes))*8 - ret >>= 64 - uint8(len(bytes))*8 - return -} - -// parseInt treats the given bytes as a big-endian, signed integer and returns -// the result. -func parseInt(bytes []byte) (int, os.Error) { - ret64, err := parseInt64(bytes) - if err != nil { - return 0, err - } - if ret64 != int64(int(ret64)) { - return 0, StructuralError{"integer too large"} - } - return int(ret64), nil -} - -// BIT STRING - -// BitString is the structure to use when you want an ASN.1 BIT STRING type. A -// bit string is padded up to the nearest byte in memory and the number of -// valid bits is recorded. Padding bits will be zero. -type BitString struct { - Bytes []byte // bits packed into bytes. - BitLength int // length in bits. -} - -// At returns the bit at the given index. If the index is out of range it -// returns false. -func (b BitString) At(i int) int { - if i < 0 || i >= b.BitLength { - return 0 - } - x := i / 8 - y := 7 - uint(i%8) - return int(b.Bytes[x]>>y) & 1 -} - -// RightAlign returns a slice where the padding bits are at the beginning. The -// slice may share memory with the BitString. -func (b BitString) RightAlign() []byte { - shift := uint(8 - (b.BitLength % 8)) - if shift == 8 || len(b.Bytes) == 0 { - return b.Bytes - } - - a := make([]byte, len(b.Bytes)) - a[0] = b.Bytes[0] >> shift - for i := 1; i < len(b.Bytes); i++ { - a[i] = b.Bytes[i-1] << (8 - shift) - a[i] |= b.Bytes[i] >> shift - } - - return a -} - -// parseBitString parses an ASN.1 bit string from the given byte array and returns it. -func parseBitString(bytes []byte) (ret BitString, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length BIT STRING"} - return - } - paddingBits := int(bytes[0]) - if paddingBits > 7 || - len(bytes) == 1 && paddingBits > 0 || - bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 { - err = SyntaxError{"invalid padding bits in BIT STRING"} - return - } - ret.BitLength = (len(bytes)-1)*8 - paddingBits - ret.Bytes = bytes[1:] - return -} - -// OBJECT IDENTIFIER - -// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER. -type ObjectIdentifier []int - -// Equal returns true iff oi and other represent the same identifier. -func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool { - if len(oi) != len(other) { - return false - } - for i := 0; i < len(oi); i++ { - if oi[i] != other[i] { - return false - } - } - - return true -} - -// parseObjectIdentifier parses an OBJECT IDENTIFER from the given bytes and -// returns it. An object identifer is a sequence of variable length integers -// that are assigned in a hierarachy. -func parseObjectIdentifier(bytes []byte) (s []int, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length OBJECT IDENTIFIER"} - return - } - - // In the worst case, we get two elements from the first byte (which is - // encoded differently) and then every varint is a single byte long. - s = make([]int, len(bytes)+1) - - // The first byte is 40*value1 + value2: - s[0] = int(bytes[0]) / 40 - s[1] = int(bytes[0]) % 40 - i := 2 - for offset := 1; offset < len(bytes); i++ { - var v int - v, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - s[i] = v - } - s = s[0:i] - return -} - -// ENUMERATED - -// An Enumerated is represented as a plain int. -type Enumerated int - -// FLAG - -// A Flag accepts any data and is set to true if present. -type Flag bool - -// parseBase128Int parses a base-128 encoded int from the given offset in the -// given byte array. It returns the value and the new offset. -func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err os.Error) { - offset = initOffset - for shifted := 0; offset < len(bytes); shifted++ { - if shifted > 4 { - err = StructuralError{"base 128 integer too large"} - return - } - ret <<= 7 - b := bytes[offset] - ret |= int(b & 0x7f) - offset++ - if b&0x80 == 0 { - return - } - } - err = SyntaxError{"truncated base 128 integer"} - return -} - -// UTCTime - -func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) { - s := string(bytes) - ret, err = time.Parse("0601021504Z0700", s) - if err == nil { - return - } - ret, err = time.Parse("060102150405Z0700", s) - return -} - -// parseGeneralizedTime parses the GeneralizedTime from the given byte array -// and returns the resulting time. -func parseGeneralizedTime(bytes []byte) (ret *time.Time, err os.Error) { - return time.Parse("20060102150405Z0700", string(bytes)) -} - -// PrintableString - -// parsePrintableString parses a ASN.1 PrintableString from the given byte -// array and returns it. -func parsePrintableString(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if !isPrintable(b) { - err = SyntaxError{"PrintableString contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// isPrintable returns true iff the given b is in the ASN.1 PrintableString set. -func isPrintable(b byte) bool { - return 'a' <= b && b <= 'z' || - 'A' <= b && b <= 'Z' || - '0' <= b && b <= '9' || - '\'' <= b && b <= ')' || - '+' <= b && b <= '/' || - b == ' ' || - b == ':' || - b == '=' || - b == '?' || - // This is techincally not allowed in a PrintableString. - // However, x509 certificates with wildcard strings don't - // always use the correct string type so we permit it. - b == '*' -} - -// IA5String - -// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given -// byte array and returns it. -func parseIA5String(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if b >= 0x80 { - err = SyntaxError{"IA5String contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// T61String - -// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given -// byte array and returns it. -func parseT61String(bytes []byte) (ret string, err os.Error) { - return string(bytes), nil -} - -// A RawValue represents an undecoded ASN.1 object. -type RawValue struct { - Class, Tag int - IsCompound bool - Bytes []byte - FullBytes []byte // includes the tag and length -} - -// RawContent is used to signal that the undecoded, DER data needs to be -// preserved for a struct. To use it, the first field of the struct must have -// this type. It's an error for any of the other fields to have this type. -type RawContent []byte - -// Tagging - -// parseTagAndLength parses an ASN.1 tag and length pair from the given offset -// into a byte array. It returns the parsed data and the new offset. SET and -// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we -// don't distinguish between ordered and unordered objects in this code. -func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err os.Error) { - offset = initOffset - b := bytes[offset] - offset++ - ret.class = int(b >> 6) - ret.isCompound = b&0x20 == 0x20 - ret.tag = int(b & 0x1f) - - // If the bottom five bits are set, then the tag number is actually base 128 - // encoded afterwards - if ret.tag == 0x1f { - ret.tag, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - } - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - if b&0x80 == 0 { - // The length is encoded in the bottom 7 bits. - ret.length = int(b & 0x7f) - } else { - // Bottom 7 bits give the number of length bytes to follow. - numBytes := int(b & 0x7f) - // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. - if numBytes > 3 { - err = StructuralError{"length too large"} - return - } - if numBytes == 0 { - err = SyntaxError{"indefinite length found (not DER)"} - return - } - ret.length = 0 - for i := 0; i < numBytes; i++ { - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - ret.length <<= 8 - ret.length |= int(b) - } - } - - return -} - -// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse -// a number of ASN.1 values from the given byte array and returns them as a -// slice of Go values of the given type. -func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflect.Type) (ret *reflect.SliceValue, err os.Error) { - expectedTag, compoundType, ok := getUniversalType(elemType) - if !ok { - err = StructuralError{"unknown Go type for slice"} - return - } - - // First we iterate over the input and count the number of elements, - // checking that the types are correct in each case. - numElements := 0 - for offset := 0; offset < len(bytes); { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so - // that a sequence of them can be parsed into a []string. - if t.tag == tagGeneralString { - t.tag = tagPrintableString - } - if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { - err = StructuralError{"sequence tag mismatch"} - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"truncated sequence"} - return - } - offset += t.length - numElements++ - } - ret = reflect.MakeSlice(sliceType, numElements, numElements) - params := fieldParameters{} - offset := 0 - for i := 0; i < numElements; i++ { - offset, err = parseField(ret.Elem(i), bytes, offset, params) - if err != nil { - return - } - } - return -} - -var ( - bitStringType = reflect.Typeof(BitString{}) - objectIdentifierType = reflect.Typeof(ObjectIdentifier{}) - enumeratedType = reflect.Typeof(Enumerated(0)) - flagType = reflect.Typeof(Flag(false)) - timeType = reflect.Typeof(&time.Time{}) - rawValueType = reflect.Typeof(RawValue{}) - rawContentsType = reflect.Typeof(RawContent(nil)) -) - -// invalidLength returns true iff offset + length > sliceLength, or if the -// addition would overflow. -func invalidLength(offset, length, sliceLength int) bool { - return offset+length < offset || offset+length > sliceLength -} - -// parseField is the main parsing function. Given a byte array and an offset -// into the array, it will try to parse a suitable ASN.1 value out and store it -// in the given Value. -func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err os.Error) { - offset = initOffset - fieldType := v.Type() - - // If we have run out of data, it may be that there are optional elements at the end. - if offset == len(bytes) { - if !setDefaultValue(v, params) { - err = SyntaxError{"sequence truncated"} - } - return - } - - // Deal with raw values. - if fieldType == rawValueType { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} - offset += t.length - v.(*reflect.StructValue).Set(reflect.NewValue(result).(*reflect.StructValue)) - return - } - - // Deal with the ANY type. - if ifaceType, ok := fieldType.(*reflect.InterfaceType); ok && ifaceType.NumMethod() == 0 { - ifaceValue := v.(*reflect.InterfaceValue) - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - var result interface{} - if !t.isCompound && t.class == classUniversal { - innerBytes := bytes[offset : offset+t.length] - switch t.tag { - case tagPrintableString: - result, err = parsePrintableString(innerBytes) - case tagIA5String: - result, err = parseIA5String(innerBytes) - case tagT61String: - result, err = parseT61String(innerBytes) - case tagInteger: - result, err = parseInt64(innerBytes) - case tagBitString: - result, err = parseBitString(innerBytes) - case tagOID: - result, err = parseObjectIdentifier(innerBytes) - case tagUTCTime: - result, err = parseUTCTime(innerBytes) - case tagOctetString: - result = innerBytes - default: - // If we don't know how to handle the type, we just leave Value as nil. - } - } - offset += t.length - if err != nil { - return - } - if result != nil { - ifaceValue.Set(reflect.NewValue(result)) - } - return - } - universalTag, compoundType, ok1 := getUniversalType(fieldType) - if !ok1 { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} - return - } - - t, offset, err := parseTagAndLength(bytes, offset) - if err != nil { - return - } - if params.explicit { - expectedClass := classContextSpecific - if params.application { - expectedClass = classApplication - } - if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { - if t.length > 0 { - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - } else { - if fieldType != flagType { - err = StructuralError{"Zero length explicit tag was not an asn1.Flag"} - return - } - - flagValue := v.(*reflect.BoolValue) - flagValue.Set(true) - return - } - } else { - // The tags didn't match, it might be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{"explicitly tagged member didn't match"} - } - return - } - } - - // Special case for strings: PrintableString and IA5String both map to - // the Go type string. getUniversalType returns the tag for - // PrintableString when it sees a string so, if we see an IA5String on - // the wire, we change the universal type to match. - if universalTag == tagPrintableString && t.tag == tagIA5String { - universalTag = tagIA5String - } - // Likewise for GeneralString - if universalTag == tagPrintableString && t.tag == tagGeneralString { - universalTag = tagGeneralString - } - - // Special case for time: UTCTime and GeneralizedTime both map to the - // Go type time.Time. - if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { - universalTag = tagGeneralizedTime - } - - expectedClass := classUniversal - expectedTag := universalTag - - if !params.explicit && params.tag != nil { - expectedClass = classContextSpecific - expectedTag = *params.tag - } - - if !params.explicit && params.application && params.tag != nil { - expectedClass = classApplication - expectedTag = *params.tag - } - - // We have unwrapped any explicit tagging at this point. - if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { - // Tags don't match. Again, it could be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} - } - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - innerBytes := bytes[offset : offset+t.length] - offset += t.length - - // We deal with the structures defined in this package first. - switch fieldType { - case objectIdentifierType: - newSlice, err1 := parseObjectIdentifier(innerBytes) - sliceValue := v.(*reflect.SliceValue) - sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice))) - if err1 == nil { - reflect.Copy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue)) - } - err = err1 - return - case bitStringType: - structValue := v.(*reflect.StructValue) - bs, err1 := parseBitString(innerBytes) - if err1 == nil { - structValue.Set(reflect.NewValue(bs).(*reflect.StructValue)) - } - err = err1 - return - case timeType: - ptrValue := v.(*reflect.PtrValue) - var time *time.Time - var err1 os.Error - if universalTag == tagUTCTime { - time, err1 = parseUTCTime(innerBytes) - } else { - time, err1 = parseGeneralizedTime(innerBytes) - } - if err1 == nil { - ptrValue.Set(reflect.NewValue(time).(*reflect.PtrValue)) - } - err = err1 - return - case enumeratedType: - parsedInt, err1 := parseInt(innerBytes) - enumValue := v.(*reflect.IntValue) - if err1 == nil { - enumValue.Set(int64(parsedInt)) - } - err = err1 - return - case flagType: - flagValue := v.(*reflect.BoolValue) - flagValue.Set(true) - return - } - switch val := v.(type) { - case *reflect.BoolValue: - parsedBool, err1 := parseBool(innerBytes) - if err1 == nil { - val.Set(parsedBool) - } - err = err1 - return - case *reflect.IntValue: - switch val.Type().Kind() { - case reflect.Int: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - val.Set(int64(parsedInt)) - } - err = err1 - return - case reflect.Int64: - parsedInt, err1 := parseInt64(innerBytes) - if err1 == nil { - val.Set(parsedInt) - } - err = err1 - return - } - case *reflect.StructValue: - structType := fieldType.(*reflect.StructType) - - if structType.NumField() > 0 && - structType.Field(0).Type == rawContentsType { - bytes := bytes[initOffset:offset] - val.Field(0).SetValue(reflect.NewValue(RawContent(bytes))) - } - - innerOffset := 0 - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if i == 0 && field.Type == rawContentsType { - continue - } - innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag)) - if err != nil { - return - } - } - // We allow extra bytes at the end of the SEQUENCE because - // adding elements to the end has been used in X.509 as the - // version numbers have increased. - return - case *reflect.SliceValue: - sliceType := fieldType.(*reflect.SliceType) - if sliceType.Elem().Kind() == reflect.Uint8 { - val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) - reflect.Copy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue)) - return - } - newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) - if err1 == nil { - val.Set(newSlice) - } - err = err1 - return - case *reflect.StringValue: - var v string - switch universalTag { - case tagPrintableString: - v, err = parsePrintableString(innerBytes) - case tagIA5String: - v, err = parseIA5String(innerBytes) - case tagT61String: - v, err = parseT61String(innerBytes) - case tagGeneralString: - // GeneralString is specified in ISO-2022/ECMA-35, - // A brief review suggests that it includes structures - // that allow the encoding to change midstring and - // such. We give up and pass it as an 8-bit string. - v, err = parseT61String(innerBytes) - default: - err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} - } - if err == nil { - val.Set(v) - } - return - } - err = StructuralError{"unknown Go type"} - return -} - -// setDefaultValue is used to install a default value, from a tag string, into -// a Value. It is successful is the field was optional, even if a default value -// wasn't provided or it failed to install it into the Value. -func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { - if !params.optional { - return - } - ok = true - if params.defaultValue == nil { - return - } - switch val := v.(type) { - case *reflect.IntValue: - val.Set(*params.defaultValue) - } - return -} - -// Unmarshal parses the DER-encoded ASN.1 data structure b -// and uses the reflect package to fill in an arbitrary value pointed at by val. -// Because Unmarshal uses the reflect package, the structs -// being written to must use upper case field names. -// -// An ASN.1 INTEGER can be written to an int or int64. -// If the encoded value does not fit in the Go type, -// Unmarshal returns a parse error. -// -// An ASN.1 BIT STRING can be written to a BitString. -// -// An ASN.1 OCTET STRING can be written to a []byte. -// -// An ASN.1 OBJECT IDENTIFIER can be written to an -// ObjectIdentifier. -// -// An ASN.1 ENUMERATED can be written to an Enumerated. -// -// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time. -// -// An ASN.1 PrintableString or IA5String can be written to a string. -// -// Any of the above ASN.1 values can be written to an interface{}. -// The value stored in the interface has the corresponding Go type. -// For integers, that type is int64. -// -// An ASN.1 SEQUENCE OF x or SET OF x can be written -// to a slice if an x can be written to the slice's element type. -// -// An ASN.1 SEQUENCE or SET can be written to a struct -// if each of the elements in the sequence can be -// written to the corresponding element in the struct. -// -// The following tags on struct fields have special meaning to Unmarshal: -// -// optional marks the field as ASN.1 OPTIONAL -// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC -// default:x sets the default value for optional integer fields -// -// If the type of the first field of a structure is RawContent then the raw -// ASN1 contents of the struct will be stored in it. -// -// Other ASN.1 types are not supported; if it encounters them, -// Unmarshal returns a parse error. -func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) { - return UnmarshalWithParams(b, val, "") -} - -// UnmarshalWithParams allows field parameters to be specified for the -// top-level element. The form of the params is the same as the field tags. -func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) { - v := reflect.NewValue(val).(*reflect.PtrValue).Elem() - offset, err := parseField(v, b, 0, parseFieldParameters(params)) - if err != nil { - return nil, err - } - return b[offset:], nil -} diff --git a/src/cmd/fix/testdata/reflect.asn1.go.out b/src/cmd/fix/testdata/reflect.asn1.go.out deleted file mode 100644 index ba6224e6df..0000000000 --- a/src/cmd/fix/testdata/reflect.asn1.go.out +++ /dev/null @@ -1,814 +0,0 @@ -// 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. - -// The asn1 package implements parsing of DER-encoded ASN.1 data structures, -// as defined in ITU-T Rec X.690. -// -// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' -// http://luca.ntop.org/Teaching/Appunti/asn1.html. -package asn1 - -// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc -// are different encoding formats for those objects. Here, we'll be dealing -// with DER, the Distinguished Encoding Rules. DER is used in X.509 because -// it's fast to parse and, unlike BER, has a unique encoding for every object. -// When calculating hashes over objects, it's important that the resulting -// bytes be the same at both ends and DER removes this margin of error. -// -// ASN.1 is very complex and this package doesn't attempt to implement -// everything by any means. - -import ( - "fmt" - "os" - "reflect" - "time" -) - -// A StructuralError suggests that the ASN.1 data is valid, but the Go type -// which is receiving it doesn't match. -type StructuralError struct { - Msg string -} - -func (e StructuralError) String() string { return "ASN.1 structure error: " + e.Msg } - -// A SyntaxError suggests that the ASN.1 data is invalid. -type SyntaxError struct { - Msg string -} - -func (e SyntaxError) String() string { return "ASN.1 syntax error: " + e.Msg } - -// We start by dealing with each of the primitive types in turn. - -// BOOLEAN - -func parseBool(bytes []byte) (ret bool, err os.Error) { - if len(bytes) != 1 { - err = SyntaxError{"invalid boolean"} - return - } - - return bytes[0] != 0, nil -} - -// INTEGER - -// parseInt64 treats the given bytes as a big-endian, signed integer and -// returns the result. -func parseInt64(bytes []byte) (ret int64, err os.Error) { - if len(bytes) > 8 { - // We'll overflow an int64 in this case. - err = StructuralError{"integer too large"} - return - } - for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { - ret <<= 8 - ret |= int64(bytes[bytesRead]) - } - - // Shift up and down in order to sign extend the result. - ret <<= 64 - uint8(len(bytes))*8 - ret >>= 64 - uint8(len(bytes))*8 - return -} - -// parseInt treats the given bytes as a big-endian, signed integer and returns -// the result. -func parseInt(bytes []byte) (int, os.Error) { - ret64, err := parseInt64(bytes) - if err != nil { - return 0, err - } - if ret64 != int64(int(ret64)) { - return 0, StructuralError{"integer too large"} - } - return int(ret64), nil -} - -// BIT STRING - -// BitString is the structure to use when you want an ASN.1 BIT STRING type. A -// bit string is padded up to the nearest byte in memory and the number of -// valid bits is recorded. Padding bits will be zero. -type BitString struct { - Bytes []byte // bits packed into bytes. - BitLength int // length in bits. -} - -// At returns the bit at the given index. If the index is out of range it -// returns false. -func (b BitString) At(i int) int { - if i < 0 || i >= b.BitLength { - return 0 - } - x := i / 8 - y := 7 - uint(i%8) - return int(b.Bytes[x]>>y) & 1 -} - -// RightAlign returns a slice where the padding bits are at the beginning. The -// slice may share memory with the BitString. -func (b BitString) RightAlign() []byte { - shift := uint(8 - (b.BitLength % 8)) - if shift == 8 || len(b.Bytes) == 0 { - return b.Bytes - } - - a := make([]byte, len(b.Bytes)) - a[0] = b.Bytes[0] >> shift - for i := 1; i < len(b.Bytes); i++ { - a[i] = b.Bytes[i-1] << (8 - shift) - a[i] |= b.Bytes[i] >> shift - } - - return a -} - -// parseBitString parses an ASN.1 bit string from the given byte array and returns it. -func parseBitString(bytes []byte) (ret BitString, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length BIT STRING"} - return - } - paddingBits := int(bytes[0]) - if paddingBits > 7 || - len(bytes) == 1 && paddingBits > 0 || - bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 { - err = SyntaxError{"invalid padding bits in BIT STRING"} - return - } - ret.BitLength = (len(bytes)-1)*8 - paddingBits - ret.Bytes = bytes[1:] - return -} - -// OBJECT IDENTIFIER - -// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER. -type ObjectIdentifier []int - -// Equal returns true iff oi and other represent the same identifier. -func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool { - if len(oi) != len(other) { - return false - } - for i := 0; i < len(oi); i++ { - if oi[i] != other[i] { - return false - } - } - - return true -} - -// parseObjectIdentifier parses an OBJECT IDENTIFER from the given bytes and -// returns it. An object identifer is a sequence of variable length integers -// that are assigned in a hierarachy. -func parseObjectIdentifier(bytes []byte) (s []int, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length OBJECT IDENTIFIER"} - return - } - - // In the worst case, we get two elements from the first byte (which is - // encoded differently) and then every varint is a single byte long. - s = make([]int, len(bytes)+1) - - // The first byte is 40*value1 + value2: - s[0] = int(bytes[0]) / 40 - s[1] = int(bytes[0]) % 40 - i := 2 - for offset := 1; offset < len(bytes); i++ { - var v int - v, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - s[i] = v - } - s = s[0:i] - return -} - -// ENUMERATED - -// An Enumerated is represented as a plain int. -type Enumerated int - -// FLAG - -// A Flag accepts any data and is set to true if present. -type Flag bool - -// parseBase128Int parses a base-128 encoded int from the given offset in the -// given byte array. It returns the value and the new offset. -func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err os.Error) { - offset = initOffset - for shifted := 0; offset < len(bytes); shifted++ { - if shifted > 4 { - err = StructuralError{"base 128 integer too large"} - return - } - ret <<= 7 - b := bytes[offset] - ret |= int(b & 0x7f) - offset++ - if b&0x80 == 0 { - return - } - } - err = SyntaxError{"truncated base 128 integer"} - return -} - -// UTCTime - -func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) { - s := string(bytes) - ret, err = time.Parse("0601021504Z0700", s) - if err == nil { - return - } - ret, err = time.Parse("060102150405Z0700", s) - return -} - -// parseGeneralizedTime parses the GeneralizedTime from the given byte array -// and returns the resulting time. -func parseGeneralizedTime(bytes []byte) (ret *time.Time, err os.Error) { - return time.Parse("20060102150405Z0700", string(bytes)) -} - -// PrintableString - -// parsePrintableString parses a ASN.1 PrintableString from the given byte -// array and returns it. -func parsePrintableString(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if !isPrintable(b) { - err = SyntaxError{"PrintableString contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// isPrintable returns true iff the given b is in the ASN.1 PrintableString set. -func isPrintable(b byte) bool { - return 'a' <= b && b <= 'z' || - 'A' <= b && b <= 'Z' || - '0' <= b && b <= '9' || - '\'' <= b && b <= ')' || - '+' <= b && b <= '/' || - b == ' ' || - b == ':' || - b == '=' || - b == '?' || - // This is techincally not allowed in a PrintableString. - // However, x509 certificates with wildcard strings don't - // always use the correct string type so we permit it. - b == '*' -} - -// IA5String - -// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given -// byte array and returns it. -func parseIA5String(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if b >= 0x80 { - err = SyntaxError{"IA5String contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// T61String - -// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given -// byte array and returns it. -func parseT61String(bytes []byte) (ret string, err os.Error) { - return string(bytes), nil -} - -// A RawValue represents an undecoded ASN.1 object. -type RawValue struct { - Class, Tag int - IsCompound bool - Bytes []byte - FullBytes []byte // includes the tag and length -} - -// RawContent is used to signal that the undecoded, DER data needs to be -// preserved for a struct. To use it, the first field of the struct must have -// this type. It's an error for any of the other fields to have this type. -type RawContent []byte - -// Tagging - -// parseTagAndLength parses an ASN.1 tag and length pair from the given offset -// into a byte array. It returns the parsed data and the new offset. SET and -// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we -// don't distinguish between ordered and unordered objects in this code. -func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err os.Error) { - offset = initOffset - b := bytes[offset] - offset++ - ret.class = int(b >> 6) - ret.isCompound = b&0x20 == 0x20 - ret.tag = int(b & 0x1f) - - // If the bottom five bits are set, then the tag number is actually base 128 - // encoded afterwards - if ret.tag == 0x1f { - ret.tag, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - } - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - if b&0x80 == 0 { - // The length is encoded in the bottom 7 bits. - ret.length = int(b & 0x7f) - } else { - // Bottom 7 bits give the number of length bytes to follow. - numBytes := int(b & 0x7f) - // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. - if numBytes > 3 { - err = StructuralError{"length too large"} - return - } - if numBytes == 0 { - err = SyntaxError{"indefinite length found (not DER)"} - return - } - ret.length = 0 - for i := 0; i < numBytes; i++ { - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - ret.length <<= 8 - ret.length |= int(b) - } - } - - return -} - -// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse -// a number of ASN.1 values from the given byte array and returns them as a -// slice of Go values of the given type. -func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) { - expectedTag, compoundType, ok := getUniversalType(elemType) - if !ok { - err = StructuralError{"unknown Go type for slice"} - return - } - - // First we iterate over the input and count the number of elements, - // checking that the types are correct in each case. - numElements := 0 - for offset := 0; offset < len(bytes); { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so - // that a sequence of them can be parsed into a []string. - if t.tag == tagGeneralString { - t.tag = tagPrintableString - } - if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { - err = StructuralError{"sequence tag mismatch"} - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"truncated sequence"} - return - } - offset += t.length - numElements++ - } - ret = reflect.MakeSlice(sliceType, numElements, numElements) - params := fieldParameters{} - offset := 0 - for i := 0; i < numElements; i++ { - offset, err = parseField(ret.Index(i), bytes, offset, params) - if err != nil { - return - } - } - return -} - -var ( - bitStringType = reflect.TypeOf(BitString{}) - objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) - enumeratedType = reflect.TypeOf(Enumerated(0)) - flagType = reflect.TypeOf(Flag(false)) - timeType = reflect.TypeOf(&time.Time{}) - rawValueType = reflect.TypeOf(RawValue{}) - rawContentsType = reflect.TypeOf(RawContent(nil)) -) - -// invalidLength returns true iff offset + length > sliceLength, or if the -// addition would overflow. -func invalidLength(offset, length, sliceLength int) bool { - return offset+length < offset || offset+length > sliceLength -} - -// parseField is the main parsing function. Given a byte array and an offset -// into the array, it will try to parse a suitable ASN.1 value out and store it -// in the given Value. -func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err os.Error) { - offset = initOffset - fieldType := v.Type() - - // If we have run out of data, it may be that there are optional elements at the end. - if offset == len(bytes) { - if !setDefaultValue(v, params) { - err = SyntaxError{"sequence truncated"} - } - return - } - - // Deal with raw values. - if fieldType == rawValueType { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} - offset += t.length - v.Set(reflect.ValueOf(result)) - return - } - - // Deal with the ANY type. - if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { - ifaceValue := v - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - var result interface{} - if !t.isCompound && t.class == classUniversal { - innerBytes := bytes[offset : offset+t.length] - switch t.tag { - case tagPrintableString: - result, err = parsePrintableString(innerBytes) - case tagIA5String: - result, err = parseIA5String(innerBytes) - case tagT61String: - result, err = parseT61String(innerBytes) - case tagInteger: - result, err = parseInt64(innerBytes) - case tagBitString: - result, err = parseBitString(innerBytes) - case tagOID: - result, err = parseObjectIdentifier(innerBytes) - case tagUTCTime: - result, err = parseUTCTime(innerBytes) - case tagOctetString: - result = innerBytes - default: - // If we don't know how to handle the type, we just leave Value as nil. - } - } - offset += t.length - if err != nil { - return - } - if result != nil { - ifaceValue.Set(reflect.ValueOf(result)) - } - return - } - universalTag, compoundType, ok1 := getUniversalType(fieldType) - if !ok1 { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} - return - } - - t, offset, err := parseTagAndLength(bytes, offset) - if err != nil { - return - } - if params.explicit { - expectedClass := classContextSpecific - if params.application { - expectedClass = classApplication - } - if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { - if t.length > 0 { - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - } else { - if fieldType != flagType { - err = StructuralError{"Zero length explicit tag was not an asn1.Flag"} - return - } - - flagValue := v - flagValue.SetBool(true) - return - } - } else { - // The tags didn't match, it might be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{"explicitly tagged member didn't match"} - } - return - } - } - - // Special case for strings: PrintableString and IA5String both map to - // the Go type string. getUniversalType returns the tag for - // PrintableString when it sees a string so, if we see an IA5String on - // the wire, we change the universal type to match. - if universalTag == tagPrintableString && t.tag == tagIA5String { - universalTag = tagIA5String - } - // Likewise for GeneralString - if universalTag == tagPrintableString && t.tag == tagGeneralString { - universalTag = tagGeneralString - } - - // Special case for time: UTCTime and GeneralizedTime both map to the - // Go type time.Time. - if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { - universalTag = tagGeneralizedTime - } - - expectedClass := classUniversal - expectedTag := universalTag - - if !params.explicit && params.tag != nil { - expectedClass = classContextSpecific - expectedTag = *params.tag - } - - if !params.explicit && params.application && params.tag != nil { - expectedClass = classApplication - expectedTag = *params.tag - } - - // We have unwrapped any explicit tagging at this point. - if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { - // Tags don't match. Again, it could be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} - } - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - innerBytes := bytes[offset : offset+t.length] - offset += t.length - - // We deal with the structures defined in this package first. - switch fieldType { - case objectIdentifierType: - newSlice, err1 := parseObjectIdentifier(innerBytes) - sliceValue := v - sliceValue.Set(reflect.MakeSlice(sliceValue.Type(), len(newSlice), len(newSlice))) - if err1 == nil { - reflect.Copy(sliceValue, reflect.ValueOf(newSlice)) - } - err = err1 - return - case bitStringType: - structValue := v - bs, err1 := parseBitString(innerBytes) - if err1 == nil { - structValue.Set(reflect.ValueOf(bs)) - } - err = err1 - return - case timeType: - ptrValue := v - var time *time.Time - var err1 os.Error - if universalTag == tagUTCTime { - time, err1 = parseUTCTime(innerBytes) - } else { - time, err1 = parseGeneralizedTime(innerBytes) - } - if err1 == nil { - ptrValue.Set(reflect.ValueOf(time)) - } - err = err1 - return - case enumeratedType: - parsedInt, err1 := parseInt(innerBytes) - enumValue := v - if err1 == nil { - enumValue.SetInt(int64(parsedInt)) - } - err = err1 - return - case flagType: - flagValue := v - flagValue.SetBool(true) - return - } - switch val := v; val.Kind() { - case reflect.Bool: - parsedBool, err1 := parseBool(innerBytes) - if err1 == nil { - val.SetBool(parsedBool) - } - err = err1 - return - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - switch val.Type().Kind() { - case reflect.Int: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - val.SetInt(int64(parsedInt)) - } - err = err1 - return - case reflect.Int64: - parsedInt, err1 := parseInt64(innerBytes) - if err1 == nil { - val.SetInt(parsedInt) - } - err = err1 - return - } - case reflect.Struct: - structType := fieldType - - if structType.NumField() > 0 && - structType.Field(0).Type == rawContentsType { - bytes := bytes[initOffset:offset] - val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) - } - - innerOffset := 0 - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if i == 0 && field.Type == rawContentsType { - continue - } - innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag)) - if err != nil { - return - } - } - // We allow extra bytes at the end of the SEQUENCE because - // adding elements to the end has been used in X.509 as the - // version numbers have increased. - return - case reflect.Slice: - sliceType := fieldType - if sliceType.Elem().Kind() == reflect.Uint8 { - val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) - reflect.Copy(val, reflect.ValueOf(innerBytes)) - return - } - newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) - if err1 == nil { - val.Set(newSlice) - } - err = err1 - return - case reflect.String: - var v string - switch universalTag { - case tagPrintableString: - v, err = parsePrintableString(innerBytes) - case tagIA5String: - v, err = parseIA5String(innerBytes) - case tagT61String: - v, err = parseT61String(innerBytes) - case tagGeneralString: - // GeneralString is specified in ISO-2022/ECMA-35, - // A brief review suggests that it includes structures - // that allow the encoding to change midstring and - // such. We give up and pass it as an 8-bit string. - v, err = parseT61String(innerBytes) - default: - err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} - } - if err == nil { - val.SetString(v) - } - return - } - err = StructuralError{"unknown Go type"} - return -} - -// setDefaultValue is used to install a default value, from a tag string, into -// a Value. It is successful is the field was optional, even if a default value -// wasn't provided or it failed to install it into the Value. -func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { - if !params.optional { - return - } - ok = true - if params.defaultValue == nil { - return - } - switch val := v; val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val.SetInt(*params.defaultValue) - } - return -} - -// Unmarshal parses the DER-encoded ASN.1 data structure b -// and uses the reflect package to fill in an arbitrary value pointed at by val. -// Because Unmarshal uses the reflect package, the structs -// being written to must use upper case field names. -// -// An ASN.1 INTEGER can be written to an int or int64. -// If the encoded value does not fit in the Go type, -// Unmarshal returns a parse error. -// -// An ASN.1 BIT STRING can be written to a BitString. -// -// An ASN.1 OCTET STRING can be written to a []byte. -// -// An ASN.1 OBJECT IDENTIFIER can be written to an -// ObjectIdentifier. -// -// An ASN.1 ENUMERATED can be written to an Enumerated. -// -// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time. -// -// An ASN.1 PrintableString or IA5String can be written to a string. -// -// Any of the above ASN.1 values can be written to an interface{}. -// The value stored in the interface has the corresponding Go type. -// For integers, that type is int64. -// -// An ASN.1 SEQUENCE OF x or SET OF x can be written -// to a slice if an x can be written to the slice's element type. -// -// An ASN.1 SEQUENCE or SET can be written to a struct -// if each of the elements in the sequence can be -// written to the corresponding element in the struct. -// -// The following tags on struct fields have special meaning to Unmarshal: -// -// optional marks the field as ASN.1 OPTIONAL -// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC -// default:x sets the default value for optional integer fields -// -// If the type of the first field of a structure is RawContent then the raw -// ASN1 contents of the struct will be stored in it. -// -// Other ASN.1 types are not supported; if it encounters them, -// Unmarshal returns a parse error. -func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) { - return UnmarshalWithParams(b, val, "") -} - -// UnmarshalWithParams allows field parameters to be specified for the -// top-level element. The form of the params is the same as the field tags. -func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) { - v := reflect.ValueOf(val).Elem() - offset, err := parseField(v, b, 0, parseFieldParameters(params)) - if err != nil { - return nil, err - } - return b[offset:], nil -} diff --git a/src/cmd/fix/testdata/reflect.datafmt.go.in b/src/cmd/fix/testdata/reflect.datafmt.go.in deleted file mode 100644 index 91f885f9a3..0000000000 --- a/src/cmd/fix/testdata/reflect.datafmt.go.in +++ /dev/null @@ -1,710 +0,0 @@ -// 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. - -/* The datafmt package implements syntax-directed, type-driven formatting - of arbitrary data structures. Formatting a data structure consists of - two phases: first, a parser reads a format specification and builds a - "compiled" format. Then, the format can be applied repeatedly to - arbitrary values. Applying a format to a value evaluates to a []byte - containing the formatted value bytes, or nil. - - A format specification is a set of package declarations and format rules: - - Format = [ Entry { ";" Entry } [ ";" ] ] . - Entry = PackageDecl | FormatRule . - - (The syntax of a format specification is presented in the same EBNF - notation as used in the Go language specification. The syntax of white - space, comments, identifiers, and string literals is the same as in Go.) - - A package declaration binds a package name (such as 'ast') to a - package import path (such as '"go/ast"'). Each package used (in - a type name, see below) must be declared once before use. - - PackageDecl = PackageName ImportPath . - PackageName = identifier . - ImportPath = string . - - A format rule binds a rule name to a format expression. A rule name - may be a type name or one of the special names 'default' or '/'. - A type name may be the name of a predeclared type (for example, 'int', - 'float32', etc.), the package-qualified name of a user-defined type - (for example, 'ast.MapType'), or an identifier indicating the structure - of unnamed composite types ('array', 'chan', 'func', 'interface', 'map', - or 'ptr'). Each rule must have a unique name; rules can be declared in - any order. - - FormatRule = RuleName "=" Expression . - RuleName = TypeName | "default" | "/" . - TypeName = [ PackageName "." ] identifier . - - To format a value, the value's type name is used to select the format rule - (there is an override mechanism, see below). The format expression of the - selected rule specifies how the value is formatted. Each format expression, - when applied to a value, evaluates to a byte sequence or nil. - - In its most general form, a format expression is a list of alternatives, - each of which is a sequence of operands: - - Expression = [ Sequence ] { "|" [ Sequence ] } . - Sequence = Operand { Operand } . - - The formatted result produced by an expression is the result of the first - alternative sequence that evaluates to a non-nil result; if there is no - such alternative, the expression evaluates to nil. The result produced by - an operand sequence is the concatenation of the results of its operands. - If any operand in the sequence evaluates to nil, the entire sequence - evaluates to nil. - - There are five kinds of operands: - - Operand = Literal | Field | Group | Option | Repetition . - - Literals evaluate to themselves, with two substitutions. First, - %-formats expand in the manner of fmt.Printf, with the current value - passed as the parameter. Second, the current indentation (see below) - is inserted after every newline or form feed character. - - Literal = string . - - This table shows string literals applied to the value 42 and the - corresponding formatted result: - - "foo" foo - "%x" 2a - "x = %d" x = 42 - "%#x = %d" 0x2a = 42 - - A field operand is a field name optionally followed by an alternate - rule name. The field name may be an identifier or one of the special - names @ or *. - - Field = FieldName [ ":" RuleName ] . - FieldName = identifier | "@" | "*" . - - If the field name is an identifier, the current value must be a struct, - and there must be a field with that name in the struct. The same lookup - rules apply as in the Go language (for instance, the name of an anonymous - field is the unqualified type name). The field name denotes the field - value in the struct. If the field is not found, formatting is aborted - and an error message is returned. (TODO consider changing the semantics - such that if a field is not found, it evaluates to nil). - - The special name '@' denotes the current value. - - The meaning of the special name '*' depends on the type of the current - value: - - array, slice types array, slice element (inside {} only, see below) - interfaces value stored in interface - pointers value pointed to by pointer - - (Implementation restriction: channel, function and map types are not - supported due to missing reflection support). - - Fields are evaluated as follows: If the field value is nil, or an array - or slice element does not exist, the result is nil (see below for details - on array/slice elements). If the value is not nil the field value is - formatted (recursively) using the rule corresponding to its type name, - or the alternate rule name, if given. - - The following example shows a complete format specification for a - struct 'myPackage.Point'. Assume the package - - package myPackage // in directory myDir/myPackage - type Point struct { - name string; - x, y int; - } - - Applying the format specification - - myPackage "myDir/myPackage"; - int = "%d"; - hexInt = "0x%x"; - string = "---%s---"; - myPackage.Point = name "{" x ", " y:hexInt "}"; - - to the value myPackage.Point{"foo", 3, 15} results in - - ---foo---{3, 0xf} - - Finally, an operand may be a grouped, optional, or repeated expression. - A grouped expression ("group") groups a more complex expression (body) - so that it can be used in place of a single operand: - - Group = "(" [ Indentation ">>" ] Body ")" . - Indentation = Expression . - Body = Expression . - - A group body may be prefixed by an indentation expression followed by '>>'. - The indentation expression is applied to the current value like any other - expression and the result, if not nil, is appended to the current indentation - during the evaluation of the body (see also formatting state, below). - - An optional expression ("option") is enclosed in '[]' brackets. - - Option = "[" Body "]" . - - An option evaluates to its body, except that if the body evaluates to nil, - the option expression evaluates to an empty []byte. Thus an option's purpose - is to protect the expression containing the option from a nil operand. - - A repeated expression ("repetition") is enclosed in '{}' braces. - - Repetition = "{" Body [ "/" Separator ] "}" . - Separator = Expression . - - A repeated expression is evaluated as follows: The body is evaluated - repeatedly and its results are concatenated until the body evaluates - to nil. The result of the repetition is the (possibly empty) concatenation, - but it is never nil. An implicit index is supplied for the evaluation of - the body: that index is used to address elements of arrays or slices. If - the corresponding elements do not exist, the field denoting the element - evaluates to nil (which in turn may terminate the repetition). - - The body of a repetition may be followed by a '/' and a "separator" - expression. If the separator is present, it is invoked between repetitions - of the body. - - The following example shows a complete format specification for formatting - a slice of unnamed type. Applying the specification - - int = "%b"; - array = { * / ", " }; // array is the type name for an unnamed slice - - to the value '[]int{2, 3, 5, 7}' results in - - 10, 11, 101, 111 - - Default rule: If a format rule named 'default' is present, it is used for - formatting a value if no other rule was found. A common default rule is - - default = "%v" - - to provide default formatting for basic types without having to specify - a specific rule for each basic type. - - Global separator rule: If a format rule named '/' is present, it is - invoked with the current value between literals. If the separator - expression evaluates to nil, it is ignored. - - For instance, a global separator rule may be used to punctuate a sequence - of values with commas. The rules: - - default = "%v"; - / = ", "; - - will format an argument list by printing each one in its default format, - separated by a comma and a space. -*/ -package datafmt - -import ( - "bytes" - "fmt" - "go/token" - "io" - "os" - "reflect" - "runtime" -) - -// ---------------------------------------------------------------------------- -// Format representation - -// Custom formatters implement the Formatter function type. -// A formatter is invoked with the current formatting state, the -// value to format, and the rule name under which the formatter -// was installed (the same formatter function may be installed -// under different names). The formatter may access the current state -// to guide formatting and use State.Write to append to the state's -// output. -// -// A formatter must return a boolean value indicating if it evaluated -// to a non-nil value (true), or a nil value (false). -// -type Formatter func(state *State, value interface{}, ruleName string) bool - -// A FormatterMap is a set of custom formatters. -// It maps a rule name to a formatter function. -// -type FormatterMap map[string]Formatter - -// A parsed format expression is built from the following nodes. -// -type ( - expr interface{} - - alternatives []expr // x | y | z - - sequence []expr // x y z - - literal [][]byte // a list of string segments, possibly starting with '%' - - field struct { - fieldName string // including "@", "*" - ruleName string // "" if no rule name specified - } - - group struct { - indent, body expr // (indent >> body) - } - - option struct { - body expr // [body] - } - - repetition struct { - body, separator expr // {body / separator} - } - - custom struct { - ruleName string - fun Formatter - } -) - -// A Format is the result of parsing a format specification. -// The format may be applied repeatedly to format values. -// -type Format map[string]expr - -// ---------------------------------------------------------------------------- -// Formatting - -// An application-specific environment may be provided to Format.Apply; -// the environment is available inside custom formatters via State.Env(). -// Environments must implement copying; the Copy method must return an -// complete copy of the receiver. This is necessary so that the formatter -// can save and restore an environment (in case of an absent expression). -// -// If the Environment doesn't change during formatting (this is under -// control of the custom formatters), the Copy function can simply return -// the receiver, and thus can be very light-weight. -// -type Environment interface { - Copy() Environment -} - -// State represents the current formatting state. -// It is provided as argument to custom formatters. -// -type State struct { - fmt Format // format in use - env Environment // user-supplied environment - errors chan os.Error // not chan *Error (errors <- nil would be wrong!) - hasOutput bool // true after the first literal has been written - indent bytes.Buffer // current indentation - output bytes.Buffer // format output - linePos token.Position // position of line beginning (Column == 0) - default_ expr // possibly nil - separator expr // possibly nil -} - -func newState(fmt Format, env Environment, errors chan os.Error) *State { - s := new(State) - s.fmt = fmt - s.env = env - s.errors = errors - s.linePos = token.Position{Line: 1} - - // if we have a default rule, cache it's expression for fast access - if x, found := fmt["default"]; found { - s.default_ = x - } - - // if we have a global separator rule, cache it's expression for fast access - if x, found := fmt["/"]; found { - s.separator = x - } - - return s -} - -// Env returns the environment passed to Format.Apply. -func (s *State) Env() interface{} { return s.env } - -// LinePos returns the position of the current line beginning -// in the state's output buffer. Line numbers start at 1. -// -func (s *State) LinePos() token.Position { return s.linePos } - -// Pos returns the position of the next byte to be written to the -// output buffer. Line numbers start at 1. -// -func (s *State) Pos() token.Position { - offs := s.output.Len() - return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs} -} - -// Write writes data to the output buffer, inserting the indentation -// string after each newline or form feed character. It cannot return an error. -// -func (s *State) Write(data []byte) (int, os.Error) { - n := 0 - i0 := 0 - for i, ch := range data { - if ch == '\n' || ch == '\f' { - // write text segment and indentation - n1, _ := s.output.Write(data[i0 : i+1]) - n2, _ := s.output.Write(s.indent.Bytes()) - n += n1 + n2 - i0 = i + 1 - s.linePos.Offset = s.output.Len() - s.linePos.Line++ - } - } - n3, _ := s.output.Write(data[i0:]) - return n + n3, nil -} - -type checkpoint struct { - env Environment - hasOutput bool - outputLen int - linePos token.Position -} - -func (s *State) save() checkpoint { - saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos} - if s.env != nil { - saved.env = s.env.Copy() - } - return saved -} - -func (s *State) restore(m checkpoint) { - s.env = m.env - s.output.Truncate(m.outputLen) -} - -func (s *State) error(msg string) { - s.errors <- os.NewError(msg) - runtime.Goexit() -} - -// TODO At the moment, unnamed types are simply mapped to the default -// names below. For instance, all unnamed arrays are mapped to -// 'array' which is not really sufficient. Eventually one may want -// to be able to specify rules for say an unnamed slice of T. -// - -func typename(typ reflect.Type) string { - switch typ.(type) { - case *reflect.ArrayType: - return "array" - case *reflect.SliceType: - return "array" - case *reflect.ChanType: - return "chan" - case *reflect.FuncType: - return "func" - case *reflect.InterfaceType: - return "interface" - case *reflect.MapType: - return "map" - case *reflect.PtrType: - return "ptr" - } - return typ.String() -} - -func (s *State) getFormat(name string) expr { - if fexpr, found := s.fmt[name]; found { - return fexpr - } - - if s.default_ != nil { - return s.default_ - } - - s.error(fmt.Sprintf("no format rule for type: '%s'", name)) - return nil -} - -// eval applies a format expression fexpr to a value. If the expression -// evaluates internally to a non-nil []byte, that slice is appended to -// the state's output buffer and eval returns true. Otherwise, eval -// returns false and the state remains unchanged. -// -func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { - // an empty format expression always evaluates - // to a non-nil (but empty) []byte - if fexpr == nil { - return true - } - - switch t := fexpr.(type) { - case alternatives: - // append the result of the first alternative that evaluates to - // a non-nil []byte to the state's output - mark := s.save() - for _, x := range t { - if s.eval(x, value, index) { - return true - } - s.restore(mark) - } - return false - - case sequence: - // append the result of all operands to the state's output - // unless a nil result is encountered - mark := s.save() - for _, x := range t { - if !s.eval(x, value, index) { - s.restore(mark) - return false - } - } - return true - - case literal: - // write separator, if any - if s.hasOutput { - // not the first literal - if s.separator != nil { - sep := s.separator // save current separator - s.separator = nil // and disable it (avoid recursion) - mark := s.save() - if !s.eval(sep, value, index) { - s.restore(mark) - } - s.separator = sep // enable it again - } - } - s.hasOutput = true - // write literal segments - for _, lit := range t { - if len(lit) > 1 && lit[0] == '%' { - // segment contains a %-format at the beginning - if lit[1] == '%' { - // "%%" is printed as a single "%" - s.Write(lit[1:]) - } else { - // use s instead of s.output to get indentation right - fmt.Fprintf(s, string(lit), value.Interface()) - } - } else { - // segment contains no %-formats - s.Write(lit) - } - } - return true // a literal never evaluates to nil - - case *field: - // determine field value - switch t.fieldName { - case "@": - // field value is current value - - case "*": - // indirection: operation is type-specific - switch v := value.(type) { - 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: - s.error("reflection support for maps incomplete") - - case *reflect.PtrValue: - if v.IsNil() { - return false - } - value = v.Elem() - - case *reflect.InterfaceValue: - if v.IsNil() { - return false - } - value = v.Elem() - - case *reflect.ChanValue: - s.error("reflection support for chans incomplete") - - case *reflect.FuncValue: - s.error("reflection support for funcs incomplete") - - default: - s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type())) - } - - default: - // value is value of named field - var field reflect.Value - if sval, ok := value.(*reflect.StructValue); ok { - field = sval.FieldByName(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())) - } - } - value = field - } - - // determine rule - ruleName := t.ruleName - if ruleName == "" { - // no alternate rule name, value type determines rule - ruleName = typename(value.Type()) - } - fexpr = s.getFormat(ruleName) - - mark := s.save() - if !s.eval(fexpr, value, index) { - s.restore(mark) - return false - } - return true - - case *group: - // remember current indentation - indentLen := s.indent.Len() - - // update current indentation - mark := s.save() - s.eval(t.indent, value, index) - // if the indentation evaluates to nil, the state's output buffer - // didn't change - either way it's ok to append the difference to - // the current identation - s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()]) - s.restore(mark) - - // format group body - mark = s.save() - b := true - if !s.eval(t.body, value, index) { - s.restore(mark) - b = false - } - - // reset indentation - s.indent.Truncate(indentLen) - return b - - case *option: - // evaluate the body and append the result to the state's output - // buffer unless the result is nil - mark := s.save() - if !s.eval(t.body, value, 0) { // TODO is 0 index correct? - s.restore(mark) - } - return true // an option never evaluates to nil - - case *repetition: - // evaluate the body and append the result to the state's output - // buffer until a result is nil - for i := 0; ; i++ { - mark := s.save() - // write separator, if any - if i > 0 && t.separator != nil { - // nil result from separator is ignored - mark := s.save() - if !s.eval(t.separator, value, i) { - s.restore(mark) - } - } - if !s.eval(t.body, value, i) { - s.restore(mark) - break - } - } - return true // a repetition never evaluates to nil - - case *custom: - // invoke the custom formatter to obtain the result - mark := s.save() - if !t.fun(s, value.Interface(), t.ruleName) { - s.restore(mark) - return false - } - return true - } - - panic("unreachable") - return false -} - -// Eval formats each argument according to the format -// f and returns the resulting []byte and os.Error. If -// an error occurred, the []byte contains the partially -// formatted result. An environment env may be passed -// in which is available in custom formatters through -// the state parameter. -// -func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) { - if f == nil { - return nil, os.NewError("format is nil") - } - - errors := make(chan os.Error) - s := newState(f, env, errors) - - go func() { - for _, v := range args { - fld := reflect.NewValue(v) - if fld == nil { - errors <- os.NewError("nil argument") - return - } - mark := s.save() - if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct? - s.restore(mark) - } - } - errors <- nil // no errors - }() - - err := <-errors - return s.output.Bytes(), err -} - -// ---------------------------------------------------------------------------- -// Convenience functions - -// Fprint formats each argument according to the format f -// and writes to w. The result is the total number of bytes -// written and an os.Error, if any. -// -func (f Format) Fprint(w io.Writer, env Environment, args ...interface{}) (int, os.Error) { - data, err := f.Eval(env, args...) - if err != nil { - // TODO should we print partial result in case of error? - return 0, err - } - return w.Write(data) -} - -// Print formats each argument according to the format f -// and writes to standard output. The result is the total -// number of bytes written and an os.Error, if any. -// -func (f Format) Print(args ...interface{}) (int, os.Error) { - return f.Fprint(os.Stdout, nil, args...) -} - -// Sprint formats each argument according to the format f -// and returns the resulting string. If an error occurs -// during formatting, the result string contains the -// partially formatted result followed by an error message. -// -func (f Format) Sprint(args ...interface{}) string { - var buf bytes.Buffer - _, err := f.Fprint(&buf, nil, args...) - if err != nil { - var i interface{} = args - fmt.Fprintf(&buf, "--- Sprint(%s) failed: %v", fmt.Sprint(i), err) - } - return buf.String() -} diff --git a/src/cmd/fix/testdata/reflect.datafmt.go.out b/src/cmd/fix/testdata/reflect.datafmt.go.out deleted file mode 100644 index fd447588b0..0000000000 --- a/src/cmd/fix/testdata/reflect.datafmt.go.out +++ /dev/null @@ -1,710 +0,0 @@ -// 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. - -/* The datafmt package implements syntax-directed, type-driven formatting - of arbitrary data structures. Formatting a data structure consists of - two phases: first, a parser reads a format specification and builds a - "compiled" format. Then, the format can be applied repeatedly to - arbitrary values. Applying a format to a value evaluates to a []byte - containing the formatted value bytes, or nil. - - A format specification is a set of package declarations and format rules: - - Format = [ Entry { ";" Entry } [ ";" ] ] . - Entry = PackageDecl | FormatRule . - - (The syntax of a format specification is presented in the same EBNF - notation as used in the Go language specification. The syntax of white - space, comments, identifiers, and string literals is the same as in Go.) - - A package declaration binds a package name (such as 'ast') to a - package import path (such as '"go/ast"'). Each package used (in - a type name, see below) must be declared once before use. - - PackageDecl = PackageName ImportPath . - PackageName = identifier . - ImportPath = string . - - A format rule binds a rule name to a format expression. A rule name - may be a type name or one of the special names 'default' or '/'. - A type name may be the name of a predeclared type (for example, 'int', - 'float32', etc.), the package-qualified name of a user-defined type - (for example, 'ast.MapType'), or an identifier indicating the structure - of unnamed composite types ('array', 'chan', 'func', 'interface', 'map', - or 'ptr'). Each rule must have a unique name; rules can be declared in - any order. - - FormatRule = RuleName "=" Expression . - RuleName = TypeName | "default" | "/" . - TypeName = [ PackageName "." ] identifier . - - To format a value, the value's type name is used to select the format rule - (there is an override mechanism, see below). The format expression of the - selected rule specifies how the value is formatted. Each format expression, - when applied to a value, evaluates to a byte sequence or nil. - - In its most general form, a format expression is a list of alternatives, - each of which is a sequence of operands: - - Expression = [ Sequence ] { "|" [ Sequence ] } . - Sequence = Operand { Operand } . - - The formatted result produced by an expression is the result of the first - alternative sequence that evaluates to a non-nil result; if there is no - such alternative, the expression evaluates to nil. The result produced by - an operand sequence is the concatenation of the results of its operands. - If any operand in the sequence evaluates to nil, the entire sequence - evaluates to nil. - - There are five kinds of operands: - - Operand = Literal | Field | Group | Option | Repetition . - - Literals evaluate to themselves, with two substitutions. First, - %-formats expand in the manner of fmt.Printf, with the current value - passed as the parameter. Second, the current indentation (see below) - is inserted after every newline or form feed character. - - Literal = string . - - This table shows string literals applied to the value 42 and the - corresponding formatted result: - - "foo" foo - "%x" 2a - "x = %d" x = 42 - "%#x = %d" 0x2a = 42 - - A field operand is a field name optionally followed by an alternate - rule name. The field name may be an identifier or one of the special - names @ or *. - - Field = FieldName [ ":" RuleName ] . - FieldName = identifier | "@" | "*" . - - If the field name is an identifier, the current value must be a struct, - and there must be a field with that name in the struct. The same lookup - rules apply as in the Go language (for instance, the name of an anonymous - field is the unqualified type name). The field name denotes the field - value in the struct. If the field is not found, formatting is aborted - and an error message is returned. (TODO consider changing the semantics - such that if a field is not found, it evaluates to nil). - - The special name '@' denotes the current value. - - The meaning of the special name '*' depends on the type of the current - value: - - array, slice types array, slice element (inside {} only, see below) - interfaces value stored in interface - pointers value pointed to by pointer - - (Implementation restriction: channel, function and map types are not - supported due to missing reflection support). - - Fields are evaluated as follows: If the field value is nil, or an array - or slice element does not exist, the result is nil (see below for details - on array/slice elements). If the value is not nil the field value is - formatted (recursively) using the rule corresponding to its type name, - or the alternate rule name, if given. - - The following example shows a complete format specification for a - struct 'myPackage.Point'. Assume the package - - package myPackage // in directory myDir/myPackage - type Point struct { - name string; - x, y int; - } - - Applying the format specification - - myPackage "myDir/myPackage"; - int = "%d"; - hexInt = "0x%x"; - string = "---%s---"; - myPackage.Point = name "{" x ", " y:hexInt "}"; - - to the value myPackage.Point{"foo", 3, 15} results in - - ---foo---{3, 0xf} - - Finally, an operand may be a grouped, optional, or repeated expression. - A grouped expression ("group") groups a more complex expression (body) - so that it can be used in place of a single operand: - - Group = "(" [ Indentation ">>" ] Body ")" . - Indentation = Expression . - Body = Expression . - - A group body may be prefixed by an indentation expression followed by '>>'. - The indentation expression is applied to the current value like any other - expression and the result, if not nil, is appended to the current indentation - during the evaluation of the body (see also formatting state, below). - - An optional expression ("option") is enclosed in '[]' brackets. - - Option = "[" Body "]" . - - An option evaluates to its body, except that if the body evaluates to nil, - the option expression evaluates to an empty []byte. Thus an option's purpose - is to protect the expression containing the option from a nil operand. - - A repeated expression ("repetition") is enclosed in '{}' braces. - - Repetition = "{" Body [ "/" Separator ] "}" . - Separator = Expression . - - A repeated expression is evaluated as follows: The body is evaluated - repeatedly and its results are concatenated until the body evaluates - to nil. The result of the repetition is the (possibly empty) concatenation, - but it is never nil. An implicit index is supplied for the evaluation of - the body: that index is used to address elements of arrays or slices. If - the corresponding elements do not exist, the field denoting the element - evaluates to nil (which in turn may terminate the repetition). - - The body of a repetition may be followed by a '/' and a "separator" - expression. If the separator is present, it is invoked between repetitions - of the body. - - The following example shows a complete format specification for formatting - a slice of unnamed type. Applying the specification - - int = "%b"; - array = { * / ", " }; // array is the type name for an unnamed slice - - to the value '[]int{2, 3, 5, 7}' results in - - 10, 11, 101, 111 - - Default rule: If a format rule named 'default' is present, it is used for - formatting a value if no other rule was found. A common default rule is - - default = "%v" - - to provide default formatting for basic types without having to specify - a specific rule for each basic type. - - Global separator rule: If a format rule named '/' is present, it is - invoked with the current value between literals. If the separator - expression evaluates to nil, it is ignored. - - For instance, a global separator rule may be used to punctuate a sequence - of values with commas. The rules: - - default = "%v"; - / = ", "; - - will format an argument list by printing each one in its default format, - separated by a comma and a space. -*/ -package datafmt - -import ( - "bytes" - "fmt" - "go/token" - "io" - "os" - "reflect" - "runtime" -) - -// ---------------------------------------------------------------------------- -// Format representation - -// Custom formatters implement the Formatter function type. -// A formatter is invoked with the current formatting state, the -// value to format, and the rule name under which the formatter -// was installed (the same formatter function may be installed -// under different names). The formatter may access the current state -// to guide formatting and use State.Write to append to the state's -// output. -// -// A formatter must return a boolean value indicating if it evaluated -// to a non-nil value (true), or a nil value (false). -// -type Formatter func(state *State, value interface{}, ruleName string) bool - -// A FormatterMap is a set of custom formatters. -// It maps a rule name to a formatter function. -// -type FormatterMap map[string]Formatter - -// A parsed format expression is built from the following nodes. -// -type ( - expr interface{} - - alternatives []expr // x | y | z - - sequence []expr // x y z - - literal [][]byte // a list of string segments, possibly starting with '%' - - field struct { - fieldName string // including "@", "*" - ruleName string // "" if no rule name specified - } - - group struct { - indent, body expr // (indent >> body) - } - - option struct { - body expr // [body] - } - - repetition struct { - body, separator expr // {body / separator} - } - - custom struct { - ruleName string - fun Formatter - } -) - -// A Format is the result of parsing a format specification. -// The format may be applied repeatedly to format values. -// -type Format map[string]expr - -// ---------------------------------------------------------------------------- -// Formatting - -// An application-specific environment may be provided to Format.Apply; -// the environment is available inside custom formatters via State.Env(). -// Environments must implement copying; the Copy method must return an -// complete copy of the receiver. This is necessary so that the formatter -// can save and restore an environment (in case of an absent expression). -// -// If the Environment doesn't change during formatting (this is under -// control of the custom formatters), the Copy function can simply return -// the receiver, and thus can be very light-weight. -// -type Environment interface { - Copy() Environment -} - -// State represents the current formatting state. -// It is provided as argument to custom formatters. -// -type State struct { - fmt Format // format in use - env Environment // user-supplied environment - errors chan os.Error // not chan *Error (errors <- nil would be wrong!) - hasOutput bool // true after the first literal has been written - indent bytes.Buffer // current indentation - output bytes.Buffer // format output - linePos token.Position // position of line beginning (Column == 0) - default_ expr // possibly nil - separator expr // possibly nil -} - -func newState(fmt Format, env Environment, errors chan os.Error) *State { - s := new(State) - s.fmt = fmt - s.env = env - s.errors = errors - s.linePos = token.Position{Line: 1} - - // if we have a default rule, cache it's expression for fast access - if x, found := fmt["default"]; found { - s.default_ = x - } - - // if we have a global separator rule, cache it's expression for fast access - if x, found := fmt["/"]; found { - s.separator = x - } - - return s -} - -// Env returns the environment passed to Format.Apply. -func (s *State) Env() interface{} { return s.env } - -// LinePos returns the position of the current line beginning -// in the state's output buffer. Line numbers start at 1. -// -func (s *State) LinePos() token.Position { return s.linePos } - -// Pos returns the position of the next byte to be written to the -// output buffer. Line numbers start at 1. -// -func (s *State) Pos() token.Position { - offs := s.output.Len() - return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs} -} - -// Write writes data to the output buffer, inserting the indentation -// string after each newline or form feed character. It cannot return an error. -// -func (s *State) Write(data []byte) (int, os.Error) { - n := 0 - i0 := 0 - for i, ch := range data { - if ch == '\n' || ch == '\f' { - // write text segment and indentation - n1, _ := s.output.Write(data[i0 : i+1]) - n2, _ := s.output.Write(s.indent.Bytes()) - n += n1 + n2 - i0 = i + 1 - s.linePos.Offset = s.output.Len() - s.linePos.Line++ - } - } - n3, _ := s.output.Write(data[i0:]) - return n + n3, nil -} - -type checkpoint struct { - env Environment - hasOutput bool - outputLen int - linePos token.Position -} - -func (s *State) save() checkpoint { - saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos} - if s.env != nil { - saved.env = s.env.Copy() - } - return saved -} - -func (s *State) restore(m checkpoint) { - s.env = m.env - s.output.Truncate(m.outputLen) -} - -func (s *State) error(msg string) { - s.errors <- os.NewError(msg) - runtime.Goexit() -} - -// TODO At the moment, unnamed types are simply mapped to the default -// names below. For instance, all unnamed arrays are mapped to -// 'array' which is not really sufficient. Eventually one may want -// to be able to specify rules for say an unnamed slice of T. -// - -func typename(typ reflect.Type) string { - switch typ.Kind() { - case reflect.Array: - return "array" - case reflect.Slice: - return "array" - case reflect.Chan: - return "chan" - case reflect.Func: - return "func" - case reflect.Interface: - return "interface" - case reflect.Map: - return "map" - case reflect.Ptr: - return "ptr" - } - return typ.String() -} - -func (s *State) getFormat(name string) expr { - if fexpr, found := s.fmt[name]; found { - return fexpr - } - - if s.default_ != nil { - return s.default_ - } - - s.error(fmt.Sprintf("no format rule for type: '%s'", name)) - return nil -} - -// eval applies a format expression fexpr to a value. If the expression -// evaluates internally to a non-nil []byte, that slice is appended to -// the state's output buffer and eval returns true. Otherwise, eval -// returns false and the state remains unchanged. -// -func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { - // an empty format expression always evaluates - // to a non-nil (but empty) []byte - if fexpr == nil { - return true - } - - switch t := fexpr.(type) { - case alternatives: - // append the result of the first alternative that evaluates to - // a non-nil []byte to the state's output - mark := s.save() - for _, x := range t { - if s.eval(x, value, index) { - return true - } - s.restore(mark) - } - return false - - case sequence: - // append the result of all operands to the state's output - // unless a nil result is encountered - mark := s.save() - for _, x := range t { - if !s.eval(x, value, index) { - s.restore(mark) - return false - } - } - return true - - case literal: - // write separator, if any - if s.hasOutput { - // not the first literal - if s.separator != nil { - sep := s.separator // save current separator - s.separator = nil // and disable it (avoid recursion) - mark := s.save() - if !s.eval(sep, value, index) { - s.restore(mark) - } - s.separator = sep // enable it again - } - } - s.hasOutput = true - // write literal segments - for _, lit := range t { - if len(lit) > 1 && lit[0] == '%' { - // segment contains a %-format at the beginning - if lit[1] == '%' { - // "%%" is printed as a single "%" - s.Write(lit[1:]) - } else { - // use s instead of s.output to get indentation right - fmt.Fprintf(s, string(lit), value.Interface()) - } - } else { - // segment contains no %-formats - s.Write(lit) - } - } - return true // a literal never evaluates to nil - - case *field: - // determine field value - switch t.fieldName { - case "@": - // field value is current value - - case "*": - // indirection: operation is type-specific - switch v := value; v.Kind() { - case reflect.Array: - if v.Len() <= index { - return false - } - value = v.Index(index) - - case reflect.Slice: - if v.IsNil() || v.Len() <= index { - return false - } - value = v.Index(index) - - case reflect.Map: - s.error("reflection support for maps incomplete") - - case reflect.Ptr: - if v.IsNil() { - return false - } - value = v.Elem() - - case reflect.Interface: - if v.IsNil() { - return false - } - value = v.Elem() - - case reflect.Chan: - s.error("reflection support for chans incomplete") - - case reflect.Func: - s.error("reflection support for funcs incomplete") - - default: - s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type())) - } - - default: - // value is value of named field - var field reflect.Value - if sval := value; sval.Kind() == reflect.Struct { - field = sval.FieldByName(t.fieldName) - if !field.IsValid() { - // TODO consider just returning false in this case - s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type())) - } - } - value = field - } - - // determine rule - ruleName := t.ruleName - if ruleName == "" { - // no alternate rule name, value type determines rule - ruleName = typename(value.Type()) - } - fexpr = s.getFormat(ruleName) - - mark := s.save() - if !s.eval(fexpr, value, index) { - s.restore(mark) - return false - } - return true - - case *group: - // remember current indentation - indentLen := s.indent.Len() - - // update current indentation - mark := s.save() - s.eval(t.indent, value, index) - // if the indentation evaluates to nil, the state's output buffer - // didn't change - either way it's ok to append the difference to - // the current identation - s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()]) - s.restore(mark) - - // format group body - mark = s.save() - b := true - if !s.eval(t.body, value, index) { - s.restore(mark) - b = false - } - - // reset indentation - s.indent.Truncate(indentLen) - return b - - case *option: - // evaluate the body and append the result to the state's output - // buffer unless the result is nil - mark := s.save() - if !s.eval(t.body, value, 0) { // TODO is 0 index correct? - s.restore(mark) - } - return true // an option never evaluates to nil - - case *repetition: - // evaluate the body and append the result to the state's output - // buffer until a result is nil - for i := 0; ; i++ { - mark := s.save() - // write separator, if any - if i > 0 && t.separator != nil { - // nil result from separator is ignored - mark := s.save() - if !s.eval(t.separator, value, i) { - s.restore(mark) - } - } - if !s.eval(t.body, value, i) { - s.restore(mark) - break - } - } - return true // a repetition never evaluates to nil - - case *custom: - // invoke the custom formatter to obtain the result - mark := s.save() - if !t.fun(s, value.Interface(), t.ruleName) { - s.restore(mark) - return false - } - return true - } - - panic("unreachable") - return false -} - -// Eval formats each argument according to the format -// f and returns the resulting []byte and os.Error. If -// an error occurred, the []byte contains the partially -// formatted result. An environment env may be passed -// in which is available in custom formatters through -// the state parameter. -// -func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) { - if f == nil { - return nil, os.NewError("format is nil") - } - - errors := make(chan os.Error) - s := newState(f, env, errors) - - go func() { - for _, v := range args { - fld := reflect.ValueOf(v) - if !fld.IsValid() { - errors <- os.NewError("nil argument") - return - } - mark := s.save() - if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct? - s.restore(mark) - } - } - errors <- nil // no errors - }() - - err := <-errors - return s.output.Bytes(), err -} - -// ---------------------------------------------------------------------------- -// Convenience functions - -// Fprint formats each argument according to the format f -// and writes to w. The result is the total number of bytes -// written and an os.Error, if any. -// -func (f Format) Fprint(w io.Writer, env Environment, args ...interface{}) (int, os.Error) { - data, err := f.Eval(env, args...) - if err != nil { - // TODO should we print partial result in case of error? - return 0, err - } - return w.Write(data) -} - -// Print formats each argument according to the format f -// and writes to standard output. The result is the total -// number of bytes written and an os.Error, if any. -// -func (f Format) Print(args ...interface{}) (int, os.Error) { - return f.Fprint(os.Stdout, nil, args...) -} - -// Sprint formats each argument according to the format f -// and returns the resulting string. If an error occurs -// during formatting, the result string contains the -// partially formatted result followed by an error message. -// -func (f Format) Sprint(args ...interface{}) string { - var buf bytes.Buffer - _, err := f.Fprint(&buf, nil, args...) - if err != nil { - var i interface{} = args - fmt.Fprintf(&buf, "--- Sprint(%s) failed: %v", fmt.Sprint(i), err) - } - return buf.String() -} diff --git a/src/cmd/fix/testdata/reflect.decode.go.in b/src/cmd/fix/testdata/reflect.decode.go.in deleted file mode 100644 index f831abee37..0000000000 --- a/src/cmd/fix/testdata/reflect.decode.go.in +++ /dev/null @@ -1,905 +0,0 @@ -// Copyright 2010 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. - -// Represents JSON data structure using native Go types: booleans, floats, -// strings, arrays, and maps. - -package json - -import ( - "container/vector" - "encoding/base64" - "os" - "reflect" - "runtime" - "strconv" - "strings" - "unicode" - "utf16" - "utf8" -) - -// Unmarshal parses the JSON-encoded data and stores the result -// in the value pointed to by v. -// -// Unmarshal traverses the value v recursively. -// If an encountered value implements the Unmarshaler interface, -// Unmarshal calls its UnmarshalJSON method with a well-formed -// JSON encoding. -// -// Otherwise, Unmarshal uses the inverse of the encodings that -// Marshal uses, allocating maps, slices, and pointers as necessary, -// with the following additional rules: -// -// To unmarshal a JSON value into a nil interface value, the -// type stored in the interface value is one of: -// -// bool, for JSON booleans -// float64, for JSON numbers -// string, for JSON strings -// []interface{}, for JSON arrays -// map[string]interface{}, for JSON objects -// nil for JSON null -// -// If a JSON value is not appropriate for a given target type, -// or if a JSON number overflows the target type, Unmarshal -// skips that field and completes the unmarshalling as best it can. -// If no more serious errors are encountered, Unmarshal returns -// an UnmarshalTypeError describing the earliest such error. -// -func Unmarshal(data []byte, v interface{}) os.Error { - d := new(decodeState).init(data) - - // Quick check for well-formedness. - // Avoids filling out half a data structure - // before discovering a JSON syntax error. - err := checkValid(data, &d.scan) - if err != nil { - return err - } - - return d.unmarshal(v) -} - -// Unmarshaler is the interface implemented by objects -// that can unmarshal a JSON description of themselves. -// The input can be assumed to be a valid JSON object -// encoding. UnmarshalJSON must copy the JSON data -// if it wishes to retain the data after returning. -type Unmarshaler interface { - UnmarshalJSON([]byte) os.Error -} - -// An UnmarshalTypeError describes a JSON value that was -// not appropriate for a value of a specific Go type. -type UnmarshalTypeError struct { - Value string // description of JSON value - "bool", "array", "number -5" - Type reflect.Type // type of Go value it could not be assigned to -} - -func (e *UnmarshalTypeError) String() string { - return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() -} - -// An UnmarshalFieldError describes a JSON object key that -// led to an unexported (and therefore unwritable) struct field. -type UnmarshalFieldError struct { - Key string - Type *reflect.StructType - Field reflect.StructField -} - -func (e *UnmarshalFieldError) String() string { - return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() -} - -// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. -// (The argument to Unmarshal must be a non-nil pointer.) -type InvalidUnmarshalError struct { - Type reflect.Type -} - -func (e *InvalidUnmarshalError) String() string { - if e.Type == nil { - return "json: Unmarshal(nil)" - } - - if _, ok := e.Type.(*reflect.PtrType); !ok { - return "json: Unmarshal(non-pointer " + e.Type.String() + ")" - } - return "json: Unmarshal(nil " + e.Type.String() + ")" -} - -func (d *decodeState) unmarshal(v interface{}) (err os.Error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(os.Error) - } - }() - - rv := reflect.NewValue(v) - pv, ok := rv.(*reflect.PtrValue) - if !ok || pv.IsNil() { - return &InvalidUnmarshalError{reflect.Typeof(v)} - } - - d.scan.reset() - // We decode rv not pv.Elem because the Unmarshaler interface - // test must be applied at the top level of the value. - d.value(rv) - return d.savedError -} - -// decodeState represents the state while decoding a JSON value. -type decodeState struct { - data []byte - off int // read offset in data - scan scanner - nextscan scanner // for calls to nextValue - savedError os.Error -} - -// errPhase is used for errors that should not happen unless -// there is a bug in the JSON decoder or something is editing -// the data slice while the decoder executes. -var errPhase = os.NewError("JSON decoder out of sync - data changing underfoot?") - -func (d *decodeState) init(data []byte) *decodeState { - d.data = data - d.off = 0 - d.savedError = nil - return d -} - -// error aborts the decoding by panicking with err. -func (d *decodeState) error(err os.Error) { - panic(err) -} - -// saveError saves the first err it is called with, -// for reporting at the end of the unmarshal. -func (d *decodeState) saveError(err os.Error) { - if d.savedError == nil { - d.savedError = err - } -} - -// next cuts off and returns the next full JSON value in d.data[d.off:]. -// The next value is known to be an object or array, not a literal. -func (d *decodeState) next() []byte { - c := d.data[d.off] - item, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // Our scanner has seen the opening brace/bracket - // and thinks we're still in the middle of the object. - // invent a closing brace/bracket to get it out. - if c == '{' { - d.scan.step(&d.scan, '}') - } else { - d.scan.step(&d.scan, ']') - } - - return item -} - -// scanWhile processes bytes in d.data[d.off:] until it -// receives a scan code not equal to op. -// It updates d.off and returns the new scan code. -func (d *decodeState) scanWhile(op int) int { - var newOp int - for { - if d.off >= len(d.data) { - newOp = d.scan.eof() - d.off = len(d.data) + 1 // mark processed EOF with len+1 - } else { - c := int(d.data[d.off]) - d.off++ - newOp = d.scan.step(&d.scan, c) - } - if newOp != op { - break - } - } - return newOp -} - -// value decodes a JSON value from d.data[d.off:] into the value. -// it updates d.off to point past the decoded value. -func (d *decodeState) value(v reflect.Value) { - if v == nil { - _, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // d.scan thinks we're still at the beginning of the item. - // Feed in an empty string - the shortest, simplest value - - // so that it knows we got to the end of the value. - if d.scan.step == stateRedo { - panic("redo") - } - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - return - } - - switch op := d.scanWhile(scanSkipSpace); op { - default: - d.error(errPhase) - - case scanBeginArray: - d.array(v) - - case scanBeginObject: - d.object(v) - - case scanBeginLiteral: - d.literal(v) - } -} - -// indirect walks down v allocating pointers as needed, -// until it gets to a non-pointer. -// if it encounters an Unmarshaler, indirect stops and returns that. -// if wantptr is true, indirect stops at the last pointer. -func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, reflect.Value) { - for { - var isUnmarshaler bool - if v.Type().NumMethod() > 0 { - // Remember that this is an unmarshaler, - // but wait to return it until after allocating - // the pointer (if necessary). - _, isUnmarshaler = v.Interface().(Unmarshaler) - } - - if iv, ok := v.(*reflect.InterfaceValue); ok && !iv.IsNil() { - v = iv.Elem() - continue - } - pv, ok := v.(*reflect.PtrValue) - if !ok { - break - } - _, isptrptr := pv.Elem().(*reflect.PtrValue) - if !isptrptr && wantptr && !isUnmarshaler { - return nil, pv - } - if pv.IsNil() { - pv.PointTo(reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())) - } - if isUnmarshaler { - // Using v.Interface().(Unmarshaler) - // here means that we have to use a pointer - // as the struct field. We cannot use a value inside - // a pointer to a struct, because in that case - // v.Interface() is the value (x.f) not the pointer (&x.f). - // This is an unfortunate consequence of reflect. - // An alternative would be to look up the - // UnmarshalJSON method and return a FuncValue. - return v.Interface().(Unmarshaler), nil - } - v = pv.Elem() - } - return nil, v -} - -// array consumes an array from d.data[d.off-1:], decoding into the value v. -// the first byte of the array ('[') has been read already. -func (d *decodeState) array(v reflect.Value) { - // Check for unmarshaler. - unmarshaler, pv := d.indirect(v, false) - if unmarshaler != nil { - d.off-- - err := unmarshaler.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - v = pv - - // Decoding into nil interface? Switch to non-reflect code. - iv, ok := v.(*reflect.InterfaceValue) - if ok { - iv.Set(reflect.NewValue(d.arrayInterface())) - return - } - - // Check type of target. - av, ok := v.(reflect.ArrayOrSliceValue) - if !ok { - d.saveError(&UnmarshalTypeError{"array", v.Type()}) - d.off-- - d.next() - return - } - - sv, _ := v.(*reflect.SliceValue) - - i := 0 - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - // Get element of array, growing if necessary. - if i >= av.Cap() && sv != nil { - newcap := sv.Cap() + sv.Cap()/2 - if newcap < 4 { - newcap = 4 - } - newv := reflect.MakeSlice(sv.Type().(*reflect.SliceType), sv.Len(), newcap) - reflect.Copy(newv, sv) - sv.Set(newv) - } - if i >= av.Len() && sv != nil { - // Must be slice; gave up on array during i >= av.Cap(). - sv.SetLen(i + 1) - } - - // Decode into element. - if i < av.Len() { - d.value(av.Elem(i)) - } else { - // Ran out of fixed array: skip. - d.value(nil) - } - i++ - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - if i < av.Len() { - if sv == nil { - // Array. Zero the rest. - z := reflect.MakeZero(av.Type().(*reflect.ArrayType).Elem()) - for ; i < av.Len(); i++ { - av.Elem(i).SetValue(z) - } - } else { - sv.SetLen(i) - } - } -} - -// matchName returns true if key should be written to a field named name. -func matchName(key, name string) bool { - return strings.ToLower(key) == strings.ToLower(name) -} - -// object consumes an object from d.data[d.off-1:], decoding into the value v. -// the first byte of the object ('{') has been read already. -func (d *decodeState) object(v reflect.Value) { - // Check for unmarshaler. - unmarshaler, pv := d.indirect(v, false) - if unmarshaler != nil { - d.off-- - err := unmarshaler.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - v = pv - - // Decoding into nil interface? Switch to non-reflect code. - iv, ok := v.(*reflect.InterfaceValue) - if ok { - iv.Set(reflect.NewValue(d.objectInterface())) - return - } - - // Check type of target: struct or map[string]T - var ( - mv *reflect.MapValue - sv *reflect.StructValue - ) - switch v := v.(type) { - case *reflect.MapValue: - // map must have string type - t := v.Type().(*reflect.MapType) - if t.Key() != reflect.Typeof("") { - d.saveError(&UnmarshalTypeError{"object", v.Type()}) - break - } - mv = v - if mv.IsNil() { - mv.SetValue(reflect.MakeMap(t)) - } - case *reflect.StructValue: - sv = v - default: - d.saveError(&UnmarshalTypeError{"object", v.Type()}) - } - - if mv == nil && sv == nil { - d.off-- - d.next() // skip over { } in input - return - } - - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Figure out field corresponding to key. - var subv reflect.Value - if mv != nil { - subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem()) - } else { - var f reflect.StructField - var ok bool - st := sv.Type().(*reflect.StructType) - // First try for field with that tag. - if isValidTag(key) { - for i := 0; i < sv.NumField(); i++ { - f = st.Field(i) - if f.Tag == key { - ok = true - break - } - } - } - if !ok { - // Second, exact match. - f, ok = st.FieldByName(key) - } - if !ok { - // Third, case-insensitive match. - f, ok = st.FieldByNameFunc(func(s string) bool { return matchName(key, s) }) - } - - // Extract value; name must be exported. - if ok { - if f.PkgPath != "" { - d.saveError(&UnmarshalFieldError{key, st, f}) - } else { - subv = sv.FieldByIndex(f.Index) - } - } - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - d.value(subv) - - // Write value back to map; - // if using struct, subv points into struct already. - if mv != nil { - mv.SetElem(reflect.NewValue(key), subv) - } - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } -} - -// literal consumes a literal from d.data[d.off-1:], decoding into the value v. -// The first byte of the literal has been read already -// (that's how the caller knows it's a literal). -func (d *decodeState) literal(v reflect.Value) { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] - - // Check for unmarshaler. - wantptr := item[0] == 'n' // null - unmarshaler, pv := d.indirect(v, wantptr) - if unmarshaler != nil { - err := unmarshaler.UnmarshalJSON(item) - if err != nil { - d.error(err) - } - return - } - v = pv - - switch c := item[0]; c { - case 'n': // null - switch v.(type) { - default: - d.saveError(&UnmarshalTypeError{"null", v.Type()}) - case *reflect.InterfaceValue, *reflect.PtrValue, *reflect.MapValue: - v.SetValue(nil) - } - - case 't', 'f': // true, false - value := c == 't' - switch v := v.(type) { - default: - d.saveError(&UnmarshalTypeError{"bool", v.Type()}) - case *reflect.BoolValue: - v.Set(value) - case *reflect.InterfaceValue: - v.Set(reflect.NewValue(value)) - } - - case '"': // string - s, ok := unquoteBytes(item) - if !ok { - d.error(errPhase) - } - switch v := v.(type) { - default: - d.saveError(&UnmarshalTypeError{"string", v.Type()}) - case *reflect.SliceValue: - if v.Type() != byteSliceType { - d.saveError(&UnmarshalTypeError{"string", v.Type()}) - break - } - b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) - n, err := base64.StdEncoding.Decode(b, s) - if err != nil { - d.saveError(err) - break - } - v.Set(reflect.NewValue(b[0:n]).(*reflect.SliceValue)) - case *reflect.StringValue: - v.Set(string(s)) - case *reflect.InterfaceValue: - v.Set(reflect.NewValue(string(s))) - } - - default: // number - if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) - } - s := string(item) - switch v := v.(type) { - default: - d.error(&UnmarshalTypeError{"number", v.Type()}) - case *reflect.InterfaceValue: - n, err := strconv.Atof64(s) - if err != nil { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.Set(reflect.NewValue(n)) - - case *reflect.IntValue: - n, err := strconv.Atoi64(s) - if err != nil || v.Overflow(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.Set(n) - - case *reflect.UintValue: - n, err := strconv.Atoui64(s) - if err != nil || v.Overflow(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.Set(n) - - case *reflect.FloatValue: - n, err := strconv.AtofN(s, v.Type().Bits()) - if err != nil || v.Overflow(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.Set(n) - } - } -} - -// The xxxInterface routines build up a value to be stored -// in an empty interface. They are not strictly necessary, -// but they avoid the weight of reflection in this common case. - -// valueInterface is like value but returns interface{} -func (d *decodeState) valueInterface() interface{} { - switch d.scanWhile(scanSkipSpace) { - default: - d.error(errPhase) - case scanBeginArray: - return d.arrayInterface() - case scanBeginObject: - return d.objectInterface() - case scanBeginLiteral: - return d.literalInterface() - } - panic("unreachable") -} - -// arrayInterface is like array but returns []interface{}. -func (d *decodeState) arrayInterface() []interface{} { - var v vector.Vector - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - v.Push(d.valueInterface()) - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - return v -} - -// objectInterface is like object but returns map[string]interface{}. -func (d *decodeState) objectInterface() map[string]interface{} { - m := make(map[string]interface{}) - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - m[key] = d.valueInterface() - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } - return m -} - -// literalInterface is like literal but returns an interface value. -func (d *decodeState) literalInterface() interface{} { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] - - switch c := item[0]; c { - case 'n': // null - return nil - - case 't', 'f': // true, false - return c == 't' - - case '"': // string - s, ok := unquote(item) - if !ok { - d.error(errPhase) - } - return s - - default: // number - if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) - } - n, err := strconv.Atof64(string(item)) - if err != nil { - d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)}) - } - return n - } - panic("unreachable") -} - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) int { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - rune, err := strconv.Btoui64(string(s[2:6]), 16) - if err != nil { - return -1 - } - return int(rune) -} - -// unquote converts a quoted JSON string literal s into an actual string t. -// The rules are different than for Go, so cannot use strconv.Unquote. -func unquote(s []byte) (t string, ok bool) { - s, ok = unquoteBytes(s) - t = string(s) - return -} - -func unquoteBytes(s []byte) (t []byte, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - s = s[1 : len(s)-1] - - // Check for unusual characters. If there are none, - // then no unquoting is needed, so return a slice of the - // original bytes. - r := 0 - for r < len(s) { - c := s[r] - if c == '\\' || c == '"' || c < ' ' { - break - } - if c < utf8.RuneSelf { - r++ - continue - } - rune, size := utf8.DecodeRune(s[r:]) - if rune == utf8.RuneError && size == 1 { - break - } - r += size - } - if r == len(s) { - return s, true - } - - b := make([]byte, len(s)+2*utf8.UTFMax) - w := copy(b, s[0:r]) - for r < len(s) { - // Out of room? Can only happen if s is full of - // malformed UTF-8 and we're replacing each - // byte with RuneError. - if w >= len(b)-2*utf8.UTFMax { - nb := make([]byte, (len(b)+utf8.UTFMax)*2) - copy(nb, b[0:w]) - b = nb - } - switch c := s[r]; { - case c == '\\': - r++ - if r >= len(s) { - return - } - switch s[r] { - default: - return - case '"', '\\', '/', '\'': - b[w] = s[r] - r++ - w++ - case 'b': - b[w] = '\b' - r++ - w++ - case 'f': - b[w] = '\f' - r++ - w++ - case 'n': - b[w] = '\n' - r++ - w++ - case 'r': - b[w] = '\r' - r++ - w++ - case 't': - b[w] = '\t' - r++ - w++ - case 'u': - r-- - rune := getu4(s[r:]) - if rune < 0 { - return - } - r += 6 - if utf16.IsSurrogate(rune) { - rune1 := getu4(s[r:]) - if dec := utf16.DecodeRune(rune, rune1); dec != unicode.ReplacementChar { - // A valid pair; consume. - r += 6 - w += utf8.EncodeRune(b[w:], dec) - break - } - // Invalid surrogate; fall back to replacement rune. - rune = unicode.ReplacementChar - } - w += utf8.EncodeRune(b[w:], rune) - } - - // Quote, control characters are invalid. - case c == '"', c < ' ': - return - - // ASCII - case c < utf8.RuneSelf: - b[w] = c - r++ - w++ - - // Coerce to well-formed UTF-8. - default: - rune, size := utf8.DecodeRune(s[r:]) - r += size - w += utf8.EncodeRune(b[w:], rune) - } - } - return b[0:w], true -} diff --git a/src/cmd/fix/testdata/reflect.decode.go.out b/src/cmd/fix/testdata/reflect.decode.go.out deleted file mode 100644 index fb7910ee30..0000000000 --- a/src/cmd/fix/testdata/reflect.decode.go.out +++ /dev/null @@ -1,908 +0,0 @@ -// Copyright 2010 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. - -// Represents JSON data structure using native Go types: booleans, floats, -// strings, arrays, and maps. - -package json - -import ( - "container/vector" - "encoding/base64" - "os" - "reflect" - "runtime" - "strconv" - "strings" - "unicode" - "utf16" - "utf8" -) - -// Unmarshal parses the JSON-encoded data and stores the result -// in the value pointed to by v. -// -// Unmarshal traverses the value v recursively. -// If an encountered value implements the Unmarshaler interface, -// Unmarshal calls its UnmarshalJSON method with a well-formed -// JSON encoding. -// -// Otherwise, Unmarshal uses the inverse of the encodings that -// Marshal uses, allocating maps, slices, and pointers as necessary, -// with the following additional rules: -// -// To unmarshal a JSON value into a nil interface value, the -// type stored in the interface value is one of: -// -// bool, for JSON booleans -// float64, for JSON numbers -// string, for JSON strings -// []interface{}, for JSON arrays -// map[string]interface{}, for JSON objects -// nil for JSON null -// -// If a JSON value is not appropriate for a given target type, -// or if a JSON number overflows the target type, Unmarshal -// skips that field and completes the unmarshalling as best it can. -// If no more serious errors are encountered, Unmarshal returns -// an UnmarshalTypeError describing the earliest such error. -// -func Unmarshal(data []byte, v interface{}) os.Error { - d := new(decodeState).init(data) - - // Quick check for well-formedness. - // Avoids filling out half a data structure - // before discovering a JSON syntax error. - err := checkValid(data, &d.scan) - if err != nil { - return err - } - - return d.unmarshal(v) -} - -// Unmarshaler is the interface implemented by objects -// that can unmarshal a JSON description of themselves. -// The input can be assumed to be a valid JSON object -// encoding. UnmarshalJSON must copy the JSON data -// if it wishes to retain the data after returning. -type Unmarshaler interface { - UnmarshalJSON([]byte) os.Error -} - -// An UnmarshalTypeError describes a JSON value that was -// not appropriate for a value of a specific Go type. -type UnmarshalTypeError struct { - Value string // description of JSON value - "bool", "array", "number -5" - Type reflect.Type // type of Go value it could not be assigned to -} - -func (e *UnmarshalTypeError) String() string { - return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() -} - -// An UnmarshalFieldError describes a JSON object key that -// led to an unexported (and therefore unwritable) struct field. -type UnmarshalFieldError struct { - Key string - Type reflect.Type - Field reflect.StructField -} - -func (e *UnmarshalFieldError) String() string { - return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() -} - -// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. -// (The argument to Unmarshal must be a non-nil pointer.) -type InvalidUnmarshalError struct { - Type reflect.Type -} - -func (e *InvalidUnmarshalError) String() string { - if e.Type == nil { - return "json: Unmarshal(nil)" - } - - if e.Type.Kind() != reflect.Ptr { - return "json: Unmarshal(non-pointer " + e.Type.String() + ")" - } - return "json: Unmarshal(nil " + e.Type.String() + ")" -} - -func (d *decodeState) unmarshal(v interface{}) (err os.Error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(os.Error) - } - }() - - rv := reflect.ValueOf(v) - pv := rv - if pv.Kind() != reflect.Ptr || - pv.IsNil() { - return &InvalidUnmarshalError{reflect.TypeOf(v)} - } - - d.scan.reset() - // We decode rv not pv.Elem because the Unmarshaler interface - // test must be applied at the top level of the value. - d.value(rv) - return d.savedError -} - -// decodeState represents the state while decoding a JSON value. -type decodeState struct { - data []byte - off int // read offset in data - scan scanner - nextscan scanner // for calls to nextValue - savedError os.Error -} - -// errPhase is used for errors that should not happen unless -// there is a bug in the JSON decoder or something is editing -// the data slice while the decoder executes. -var errPhase = os.NewError("JSON decoder out of sync - data changing underfoot?") - -func (d *decodeState) init(data []byte) *decodeState { - d.data = data - d.off = 0 - d.savedError = nil - return d -} - -// error aborts the decoding by panicking with err. -func (d *decodeState) error(err os.Error) { - panic(err) -} - -// saveError saves the first err it is called with, -// for reporting at the end of the unmarshal. -func (d *decodeState) saveError(err os.Error) { - if d.savedError == nil { - d.savedError = err - } -} - -// next cuts off and returns the next full JSON value in d.data[d.off:]. -// The next value is known to be an object or array, not a literal. -func (d *decodeState) next() []byte { - c := d.data[d.off] - item, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // Our scanner has seen the opening brace/bracket - // and thinks we're still in the middle of the object. - // invent a closing brace/bracket to get it out. - if c == '{' { - d.scan.step(&d.scan, '}') - } else { - d.scan.step(&d.scan, ']') - } - - return item -} - -// scanWhile processes bytes in d.data[d.off:] until it -// receives a scan code not equal to op. -// It updates d.off and returns the new scan code. -func (d *decodeState) scanWhile(op int) int { - var newOp int - for { - if d.off >= len(d.data) { - newOp = d.scan.eof() - d.off = len(d.data) + 1 // mark processed EOF with len+1 - } else { - c := int(d.data[d.off]) - d.off++ - newOp = d.scan.step(&d.scan, c) - } - if newOp != op { - break - } - } - return newOp -} - -// value decodes a JSON value from d.data[d.off:] into the value. -// it updates d.off to point past the decoded value. -func (d *decodeState) value(v reflect.Value) { - if !v.IsValid() { - _, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // d.scan thinks we're still at the beginning of the item. - // Feed in an empty string - the shortest, simplest value - - // so that it knows we got to the end of the value. - if d.scan.step == stateRedo { - panic("redo") - } - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - return - } - - switch op := d.scanWhile(scanSkipSpace); op { - default: - d.error(errPhase) - - case scanBeginArray: - d.array(v) - - case scanBeginObject: - d.object(v) - - case scanBeginLiteral: - d.literal(v) - } -} - -// indirect walks down v allocating pointers as needed, -// until it gets to a non-pointer. -// if it encounters an Unmarshaler, indirect stops and returns that. -// if wantptr is true, indirect stops at the last pointer. -func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, reflect.Value) { - for { - var isUnmarshaler bool - if v.Type().NumMethod() > 0 { - // Remember that this is an unmarshaler, - // but wait to return it until after allocating - // the pointer (if necessary). - _, isUnmarshaler = v.Interface().(Unmarshaler) - } - - if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() { - v = iv.Elem() - continue - } - pv := v - if pv.Kind() != reflect.Ptr { - break - } - - if pv.Elem().Kind() != reflect.Ptr && - wantptr && !isUnmarshaler { - return nil, pv - } - if pv.IsNil() { - pv.Set(reflect.Zero(pv.Type().Elem()).Addr()) - } - if isUnmarshaler { - // Using v.Interface().(Unmarshaler) - // here means that we have to use a pointer - // as the struct field. We cannot use a value inside - // a pointer to a struct, because in that case - // v.Interface() is the value (x.f) not the pointer (&x.f). - // This is an unfortunate consequence of reflect. - // An alternative would be to look up the - // UnmarshalJSON method and return a FuncValue. - return v.Interface().(Unmarshaler), reflect.Value{} - } - v = pv.Elem() - } - return nil, v -} - -// array consumes an array from d.data[d.off-1:], decoding into the value v. -// the first byte of the array ('[') has been read already. -func (d *decodeState) array(v reflect.Value) { - // Check for unmarshaler. - unmarshaler, pv := d.indirect(v, false) - if unmarshaler != nil { - d.off-- - err := unmarshaler.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - v = pv - - // Decoding into nil interface? Switch to non-reflect code. - iv := v - ok := iv.Kind() == reflect.Interface - if ok { - iv.Set(reflect.ValueOf(d.arrayInterface())) - return - } - - // Check type of target. - av := v - if av.Kind() != reflect.Array && av.Kind() != reflect.Slice { - d.saveError(&UnmarshalTypeError{"array", v.Type()}) - d.off-- - d.next() - return - } - - sv := v - - i := 0 - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - // Get element of array, growing if necessary. - if i >= av.Cap() && sv.IsValid() { - newcap := sv.Cap() + sv.Cap()/2 - if newcap < 4 { - newcap = 4 - } - newv := reflect.MakeSlice(sv.Type(), sv.Len(), newcap) - reflect.Copy(newv, sv) - sv.Set(newv) - } - if i >= av.Len() && sv.IsValid() { - // Must be slice; gave up on array during i >= av.Cap(). - sv.SetLen(i + 1) - } - - // Decode into element. - if i < av.Len() { - d.value(av.Index(i)) - } else { - // Ran out of fixed array: skip. - d.value(reflect.Value{}) - } - i++ - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - if i < av.Len() { - if !sv.IsValid() { - // Array. Zero the rest. - z := reflect.Zero(av.Type().Elem()) - for ; i < av.Len(); i++ { - av.Index(i).Set(z) - } - } else { - sv.SetLen(i) - } - } -} - -// matchName returns true if key should be written to a field named name. -func matchName(key, name string) bool { - return strings.ToLower(key) == strings.ToLower(name) -} - -// object consumes an object from d.data[d.off-1:], decoding into the value v. -// the first byte of the object ('{') has been read already. -func (d *decodeState) object(v reflect.Value) { - // Check for unmarshaler. - unmarshaler, pv := d.indirect(v, false) - if unmarshaler != nil { - d.off-- - err := unmarshaler.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - v = pv - - // Decoding into nil interface? Switch to non-reflect code. - iv := v - if iv.Kind() == reflect.Interface { - iv.Set(reflect.ValueOf(d.objectInterface())) - return - } - - // Check type of target: struct or map[string]T - var ( - mv reflect.Value - sv reflect.Value - ) - switch v.Kind() { - case reflect.Map: - // map must have string type - t := v.Type() - if t.Key() != reflect.TypeOf("") { - d.saveError(&UnmarshalTypeError{"object", v.Type()}) - break - } - mv = v - if mv.IsNil() { - mv.Set(reflect.MakeMap(t)) - } - case reflect.Struct: - sv = v - default: - d.saveError(&UnmarshalTypeError{"object", v.Type()}) - } - - if !mv.IsValid() && !sv.IsValid() { - d.off-- - d.next() // skip over { } in input - return - } - - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Figure out field corresponding to key. - var subv reflect.Value - if mv.IsValid() { - subv = reflect.Zero(mv.Type().Elem()) - } else { - var f reflect.StructField - var ok bool - st := sv.Type() - // First try for field with that tag. - if isValidTag(key) { - for i := 0; i < sv.NumField(); i++ { - f = st.Field(i) - if f.Tag == key { - ok = true - break - } - } - } - if !ok { - // Second, exact match. - f, ok = st.FieldByName(key) - } - if !ok { - // Third, case-insensitive match. - f, ok = st.FieldByNameFunc(func(s string) bool { return matchName(key, s) }) - } - - // Extract value; name must be exported. - if ok { - if f.PkgPath != "" { - d.saveError(&UnmarshalFieldError{key, st, f}) - } else { - subv = sv.FieldByIndex(f.Index) - } - } - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - d.value(subv) - - // Write value back to map; - // if using struct, subv points into struct already. - if mv.IsValid() { - mv.SetMapIndex(reflect.ValueOf(key), subv) - } - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } -} - -// literal consumes a literal from d.data[d.off-1:], decoding into the value v. -// The first byte of the literal has been read already -// (that's how the caller knows it's a literal). -func (d *decodeState) literal(v reflect.Value) { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] - - // Check for unmarshaler. - wantptr := item[0] == 'n' // null - unmarshaler, pv := d.indirect(v, wantptr) - if unmarshaler != nil { - err := unmarshaler.UnmarshalJSON(item) - if err != nil { - d.error(err) - } - return - } - v = pv - - switch c := item[0]; c { - case 'n': // null - switch v.Kind() { - default: - d.saveError(&UnmarshalTypeError{"null", v.Type()}) - case reflect.Interface, reflect.Ptr, reflect.Map: - v.Set(reflect.Zero(v.Type())) - } - - case 't', 'f': // true, false - value := c == 't' - switch v.Kind() { - default: - d.saveError(&UnmarshalTypeError{"bool", v.Type()}) - case reflect.Bool: - v.SetBool(value) - case reflect.Interface: - v.Set(reflect.ValueOf(value)) - } - - case '"': // string - s, ok := unquoteBytes(item) - if !ok { - d.error(errPhase) - } - switch v.Kind() { - default: - d.saveError(&UnmarshalTypeError{"string", v.Type()}) - case reflect.Slice: - if v.Type() != byteSliceType { - d.saveError(&UnmarshalTypeError{"string", v.Type()}) - break - } - b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) - n, err := base64.StdEncoding.Decode(b, s) - if err != nil { - d.saveError(err) - break - } - v.Set(reflect.ValueOf(b[0:n])) - case reflect.String: - v.SetString(string(s)) - case reflect.Interface: - v.Set(reflect.ValueOf(string(s))) - } - - default: // number - if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) - } - s := string(item) - switch v.Kind() { - default: - d.error(&UnmarshalTypeError{"number", v.Type()}) - case reflect.Interface: - n, err := strconv.Atof64(s) - if err != nil { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.Set(reflect.ValueOf(n)) - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - n, err := strconv.Atoi64(s) - if err != nil || v.OverflowInt(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.SetInt(n) - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - n, err := strconv.Atoui64(s) - if err != nil || v.OverflowUint(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.SetUint(n) - - case reflect.Float32, reflect.Float64: - n, err := strconv.AtofN(s, v.Type().Bits()) - if err != nil || v.OverflowFloat(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) - break - } - v.SetFloat(n) - } - } -} - -// The xxxInterface routines build up a value to be stored -// in an empty interface. They are not strictly necessary, -// but they avoid the weight of reflection in this common case. - -// valueInterface is like value but returns interface{} -func (d *decodeState) valueInterface() interface{} { - switch d.scanWhile(scanSkipSpace) { - default: - d.error(errPhase) - case scanBeginArray: - return d.arrayInterface() - case scanBeginObject: - return d.objectInterface() - case scanBeginLiteral: - return d.literalInterface() - } - panic("unreachable") -} - -// arrayInterface is like array but returns []interface{}. -func (d *decodeState) arrayInterface() []interface{} { - var v vector.Vector - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - v.Push(d.valueInterface()) - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - return v -} - -// objectInterface is like object but returns map[string]interface{}. -func (d *decodeState) objectInterface() map[string]interface{} { - m := make(map[string]interface{}) - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - m[key] = d.valueInterface() - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } - return m -} - -// literalInterface is like literal but returns an interface value. -func (d *decodeState) literalInterface() interface{} { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] - - switch c := item[0]; c { - case 'n': // null - return nil - - case 't', 'f': // true, false - return c == 't' - - case '"': // string - s, ok := unquote(item) - if !ok { - d.error(errPhase) - } - return s - - default: // number - if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) - } - n, err := strconv.Atof64(string(item)) - if err != nil { - d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)}) - } - return n - } - panic("unreachable") -} - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) int { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - rune, err := strconv.Btoui64(string(s[2:6]), 16) - if err != nil { - return -1 - } - return int(rune) -} - -// unquote converts a quoted JSON string literal s into an actual string t. -// The rules are different than for Go, so cannot use strconv.Unquote. -func unquote(s []byte) (t string, ok bool) { - s, ok = unquoteBytes(s) - t = string(s) - return -} - -func unquoteBytes(s []byte) (t []byte, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - s = s[1 : len(s)-1] - - // Check for unusual characters. If there are none, - // then no unquoting is needed, so return a slice of the - // original bytes. - r := 0 - for r < len(s) { - c := s[r] - if c == '\\' || c == '"' || c < ' ' { - break - } - if c < utf8.RuneSelf { - r++ - continue - } - rune, size := utf8.DecodeRune(s[r:]) - if rune == utf8.RuneError && size == 1 { - break - } - r += size - } - if r == len(s) { - return s, true - } - - b := make([]byte, len(s)+2*utf8.UTFMax) - w := copy(b, s[0:r]) - for r < len(s) { - // Out of room? Can only happen if s is full of - // malformed UTF-8 and we're replacing each - // byte with RuneError. - if w >= len(b)-2*utf8.UTFMax { - nb := make([]byte, (len(b)+utf8.UTFMax)*2) - copy(nb, b[0:w]) - b = nb - } - switch c := s[r]; { - case c == '\\': - r++ - if r >= len(s) { - return - } - switch s[r] { - default: - return - case '"', '\\', '/', '\'': - b[w] = s[r] - r++ - w++ - case 'b': - b[w] = '\b' - r++ - w++ - case 'f': - b[w] = '\f' - r++ - w++ - case 'n': - b[w] = '\n' - r++ - w++ - case 'r': - b[w] = '\r' - r++ - w++ - case 't': - b[w] = '\t' - r++ - w++ - case 'u': - r-- - rune := getu4(s[r:]) - if rune < 0 { - return - } - r += 6 - if utf16.IsSurrogate(rune) { - rune1 := getu4(s[r:]) - if dec := utf16.DecodeRune(rune, rune1); dec != unicode.ReplacementChar { - // A valid pair; consume. - r += 6 - w += utf8.EncodeRune(b[w:], dec) - break - } - // Invalid surrogate; fall back to replacement rune. - rune = unicode.ReplacementChar - } - w += utf8.EncodeRune(b[w:], rune) - } - - // Quote, control characters are invalid. - case c == '"', c < ' ': - return - - // ASCII - case c < utf8.RuneSelf: - b[w] = c - r++ - w++ - - // Coerce to well-formed UTF-8. - default: - rune, size := utf8.DecodeRune(s[r:]) - r += size - w += utf8.EncodeRune(b[w:], rune) - } - } - return b[0:w], true -} diff --git a/src/cmd/fix/testdata/reflect.decoder.go.in b/src/cmd/fix/testdata/reflect.decoder.go.in deleted file mode 100644 index 0ce9b06fdd..0000000000 --- a/src/cmd/fix/testdata/reflect.decoder.go.in +++ /dev/null @@ -1,196 +0,0 @@ -// 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. - -package gob - -import ( - "bufio" - "bytes" - "io" - "os" - "reflect" - "sync" -) - -// A Decoder manages the receipt of type and data information read from the -// remote side of a connection. -type Decoder struct { - mutex sync.Mutex // each item must be received atomically - r io.Reader // source of the data - buf bytes.Buffer // buffer for more efficient i/o from r - wireType map[typeId]*wireType // map from remote ID to local description - decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines - ignorerCache map[typeId]**decEngine // ditto for ignored objects - freeList *decoderState // list of free decoderStates; avoids reallocation - countBuf []byte // used for decoding integers while parsing messages - tmp []byte // temporary storage for i/o; saves reallocating - err os.Error -} - -// NewDecoder returns a new decoder that reads from the io.Reader. -func NewDecoder(r io.Reader) *Decoder { - dec := new(Decoder) - dec.r = bufio.NewReader(r) - dec.wireType = make(map[typeId]*wireType) - dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) - dec.ignorerCache = make(map[typeId]**decEngine) - dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes - - return dec -} - -// recvType loads the definition of a type. -func (dec *Decoder) recvType(id typeId) { - // Have we already seen this type? That's an error - if id < firstUserId || dec.wireType[id] != nil { - dec.err = os.NewError("gob: duplicate type received") - return - } - - // Type: - wire := new(wireType) - dec.decodeValue(tWireType, reflect.NewValue(wire)) - if dec.err != nil { - return - } - // Remember we've seen this type. - dec.wireType[id] = wire -} - -// recvMessage reads the next count-delimited item from the input. It is the converse -// of Encoder.writeMessage. It returns false on EOF or other error reading the message. -func (dec *Decoder) recvMessage() bool { - // Read a count. - nbytes, _, err := decodeUintReader(dec.r, dec.countBuf) - if err != nil { - dec.err = err - return false - } - dec.readMessage(int(nbytes)) - return dec.err == nil -} - -// readMessage reads the next nbytes bytes from the input. -func (dec *Decoder) readMessage(nbytes int) { - // Allocate the buffer. - if cap(dec.tmp) < nbytes { - dec.tmp = make([]byte, nbytes+100) // room to grow - } - dec.tmp = dec.tmp[:nbytes] - - // Read the data - _, dec.err = io.ReadFull(dec.r, dec.tmp) - if dec.err != nil { - if dec.err == os.EOF { - dec.err = io.ErrUnexpectedEOF - } - return - } - dec.buf.Write(dec.tmp) -} - -// toInt turns an encoded uint64 into an int, according to the marshaling rules. -func toInt(x uint64) int64 { - i := int64(x >> 1) - if x&1 != 0 { - i = ^i - } - return i -} - -func (dec *Decoder) nextInt() int64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return toInt(n) -} - -func (dec *Decoder) nextUint() uint64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return n -} - -// decodeTypeSequence parses: -// TypeSequence -// (TypeDefinition DelimitedTypeDefinition*)? -// and returns the type id of the next value. It returns -1 at -// EOF. Upon return, the remainder of dec.buf is the value to be -// decoded. If this is an interface value, it can be ignored by -// simply resetting that buffer. -func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { - for dec.err == nil { - if dec.buf.Len() == 0 { - if !dec.recvMessage() { - break - } - } - // Receive a type id. - id := typeId(dec.nextInt()) - if id >= 0 { - // Value follows. - return id - } - // Type definition for (-id) follows. - dec.recvType(-id) - // When decoding an interface, after a type there may be a - // DelimitedValue still in the buffer. Skip its count. - // (Alternatively, the buffer is empty and the byte count - // will be absorbed by recvMessage.) - if dec.buf.Len() > 0 { - if !isInterface { - dec.err = os.NewError("extra data in buffer") - break - } - dec.nextUint() - } - } - return -1 -} - -// Decode reads the next value from the connection and stores -// it in the data represented by the empty interface value. -// If e is nil, the value will be discarded. Otherwise, -// the value underlying e must either be the correct type for the next -// data item received, and must be a pointer. -func (dec *Decoder) Decode(e interface{}) os.Error { - if e == nil { - return dec.DecodeValue(nil) - } - value := reflect.NewValue(e) - // If e represents a value as opposed to a pointer, the answer won't - // get back to the caller. Make sure it's a pointer. - if value.Type().Kind() != reflect.Ptr { - dec.err = os.NewError("gob: attempt to decode into a non-pointer") - return dec.err - } - return dec.DecodeValue(value) -} - -// DecodeValue reads the next value from the connection and stores -// it in the data represented by the reflection value. -// The value must be the correct type for the next -// data item received, or it may be nil, which means the -// value will be discarded. -func (dec *Decoder) DecodeValue(value reflect.Value) os.Error { - // Make sure we're single-threaded through here. - dec.mutex.Lock() - defer dec.mutex.Unlock() - - dec.buf.Reset() // In case data lingers from previous invocation. - dec.err = nil - id := dec.decodeTypeSequence(false) - if dec.err == nil { - dec.decodeValue(id, value) - } - return dec.err -} - -// If debug.go is compiled into the program , debugFunc prints a human-readable -// representation of the gob data read from r by calling that file's Debug function. -// Otherwise it is nil. -var debugFunc func(io.Reader) diff --git a/src/cmd/fix/testdata/reflect.decoder.go.out b/src/cmd/fix/testdata/reflect.decoder.go.out deleted file mode 100644 index ece88ecbed..0000000000 --- a/src/cmd/fix/testdata/reflect.decoder.go.out +++ /dev/null @@ -1,196 +0,0 @@ -// 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. - -package gob - -import ( - "bufio" - "bytes" - "io" - "os" - "reflect" - "sync" -) - -// A Decoder manages the receipt of type and data information read from the -// remote side of a connection. -type Decoder struct { - mutex sync.Mutex // each item must be received atomically - r io.Reader // source of the data - buf bytes.Buffer // buffer for more efficient i/o from r - wireType map[typeId]*wireType // map from remote ID to local description - decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines - ignorerCache map[typeId]**decEngine // ditto for ignored objects - freeList *decoderState // list of free decoderStates; avoids reallocation - countBuf []byte // used for decoding integers while parsing messages - tmp []byte // temporary storage for i/o; saves reallocating - err os.Error -} - -// NewDecoder returns a new decoder that reads from the io.Reader. -func NewDecoder(r io.Reader) *Decoder { - dec := new(Decoder) - dec.r = bufio.NewReader(r) - dec.wireType = make(map[typeId]*wireType) - dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine) - dec.ignorerCache = make(map[typeId]**decEngine) - dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes - - return dec -} - -// recvType loads the definition of a type. -func (dec *Decoder) recvType(id typeId) { - // Have we already seen this type? That's an error - if id < firstUserId || dec.wireType[id] != nil { - dec.err = os.NewError("gob: duplicate type received") - return - } - - // Type: - wire := new(wireType) - dec.decodeValue(tWireType, reflect.ValueOf(wire)) - if dec.err != nil { - return - } - // Remember we've seen this type. - dec.wireType[id] = wire -} - -// recvMessage reads the next count-delimited item from the input. It is the converse -// of Encoder.writeMessage. It returns false on EOF or other error reading the message. -func (dec *Decoder) recvMessage() bool { - // Read a count. - nbytes, _, err := decodeUintReader(dec.r, dec.countBuf) - if err != nil { - dec.err = err - return false - } - dec.readMessage(int(nbytes)) - return dec.err == nil -} - -// readMessage reads the next nbytes bytes from the input. -func (dec *Decoder) readMessage(nbytes int) { - // Allocate the buffer. - if cap(dec.tmp) < nbytes { - dec.tmp = make([]byte, nbytes+100) // room to grow - } - dec.tmp = dec.tmp[:nbytes] - - // Read the data - _, dec.err = io.ReadFull(dec.r, dec.tmp) - if dec.err != nil { - if dec.err == os.EOF { - dec.err = io.ErrUnexpectedEOF - } - return - } - dec.buf.Write(dec.tmp) -} - -// toInt turns an encoded uint64 into an int, according to the marshaling rules. -func toInt(x uint64) int64 { - i := int64(x >> 1) - if x&1 != 0 { - i = ^i - } - return i -} - -func (dec *Decoder) nextInt() int64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return toInt(n) -} - -func (dec *Decoder) nextUint() uint64 { - n, _, err := decodeUintReader(&dec.buf, dec.countBuf) - if err != nil { - dec.err = err - } - return n -} - -// decodeTypeSequence parses: -// TypeSequence -// (TypeDefinition DelimitedTypeDefinition*)? -// and returns the type id of the next value. It returns -1 at -// EOF. Upon return, the remainder of dec.buf is the value to be -// decoded. If this is an interface value, it can be ignored by -// simply resetting that buffer. -func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { - for dec.err == nil { - if dec.buf.Len() == 0 { - if !dec.recvMessage() { - break - } - } - // Receive a type id. - id := typeId(dec.nextInt()) - if id >= 0 { - // Value follows. - return id - } - // Type definition for (-id) follows. - dec.recvType(-id) - // When decoding an interface, after a type there may be a - // DelimitedValue still in the buffer. Skip its count. - // (Alternatively, the buffer is empty and the byte count - // will be absorbed by recvMessage.) - if dec.buf.Len() > 0 { - if !isInterface { - dec.err = os.NewError("extra data in buffer") - break - } - dec.nextUint() - } - } - return -1 -} - -// Decode reads the next value from the connection and stores -// it in the data represented by the empty interface value. -// If e is nil, the value will be discarded. Otherwise, -// the value underlying e must either be the correct type for the next -// data item received, and must be a pointer. -func (dec *Decoder) Decode(e interface{}) os.Error { - if e == nil { - return dec.DecodeValue(reflect.Value{}) - } - value := reflect.ValueOf(e) - // If e represents a value as opposed to a pointer, the answer won't - // get back to the caller. Make sure it's a pointer. - if value.Type().Kind() != reflect.Ptr { - dec.err = os.NewError("gob: attempt to decode into a non-pointer") - return dec.err - } - return dec.DecodeValue(value) -} - -// DecodeValue reads the next value from the connection and stores -// it in the data represented by the reflection value. -// The value must be the correct type for the next -// data item received, or it may be nil, which means the -// value will be discarded. -func (dec *Decoder) DecodeValue(value reflect.Value) os.Error { - // Make sure we're single-threaded through here. - dec.mutex.Lock() - defer dec.mutex.Unlock() - - dec.buf.Reset() // In case data lingers from previous invocation. - dec.err = nil - id := dec.decodeTypeSequence(false) - if dec.err == nil { - dec.decodeValue(id, value) - } - return dec.err -} - -// If debug.go is compiled into the program , debugFunc prints a human-readable -// representation of the gob data read from r by calling that file's Debug function. -// Otherwise it is nil. -var debugFunc func(io.Reader) diff --git a/src/cmd/fix/testdata/reflect.dnsmsg.go.in b/src/cmd/fix/testdata/reflect.dnsmsg.go.in deleted file mode 100644 index 3d9c312f24..0000000000 --- a/src/cmd/fix/testdata/reflect.dnsmsg.go.in +++ /dev/null @@ -1,777 +0,0 @@ -// 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. - -// DNS packet assembly. See RFC 1035. -// -// This is intended to support name resolution during net.Dial. -// It doesn't have to be blazing fast. -// -// Rather than write the usual handful of routines to pack and -// unpack every message that can appear on the wire, we use -// reflection to write a generic pack/unpack for structs and then -// use it. Thus, if in the future we need to define new message -// structs, no new pack/unpack/printing code needs to be written. -// -// The first half of this file defines the DNS message formats. -// The second half implements the conversion to and from wire format. -// A few of the structure elements have string tags to aid the -// generic pack/unpack routines. -// -// TODO(rsc): There are enough names defined in this file that they're all -// prefixed with dns. Perhaps put this in its own package later. - -package net - -import ( - "fmt" - "os" - "reflect" -) - -// Packet formats - -// Wire constants. -const ( - // valid dnsRR_Header.Rrtype and dnsQuestion.qtype - dnsTypeA = 1 - dnsTypeNS = 2 - dnsTypeMD = 3 - dnsTypeMF = 4 - dnsTypeCNAME = 5 - dnsTypeSOA = 6 - dnsTypeMB = 7 - dnsTypeMG = 8 - dnsTypeMR = 9 - dnsTypeNULL = 10 - dnsTypeWKS = 11 - dnsTypePTR = 12 - dnsTypeHINFO = 13 - dnsTypeMINFO = 14 - dnsTypeMX = 15 - dnsTypeTXT = 16 - dnsTypeAAAA = 28 - dnsTypeSRV = 33 - - // valid dnsQuestion.qtype only - dnsTypeAXFR = 252 - dnsTypeMAILB = 253 - dnsTypeMAILA = 254 - dnsTypeALL = 255 - - // valid dnsQuestion.qclass - dnsClassINET = 1 - dnsClassCSNET = 2 - dnsClassCHAOS = 3 - dnsClassHESIOD = 4 - dnsClassANY = 255 - - // dnsMsg.rcode - dnsRcodeSuccess = 0 - dnsRcodeFormatError = 1 - dnsRcodeServerFailure = 2 - dnsRcodeNameError = 3 - dnsRcodeNotImplemented = 4 - dnsRcodeRefused = 5 -) - -// The wire format for the DNS packet header. -type dnsHeader struct { - Id uint16 - Bits uint16 - Qdcount, Ancount, Nscount, Arcount uint16 -} - -const ( - // dnsHeader.Bits - _QR = 1 << 15 // query/response (response=1) - _AA = 1 << 10 // authoritative - _TC = 1 << 9 // truncated - _RD = 1 << 8 // recursion desired - _RA = 1 << 7 // recursion available -) - -// DNS queries. -type dnsQuestion struct { - Name string "domain-name" // "domain-name" specifies encoding; see packers below - Qtype uint16 - Qclass uint16 -} - -// DNS responses (resource records). -// There are many types of messages, -// but they all share the same header. -type dnsRR_Header struct { - Name string "domain-name" - Rrtype uint16 - Class uint16 - Ttl uint32 - Rdlength uint16 // length of data after header -} - -func (h *dnsRR_Header) Header() *dnsRR_Header { - return h -} - -type dnsRR interface { - Header() *dnsRR_Header -} - -// Specific DNS RR formats for each query type. - -type dnsRR_CNAME struct { - Hdr dnsRR_Header - Cname string "domain-name" -} - -func (rr *dnsRR_CNAME) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_HINFO struct { - Hdr dnsRR_Header - Cpu string - Os string -} - -func (rr *dnsRR_HINFO) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MB struct { - Hdr dnsRR_Header - Mb string "domain-name" -} - -func (rr *dnsRR_MB) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MG struct { - Hdr dnsRR_Header - Mg string "domain-name" -} - -func (rr *dnsRR_MG) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MINFO struct { - Hdr dnsRR_Header - Rmail string "domain-name" - Email string "domain-name" -} - -func (rr *dnsRR_MINFO) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MR struct { - Hdr dnsRR_Header - Mr string "domain-name" -} - -func (rr *dnsRR_MR) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MX struct { - Hdr dnsRR_Header - Pref uint16 - Mx string "domain-name" -} - -func (rr *dnsRR_MX) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_NS struct { - Hdr dnsRR_Header - Ns string "domain-name" -} - -func (rr *dnsRR_NS) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_PTR struct { - Hdr dnsRR_Header - Ptr string "domain-name" -} - -func (rr *dnsRR_PTR) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_SOA struct { - Hdr dnsRR_Header - Ns string "domain-name" - Mbox string "domain-name" - Serial uint32 - Refresh uint32 - Retry uint32 - Expire uint32 - Minttl uint32 -} - -func (rr *dnsRR_SOA) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_TXT struct { - Hdr dnsRR_Header - Txt string // not domain name -} - -func (rr *dnsRR_TXT) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_SRV struct { - Hdr dnsRR_Header - Priority uint16 - Weight uint16 - Port uint16 - Target string "domain-name" -} - -func (rr *dnsRR_SRV) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_A struct { - Hdr dnsRR_Header - A uint32 "ipv4" -} - -func (rr *dnsRR_A) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_AAAA struct { - Hdr dnsRR_Header - AAAA [16]byte "ipv6" -} - -func (rr *dnsRR_AAAA) Header() *dnsRR_Header { - return &rr.Hdr -} - -// Packing and unpacking. -// -// All the packers and unpackers take a (msg []byte, off int) -// and return (off1 int, ok bool). If they return ok==false, they -// also return off1==len(msg), so that the next unpacker will -// also fail. This lets us avoid checks of ok until the end of a -// packing sequence. - -// Map of constructors for each RR wire type. -var rr_mk = map[int]func() dnsRR{ - dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) }, - dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) }, - dnsTypeMB: func() dnsRR { return new(dnsRR_MB) }, - dnsTypeMG: func() dnsRR { return new(dnsRR_MG) }, - dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) }, - dnsTypeMR: func() dnsRR { return new(dnsRR_MR) }, - dnsTypeMX: func() dnsRR { return new(dnsRR_MX) }, - dnsTypeNS: func() dnsRR { return new(dnsRR_NS) }, - dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) }, - dnsTypeSOA: func() dnsRR { return new(dnsRR_SOA) }, - dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) }, - dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) }, - dnsTypeA: func() dnsRR { return new(dnsRR_A) }, - dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) }, -} - -// Pack a domain name s into msg[off:]. -// Domain names are a sequence of counted strings -// split at the dots. They end with a zero-length string. -func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) { - // Add trailing dot to canonicalize name. - if n := len(s); n == 0 || s[n-1] != '.' { - s += "." - } - - // Each dot ends a segment of the name. - // We trade each dot byte for a length byte. - // There is also a trailing zero. - // Check that we have all the space we need. - tot := len(s) + 1 - if off+tot > len(msg) { - return len(msg), false - } - - // Emit sequence of counted strings, chopping at dots. - begin := 0 - for i := 0; i < len(s); i++ { - if s[i] == '.' { - if i-begin >= 1<<6 { // top two bits of length must be clear - return len(msg), false - } - msg[off] = byte(i - begin) - off++ - for j := begin; j < i; j++ { - msg[off] = s[j] - off++ - } - begin = i + 1 - } - } - msg[off] = 0 - off++ - return off, true -} - -// Unpack a domain name. -// In addition to the simple sequences of counted strings above, -// domain names are allowed to refer to strings elsewhere in the -// packet, to avoid repeating common suffixes when returning -// many entries in a single domain. The pointers are marked -// by a length byte with the top two bits set. Ignoring those -// two bits, that byte and the next give a 14 bit offset from msg[0] -// where we should pick up the trail. -// Note that if we jump elsewhere in the packet, -// we return off1 == the offset after the first pointer we found, -// which is where the next record will start. -// In theory, the pointers are only allowed to jump backward. -// We let them jump anywhere and stop jumping after a while. -func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) { - s = "" - ptr := 0 // number of pointers followed -Loop: - for { - if off >= len(msg) { - return "", len(msg), false - } - c := int(msg[off]) - off++ - switch c & 0xC0 { - case 0x00: - if c == 0x00 { - // end of name - break Loop - } - // literal string - if off+c > len(msg) { - return "", len(msg), false - } - s += string(msg[off:off+c]) + "." - off += c - case 0xC0: - // pointer to somewhere else in msg. - // remember location after first ptr, - // since that's how many bytes we consumed. - // also, don't follow too many pointers -- - // maybe there's a loop. - if off >= len(msg) { - return "", len(msg), false - } - c1 := msg[off] - off++ - if ptr == 0 { - off1 = off - } - if ptr++; ptr > 10 { - return "", len(msg), false - } - off = (c^0xC0)<<8 | int(c1) - default: - // 0x80 and 0x40 are reserved - return "", len(msg), false - } - } - if ptr == 0 { - off1 = off - } - return s, off1, true -} - -// TODO(rsc): Move into generic library? -// Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string, -// [n]byte, and other (often anonymous) structs. -func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) { - for i := 0; i < val.NumField(); i++ { - f := val.Type().(*reflect.StructType).Field(i) - switch fv := val.Field(i).(type) { - default: - BadType: - fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) - return len(msg), false - case *reflect.StructValue: - off, ok = packStructValue(fv, msg, off) - case *reflect.UintValue: - i := fv.Get() - switch fv.Type().Kind() { - default: - goto BadType - case reflect.Uint16: - if off+2 > len(msg) { - return len(msg), false - } - msg[off] = byte(i >> 8) - msg[off+1] = byte(i) - off += 2 - case reflect.Uint32: - if off+4 > len(msg) { - return len(msg), false - } - msg[off] = byte(i >> 24) - msg[off+1] = byte(i >> 16) - msg[off+2] = byte(i >> 8) - msg[off+3] = byte(i) - off += 4 - } - case *reflect.ArrayValue: - if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 { - goto BadType - } - n := fv.Len() - if off+n > len(msg) { - return len(msg), false - } - reflect.Copy(reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue), fv) - off += n - case *reflect.StringValue: - // There are multiple string encodings. - // The tag distinguishes ordinary strings from domain names. - s := fv.Get() - switch f.Tag { - default: - fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) - return len(msg), false - case "domain-name": - off, ok = packDomainName(s, msg, off) - if !ok { - return len(msg), false - } - case "": - // Counted string: 1 byte length. - if len(s) > 255 || off+1+len(s) > len(msg) { - return len(msg), false - } - msg[off] = byte(len(s)) - off++ - off += copy(msg[off:], s) - } - } - } - return off, true -} - -func structValue(any interface{}) *reflect.StructValue { - return reflect.NewValue(any).(*reflect.PtrValue).Elem().(*reflect.StructValue) -} - -func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) { - off, ok = packStructValue(structValue(any), msg, off) - return off, ok -} - -// TODO(rsc): Move into generic library? -// Unpack a reflect.StructValue from msg. -// Same restrictions as packStructValue. -func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) { - for i := 0; i < val.NumField(); i++ { - f := val.Type().(*reflect.StructType).Field(i) - switch fv := val.Field(i).(type) { - default: - BadType: - fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) - return len(msg), false - case *reflect.StructValue: - off, ok = unpackStructValue(fv, msg, off) - case *reflect.UintValue: - switch fv.Type().Kind() { - default: - goto BadType - case reflect.Uint16: - if off+2 > len(msg) { - return len(msg), false - } - i := uint16(msg[off])<<8 | uint16(msg[off+1]) - fv.Set(uint64(i)) - off += 2 - case reflect.Uint32: - if off+4 > len(msg) { - return len(msg), false - } - i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) - fv.Set(uint64(i)) - off += 4 - } - case *reflect.ArrayValue: - if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 { - goto BadType - } - n := fv.Len() - if off+n > len(msg) { - return len(msg), false - } - reflect.Copy(fv, reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue)) - off += n - case *reflect.StringValue: - var s string - switch f.Tag { - default: - fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) - return len(msg), false - case "domain-name": - s, off, ok = unpackDomainName(msg, off) - if !ok { - return len(msg), false - } - case "": - if off >= len(msg) || off+1+int(msg[off]) > len(msg) { - return len(msg), false - } - n := int(msg[off]) - off++ - b := make([]byte, n) - for i := 0; i < n; i++ { - b[i] = msg[off+i] - } - off += n - s = string(b) - } - fv.Set(s) - } - } - return off, true -} - -func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) { - off, ok = unpackStructValue(structValue(any), msg, off) - return off, ok -} - -// Generic struct printer. -// Doesn't care about the string tag "domain-name", -// but does look for an "ipv4" tag on uint32 variables -// and the "ipv6" tag on array variables, -// printing them as IP addresses. -func printStructValue(val *reflect.StructValue) string { - s := "{" - for i := 0; i < val.NumField(); i++ { - if i > 0 { - s += ", " - } - f := val.Type().(*reflect.StructType).Field(i) - if !f.Anonymous { - s += f.Name + "=" - } - fval := val.Field(i) - if fv, ok := fval.(*reflect.StructValue); ok { - s += printStructValue(fv) - } else if fv, ok := fval.(*reflect.UintValue); ok && f.Tag == "ipv4" { - i := fv.Get() - s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String() - } else if fv, ok := fval.(*reflect.ArrayValue); ok && f.Tag == "ipv6" { - i := fv.Interface().([]byte) - s += IP(i).String() - } else { - s += fmt.Sprint(fval.Interface()) - } - } - s += "}" - return s -} - -func printStruct(any interface{}) string { return printStructValue(structValue(any)) } - -// Resource record packer. -func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) { - var off1 int - // pack twice, once to find end of header - // and again to find end of packet. - // a bit inefficient but this doesn't need to be fast. - // off1 is end of header - // off2 is end of rr - off1, ok = packStruct(rr.Header(), msg, off) - off2, ok = packStruct(rr, msg, off) - if !ok { - return len(msg), false - } - // pack a third time; redo header with correct data length - rr.Header().Rdlength = uint16(off2 - off1) - packStruct(rr.Header(), msg, off) - return off2, true -} - -// Resource record unpacker. -func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) { - // unpack just the header, to find the rr type and length - var h dnsRR_Header - off0 := off - if off, ok = unpackStruct(&h, msg, off); !ok { - return nil, len(msg), false - } - end := off + int(h.Rdlength) - - // make an rr of that type and re-unpack. - // again inefficient but doesn't need to be fast. - mk, known := rr_mk[int(h.Rrtype)] - if !known { - return &h, end, true - } - rr = mk() - off, ok = unpackStruct(rr, msg, off0) - if off != end { - return &h, end, true - } - return rr, off, ok -} - -// Usable representation of a DNS packet. - -// A manually-unpacked version of (id, bits). -// This is in its own struct for easy printing. -type dnsMsgHdr struct { - id uint16 - response bool - opcode int - authoritative bool - truncated bool - recursion_desired bool - recursion_available bool - rcode int -} - -type dnsMsg struct { - dnsMsgHdr - question []dnsQuestion - answer []dnsRR - ns []dnsRR - extra []dnsRR -} - -func (dns *dnsMsg) Pack() (msg []byte, ok bool) { - var dh dnsHeader - - // Convert convenient dnsMsg into wire-like dnsHeader. - dh.Id = dns.id - dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode) - if dns.recursion_available { - dh.Bits |= _RA - } - if dns.recursion_desired { - dh.Bits |= _RD - } - if dns.truncated { - dh.Bits |= _TC - } - if dns.authoritative { - dh.Bits |= _AA - } - if dns.response { - dh.Bits |= _QR - } - - // Prepare variable sized arrays. - question := dns.question - answer := dns.answer - ns := dns.ns - extra := dns.extra - - dh.Qdcount = uint16(len(question)) - dh.Ancount = uint16(len(answer)) - dh.Nscount = uint16(len(ns)) - dh.Arcount = uint16(len(extra)) - - // Could work harder to calculate message size, - // but this is far more than we need and not - // big enough to hurt the allocator. - msg = make([]byte, 2000) - - // Pack it in: header and then the pieces. - off := 0 - off, ok = packStruct(&dh, msg, off) - for i := 0; i < len(question); i++ { - off, ok = packStruct(&question[i], msg, off) - } - for i := 0; i < len(answer); i++ { - off, ok = packRR(answer[i], msg, off) - } - for i := 0; i < len(ns); i++ { - off, ok = packRR(ns[i], msg, off) - } - for i := 0; i < len(extra); i++ { - off, ok = packRR(extra[i], msg, off) - } - if !ok { - return nil, false - } - return msg[0:off], true -} - -func (dns *dnsMsg) Unpack(msg []byte) bool { - // Header. - var dh dnsHeader - off := 0 - var ok bool - if off, ok = unpackStruct(&dh, msg, off); !ok { - return false - } - dns.id = dh.Id - dns.response = (dh.Bits & _QR) != 0 - dns.opcode = int(dh.Bits>>11) & 0xF - dns.authoritative = (dh.Bits & _AA) != 0 - dns.truncated = (dh.Bits & _TC) != 0 - dns.recursion_desired = (dh.Bits & _RD) != 0 - dns.recursion_available = (dh.Bits & _RA) != 0 - dns.rcode = int(dh.Bits & 0xF) - - // Arrays. - dns.question = make([]dnsQuestion, dh.Qdcount) - dns.answer = make([]dnsRR, dh.Ancount) - dns.ns = make([]dnsRR, dh.Nscount) - dns.extra = make([]dnsRR, dh.Arcount) - - for i := 0; i < len(dns.question); i++ { - off, ok = unpackStruct(&dns.question[i], msg, off) - } - for i := 0; i < len(dns.answer); i++ { - dns.answer[i], off, ok = unpackRR(msg, off) - } - for i := 0; i < len(dns.ns); i++ { - dns.ns[i], off, ok = unpackRR(msg, off) - } - for i := 0; i < len(dns.extra); i++ { - dns.extra[i], off, ok = unpackRR(msg, off) - } - if !ok { - return false - } - // if off != len(msg) { - // println("extra bytes in dns packet", off, "<", len(msg)); - // } - return true -} - -func (dns *dnsMsg) String() string { - s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n" - if len(dns.question) > 0 { - s += "-- Questions\n" - for i := 0; i < len(dns.question); i++ { - s += printStruct(&dns.question[i]) + "\n" - } - } - if len(dns.answer) > 0 { - s += "-- Answers\n" - for i := 0; i < len(dns.answer); i++ { - s += printStruct(dns.answer[i]) + "\n" - } - } - if len(dns.ns) > 0 { - s += "-- Name servers\n" - for i := 0; i < len(dns.ns); i++ { - s += printStruct(dns.ns[i]) + "\n" - } - } - if len(dns.extra) > 0 { - s += "-- Extra\n" - for i := 0; i < len(dns.extra); i++ { - s += printStruct(dns.extra[i]) + "\n" - } - } - return s -} diff --git a/src/cmd/fix/testdata/reflect.dnsmsg.go.out b/src/cmd/fix/testdata/reflect.dnsmsg.go.out deleted file mode 100644 index c777fe27cb..0000000000 --- a/src/cmd/fix/testdata/reflect.dnsmsg.go.out +++ /dev/null @@ -1,777 +0,0 @@ -// 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. - -// DNS packet assembly. See RFC 1035. -// -// This is intended to support name resolution during net.Dial. -// It doesn't have to be blazing fast. -// -// Rather than write the usual handful of routines to pack and -// unpack every message that can appear on the wire, we use -// reflection to write a generic pack/unpack for structs and then -// use it. Thus, if in the future we need to define new message -// structs, no new pack/unpack/printing code needs to be written. -// -// The first half of this file defines the DNS message formats. -// The second half implements the conversion to and from wire format. -// A few of the structure elements have string tags to aid the -// generic pack/unpack routines. -// -// TODO(rsc): There are enough names defined in this file that they're all -// prefixed with dns. Perhaps put this in its own package later. - -package net - -import ( - "fmt" - "os" - "reflect" -) - -// Packet formats - -// Wire constants. -const ( - // valid dnsRR_Header.Rrtype and dnsQuestion.qtype - dnsTypeA = 1 - dnsTypeNS = 2 - dnsTypeMD = 3 - dnsTypeMF = 4 - dnsTypeCNAME = 5 - dnsTypeSOA = 6 - dnsTypeMB = 7 - dnsTypeMG = 8 - dnsTypeMR = 9 - dnsTypeNULL = 10 - dnsTypeWKS = 11 - dnsTypePTR = 12 - dnsTypeHINFO = 13 - dnsTypeMINFO = 14 - dnsTypeMX = 15 - dnsTypeTXT = 16 - dnsTypeAAAA = 28 - dnsTypeSRV = 33 - - // valid dnsQuestion.qtype only - dnsTypeAXFR = 252 - dnsTypeMAILB = 253 - dnsTypeMAILA = 254 - dnsTypeALL = 255 - - // valid dnsQuestion.qclass - dnsClassINET = 1 - dnsClassCSNET = 2 - dnsClassCHAOS = 3 - dnsClassHESIOD = 4 - dnsClassANY = 255 - - // dnsMsg.rcode - dnsRcodeSuccess = 0 - dnsRcodeFormatError = 1 - dnsRcodeServerFailure = 2 - dnsRcodeNameError = 3 - dnsRcodeNotImplemented = 4 - dnsRcodeRefused = 5 -) - -// The wire format for the DNS packet header. -type dnsHeader struct { - Id uint16 - Bits uint16 - Qdcount, Ancount, Nscount, Arcount uint16 -} - -const ( - // dnsHeader.Bits - _QR = 1 << 15 // query/response (response=1) - _AA = 1 << 10 // authoritative - _TC = 1 << 9 // truncated - _RD = 1 << 8 // recursion desired - _RA = 1 << 7 // recursion available -) - -// DNS queries. -type dnsQuestion struct { - Name string "domain-name" // "domain-name" specifies encoding; see packers below - Qtype uint16 - Qclass uint16 -} - -// DNS responses (resource records). -// There are many types of messages, -// but they all share the same header. -type dnsRR_Header struct { - Name string "domain-name" - Rrtype uint16 - Class uint16 - Ttl uint32 - Rdlength uint16 // length of data after header -} - -func (h *dnsRR_Header) Header() *dnsRR_Header { - return h -} - -type dnsRR interface { - Header() *dnsRR_Header -} - -// Specific DNS RR formats for each query type. - -type dnsRR_CNAME struct { - Hdr dnsRR_Header - Cname string "domain-name" -} - -func (rr *dnsRR_CNAME) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_HINFO struct { - Hdr dnsRR_Header - Cpu string - Os string -} - -func (rr *dnsRR_HINFO) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MB struct { - Hdr dnsRR_Header - Mb string "domain-name" -} - -func (rr *dnsRR_MB) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MG struct { - Hdr dnsRR_Header - Mg string "domain-name" -} - -func (rr *dnsRR_MG) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MINFO struct { - Hdr dnsRR_Header - Rmail string "domain-name" - Email string "domain-name" -} - -func (rr *dnsRR_MINFO) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MR struct { - Hdr dnsRR_Header - Mr string "domain-name" -} - -func (rr *dnsRR_MR) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_MX struct { - Hdr dnsRR_Header - Pref uint16 - Mx string "domain-name" -} - -func (rr *dnsRR_MX) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_NS struct { - Hdr dnsRR_Header - Ns string "domain-name" -} - -func (rr *dnsRR_NS) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_PTR struct { - Hdr dnsRR_Header - Ptr string "domain-name" -} - -func (rr *dnsRR_PTR) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_SOA struct { - Hdr dnsRR_Header - Ns string "domain-name" - Mbox string "domain-name" - Serial uint32 - Refresh uint32 - Retry uint32 - Expire uint32 - Minttl uint32 -} - -func (rr *dnsRR_SOA) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_TXT struct { - Hdr dnsRR_Header - Txt string // not domain name -} - -func (rr *dnsRR_TXT) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_SRV struct { - Hdr dnsRR_Header - Priority uint16 - Weight uint16 - Port uint16 - Target string "domain-name" -} - -func (rr *dnsRR_SRV) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_A struct { - Hdr dnsRR_Header - A uint32 "ipv4" -} - -func (rr *dnsRR_A) Header() *dnsRR_Header { - return &rr.Hdr -} - -type dnsRR_AAAA struct { - Hdr dnsRR_Header - AAAA [16]byte "ipv6" -} - -func (rr *dnsRR_AAAA) Header() *dnsRR_Header { - return &rr.Hdr -} - -// Packing and unpacking. -// -// All the packers and unpackers take a (msg []byte, off int) -// and return (off1 int, ok bool). If they return ok==false, they -// also return off1==len(msg), so that the next unpacker will -// also fail. This lets us avoid checks of ok until the end of a -// packing sequence. - -// Map of constructors for each RR wire type. -var rr_mk = map[int]func() dnsRR{ - dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) }, - dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) }, - dnsTypeMB: func() dnsRR { return new(dnsRR_MB) }, - dnsTypeMG: func() dnsRR { return new(dnsRR_MG) }, - dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) }, - dnsTypeMR: func() dnsRR { return new(dnsRR_MR) }, - dnsTypeMX: func() dnsRR { return new(dnsRR_MX) }, - dnsTypeNS: func() dnsRR { return new(dnsRR_NS) }, - dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) }, - dnsTypeSOA: func() dnsRR { return new(dnsRR_SOA) }, - dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) }, - dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) }, - dnsTypeA: func() dnsRR { return new(dnsRR_A) }, - dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) }, -} - -// Pack a domain name s into msg[off:]. -// Domain names are a sequence of counted strings -// split at the dots. They end with a zero-length string. -func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) { - // Add trailing dot to canonicalize name. - if n := len(s); n == 0 || s[n-1] != '.' { - s += "." - } - - // Each dot ends a segment of the name. - // We trade each dot byte for a length byte. - // There is also a trailing zero. - // Check that we have all the space we need. - tot := len(s) + 1 - if off+tot > len(msg) { - return len(msg), false - } - - // Emit sequence of counted strings, chopping at dots. - begin := 0 - for i := 0; i < len(s); i++ { - if s[i] == '.' { - if i-begin >= 1<<6 { // top two bits of length must be clear - return len(msg), false - } - msg[off] = byte(i - begin) - off++ - for j := begin; j < i; j++ { - msg[off] = s[j] - off++ - } - begin = i + 1 - } - } - msg[off] = 0 - off++ - return off, true -} - -// Unpack a domain name. -// In addition to the simple sequences of counted strings above, -// domain names are allowed to refer to strings elsewhere in the -// packet, to avoid repeating common suffixes when returning -// many entries in a single domain. The pointers are marked -// by a length byte with the top two bits set. Ignoring those -// two bits, that byte and the next give a 14 bit offset from msg[0] -// where we should pick up the trail. -// Note that if we jump elsewhere in the packet, -// we return off1 == the offset after the first pointer we found, -// which is where the next record will start. -// In theory, the pointers are only allowed to jump backward. -// We let them jump anywhere and stop jumping after a while. -func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) { - s = "" - ptr := 0 // number of pointers followed -Loop: - for { - if off >= len(msg) { - return "", len(msg), false - } - c := int(msg[off]) - off++ - switch c & 0xC0 { - case 0x00: - if c == 0x00 { - // end of name - break Loop - } - // literal string - if off+c > len(msg) { - return "", len(msg), false - } - s += string(msg[off:off+c]) + "." - off += c - case 0xC0: - // pointer to somewhere else in msg. - // remember location after first ptr, - // since that's how many bytes we consumed. - // also, don't follow too many pointers -- - // maybe there's a loop. - if off >= len(msg) { - return "", len(msg), false - } - c1 := msg[off] - off++ - if ptr == 0 { - off1 = off - } - if ptr++; ptr > 10 { - return "", len(msg), false - } - off = (c^0xC0)<<8 | int(c1) - default: - // 0x80 and 0x40 are reserved - return "", len(msg), false - } - } - if ptr == 0 { - off1 = off - } - return s, off1, true -} - -// TODO(rsc): Move into generic library? -// Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string, -// [n]byte, and other (often anonymous) structs. -func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) { - for i := 0; i < val.NumField(); i++ { - f := val.Type().Field(i) - switch fv := val.Field(i); fv.Kind() { - default: - BadType: - fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) - return len(msg), false - case reflect.Struct: - off, ok = packStructValue(fv, msg, off) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - i := fv.Uint() - switch fv.Type().Kind() { - default: - goto BadType - case reflect.Uint16: - if off+2 > len(msg) { - return len(msg), false - } - msg[off] = byte(i >> 8) - msg[off+1] = byte(i) - off += 2 - case reflect.Uint32: - if off+4 > len(msg) { - return len(msg), false - } - msg[off] = byte(i >> 24) - msg[off+1] = byte(i >> 16) - msg[off+2] = byte(i >> 8) - msg[off+3] = byte(i) - off += 4 - } - case reflect.Array: - if fv.Type().Elem().Kind() != reflect.Uint8 { - goto BadType - } - n := fv.Len() - if off+n > len(msg) { - return len(msg), false - } - reflect.Copy(reflect.ValueOf(msg[off:off+n]), fv) - off += n - case reflect.String: - // There are multiple string encodings. - // The tag distinguishes ordinary strings from domain names. - s := fv.String() - switch f.Tag { - default: - fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) - return len(msg), false - case "domain-name": - off, ok = packDomainName(s, msg, off) - if !ok { - return len(msg), false - } - case "": - // Counted string: 1 byte length. - if len(s) > 255 || off+1+len(s) > len(msg) { - return len(msg), false - } - msg[off] = byte(len(s)) - off++ - off += copy(msg[off:], s) - } - } - } - return off, true -} - -func structValue(any interface{}) reflect.Value { - return reflect.ValueOf(any).Elem() -} - -func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) { - off, ok = packStructValue(structValue(any), msg, off) - return off, ok -} - -// TODO(rsc): Move into generic library? -// Unpack a reflect.StructValue from msg. -// Same restrictions as packStructValue. -func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) { - for i := 0; i < val.NumField(); i++ { - f := val.Type().Field(i) - switch fv := val.Field(i); fv.Kind() { - default: - BadType: - fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) - return len(msg), false - case reflect.Struct: - off, ok = unpackStructValue(fv, msg, off) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - switch fv.Type().Kind() { - default: - goto BadType - case reflect.Uint16: - if off+2 > len(msg) { - return len(msg), false - } - i := uint16(msg[off])<<8 | uint16(msg[off+1]) - fv.SetUint(uint64(i)) - off += 2 - case reflect.Uint32: - if off+4 > len(msg) { - return len(msg), false - } - i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) - fv.SetUint(uint64(i)) - off += 4 - } - case reflect.Array: - if fv.Type().Elem().Kind() != reflect.Uint8 { - goto BadType - } - n := fv.Len() - if off+n > len(msg) { - return len(msg), false - } - reflect.Copy(fv, reflect.ValueOf(msg[off:off+n])) - off += n - case reflect.String: - var s string - switch f.Tag { - default: - fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) - return len(msg), false - case "domain-name": - s, off, ok = unpackDomainName(msg, off) - if !ok { - return len(msg), false - } - case "": - if off >= len(msg) || off+1+int(msg[off]) > len(msg) { - return len(msg), false - } - n := int(msg[off]) - off++ - b := make([]byte, n) - for i := 0; i < n; i++ { - b[i] = msg[off+i] - } - off += n - s = string(b) - } - fv.SetString(s) - } - } - return off, true -} - -func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) { - off, ok = unpackStructValue(structValue(any), msg, off) - return off, ok -} - -// Generic struct printer. -// Doesn't care about the string tag "domain-name", -// but does look for an "ipv4" tag on uint32 variables -// and the "ipv6" tag on array variables, -// printing them as IP addresses. -func printStructValue(val reflect.Value) string { - s := "{" - for i := 0; i < val.NumField(); i++ { - if i > 0 { - s += ", " - } - f := val.Type().Field(i) - if !f.Anonymous { - s += f.Name + "=" - } - fval := val.Field(i) - if fv := fval; fv.Kind() == reflect.Struct { - s += printStructValue(fv) - } else if fv := fval; (fv.Kind() == reflect.Uint || fv.Kind() == reflect.Uint8 || fv.Kind() == reflect.Uint16 || fv.Kind() == reflect.Uint32 || fv.Kind() == reflect.Uint64 || fv.Kind() == reflect.Uintptr) && f.Tag == "ipv4" { - i := fv.Uint() - s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String() - } else if fv := fval; fv.Kind() == reflect.Array && f.Tag == "ipv6" { - i := fv.Interface().([]byte) - s += IP(i).String() - } else { - s += fmt.Sprint(fval.Interface()) - } - } - s += "}" - return s -} - -func printStruct(any interface{}) string { return printStructValue(structValue(any)) } - -// Resource record packer. -func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) { - var off1 int - // pack twice, once to find end of header - // and again to find end of packet. - // a bit inefficient but this doesn't need to be fast. - // off1 is end of header - // off2 is end of rr - off1, ok = packStruct(rr.Header(), msg, off) - off2, ok = packStruct(rr, msg, off) - if !ok { - return len(msg), false - } - // pack a third time; redo header with correct data length - rr.Header().Rdlength = uint16(off2 - off1) - packStruct(rr.Header(), msg, off) - return off2, true -} - -// Resource record unpacker. -func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) { - // unpack just the header, to find the rr type and length - var h dnsRR_Header - off0 := off - if off, ok = unpackStruct(&h, msg, off); !ok { - return nil, len(msg), false - } - end := off + int(h.Rdlength) - - // make an rr of that type and re-unpack. - // again inefficient but doesn't need to be fast. - mk, known := rr_mk[int(h.Rrtype)] - if !known { - return &h, end, true - } - rr = mk() - off, ok = unpackStruct(rr, msg, off0) - if off != end { - return &h, end, true - } - return rr, off, ok -} - -// Usable representation of a DNS packet. - -// A manually-unpacked version of (id, bits). -// This is in its own struct for easy printing. -type dnsMsgHdr struct { - id uint16 - response bool - opcode int - authoritative bool - truncated bool - recursion_desired bool - recursion_available bool - rcode int -} - -type dnsMsg struct { - dnsMsgHdr - question []dnsQuestion - answer []dnsRR - ns []dnsRR - extra []dnsRR -} - -func (dns *dnsMsg) Pack() (msg []byte, ok bool) { - var dh dnsHeader - - // Convert convenient dnsMsg into wire-like dnsHeader. - dh.Id = dns.id - dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode) - if dns.recursion_available { - dh.Bits |= _RA - } - if dns.recursion_desired { - dh.Bits |= _RD - } - if dns.truncated { - dh.Bits |= _TC - } - if dns.authoritative { - dh.Bits |= _AA - } - if dns.response { - dh.Bits |= _QR - } - - // Prepare variable sized arrays. - question := dns.question - answer := dns.answer - ns := dns.ns - extra := dns.extra - - dh.Qdcount = uint16(len(question)) - dh.Ancount = uint16(len(answer)) - dh.Nscount = uint16(len(ns)) - dh.Arcount = uint16(len(extra)) - - // Could work harder to calculate message size, - // but this is far more than we need and not - // big enough to hurt the allocator. - msg = make([]byte, 2000) - - // Pack it in: header and then the pieces. - off := 0 - off, ok = packStruct(&dh, msg, off) - for i := 0; i < len(question); i++ { - off, ok = packStruct(&question[i], msg, off) - } - for i := 0; i < len(answer); i++ { - off, ok = packRR(answer[i], msg, off) - } - for i := 0; i < len(ns); i++ { - off, ok = packRR(ns[i], msg, off) - } - for i := 0; i < len(extra); i++ { - off, ok = packRR(extra[i], msg, off) - } - if !ok { - return nil, false - } - return msg[0:off], true -} - -func (dns *dnsMsg) Unpack(msg []byte) bool { - // Header. - var dh dnsHeader - off := 0 - var ok bool - if off, ok = unpackStruct(&dh, msg, off); !ok { - return false - } - dns.id = dh.Id - dns.response = (dh.Bits & _QR) != 0 - dns.opcode = int(dh.Bits>>11) & 0xF - dns.authoritative = (dh.Bits & _AA) != 0 - dns.truncated = (dh.Bits & _TC) != 0 - dns.recursion_desired = (dh.Bits & _RD) != 0 - dns.recursion_available = (dh.Bits & _RA) != 0 - dns.rcode = int(dh.Bits & 0xF) - - // Arrays. - dns.question = make([]dnsQuestion, dh.Qdcount) - dns.answer = make([]dnsRR, dh.Ancount) - dns.ns = make([]dnsRR, dh.Nscount) - dns.extra = make([]dnsRR, dh.Arcount) - - for i := 0; i < len(dns.question); i++ { - off, ok = unpackStruct(&dns.question[i], msg, off) - } - for i := 0; i < len(dns.answer); i++ { - dns.answer[i], off, ok = unpackRR(msg, off) - } - for i := 0; i < len(dns.ns); i++ { - dns.ns[i], off, ok = unpackRR(msg, off) - } - for i := 0; i < len(dns.extra); i++ { - dns.extra[i], off, ok = unpackRR(msg, off) - } - if !ok { - return false - } - // if off != len(msg) { - // println("extra bytes in dns packet", off, "<", len(msg)); - // } - return true -} - -func (dns *dnsMsg) String() string { - s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n" - if len(dns.question) > 0 { - s += "-- Questions\n" - for i := 0; i < len(dns.question); i++ { - s += printStruct(&dns.question[i]) + "\n" - } - } - if len(dns.answer) > 0 { - s += "-- Answers\n" - for i := 0; i < len(dns.answer); i++ { - s += printStruct(dns.answer[i]) + "\n" - } - } - if len(dns.ns) > 0 { - s += "-- Name servers\n" - for i := 0; i < len(dns.ns); i++ { - s += printStruct(dns.ns[i]) + "\n" - } - } - if len(dns.extra) > 0 { - s += "-- Extra\n" - for i := 0; i < len(dns.extra); i++ { - s += printStruct(dns.extra[i]) + "\n" - } - } - return s -} diff --git a/src/cmd/fix/testdata/reflect.encode.go.in b/src/cmd/fix/testdata/reflect.encode.go.in deleted file mode 100644 index 26ce47039f..0000000000 --- a/src/cmd/fix/testdata/reflect.encode.go.in +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2010 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. - -// The json package implements encoding and decoding of JSON objects as -// defined in RFC 4627. -package json - -import ( - "bytes" - "encoding/base64" - "os" - "reflect" - "runtime" - "sort" - "strconv" - "unicode" - "utf8" -) - -// Marshal returns the JSON encoding of v. -// -// Marshal traverses the value v recursively. -// If an encountered value implements the Marshaler interface, -// Marshal calls its MarshalJSON method to produce JSON. -// -// Otherwise, Marshal uses the following type-dependent default encodings: -// -// Boolean values encode as JSON booleans. -// -// Floating point and integer values encode as JSON numbers. -// -// String values encode as JSON strings, with each invalid UTF-8 sequence -// replaced by the encoding of the Unicode replacement character U+FFFD. -// -// Array and slice values encode as JSON arrays, except that -// []byte encodes as a base64-encoded string. -// -// Struct values encode as JSON objects. Each struct field becomes -// a member of the object. By default the object's key name is the -// struct field name. If the struct field has a non-empty tag consisting -// of only Unicode letters, digits, and underscores, that tag will be used -// as the name instead. Only exported fields will be encoded. -// -// Map values encode as JSON objects. -// The map's key type must be string; the object keys are used directly -// as map keys. -// -// Pointer values encode as the value pointed to. -// A nil pointer encodes as the null JSON object. -// -// Interface values encode as the value contained in the interface. -// A nil interface value encodes as the null JSON object. -// -// Channel, complex, and function values cannot be encoded in JSON. -// Attempting to encode such a value causes Marshal to return -// an InvalidTypeError. -// -// JSON cannot represent cyclic data structures and Marshal does not -// handle them. Passing cyclic structures to Marshal will result in -// an infinite recursion. -// -func Marshal(v interface{}) ([]byte, os.Error) { - e := &encodeState{} - err := e.marshal(v) - if err != nil { - return nil, err - } - return e.Bytes(), nil -} - -// MarshalIndent is like Marshal but applies Indent to format the output. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, os.Error) { - b, err := Marshal(v) - if err != nil { - return nil, err - } - var buf bytes.Buffer - err = Indent(&buf, b, prefix, indent) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalForHTML is like Marshal but applies HTMLEscape to the output. -func MarshalForHTML(v interface{}) ([]byte, os.Error) { - b, err := Marshal(v) - if err != nil { - return nil, err - } - var buf bytes.Buffer - HTMLEscape(&buf, b) - return buf.Bytes(), nil -} - -// HTMLEscape appends to dst the JSON-encoded src with <, >, and & -// characters inside string literals changed to \u003c, \u003e, \u0026 -// so that the JSON will be safe to embed inside HTML <script> tags. -// For historical reasons, web browsers don't honor standard HTML -// escaping within <script> tags, so an alternative JSON encoding must -// be used. -func HTMLEscape(dst *bytes.Buffer, src []byte) { - // < > & can only appear in string literals, - // so just scan the string one byte at a time. - start := 0 - for i, c := range src { - if c == '<' || c == '>' || c == '&' { - if start < i { - dst.Write(src[start:i]) - } - dst.WriteString(`\u00`) - dst.WriteByte(hex[c>>4]) - dst.WriteByte(hex[c&0xF]) - start = i + 1 - } - } - if start < len(src) { - dst.Write(src[start:]) - } -} - -// Marshaler is the interface implemented by objects that -// can marshal themselves into valid JSON. -type Marshaler interface { - MarshalJSON() ([]byte, os.Error) -} - -type UnsupportedTypeError struct { - Type reflect.Type -} - -func (e *UnsupportedTypeError) String() string { - return "json: unsupported type: " + e.Type.String() -} - -type InvalidUTF8Error struct { - S string -} - -func (e *InvalidUTF8Error) String() string { - return "json: invalid UTF-8 in string: " + strconv.Quote(e.S) -} - -type MarshalerError struct { - Type reflect.Type - Error os.Error -} - -func (e *MarshalerError) String() string { - return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Error.String() -} - -type interfaceOrPtrValue interface { - IsNil() bool - Elem() reflect.Value -} - -var hex = "0123456789abcdef" - -// An encodeState encodes JSON into a bytes.Buffer. -type encodeState struct { - bytes.Buffer // accumulated output -} - -func (e *encodeState) marshal(v interface{}) (err os.Error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(os.Error) - } - }() - e.reflectValue(reflect.NewValue(v)) - return nil -} - -func (e *encodeState) error(err os.Error) { - panic(err) -} - -var byteSliceType = reflect.Typeof([]byte(nil)) - -func (e *encodeState) reflectValue(v reflect.Value) { - if v == nil { - e.WriteString("null") - return - } - - if j, ok := v.Interface().(Marshaler); ok { - b, err := j.MarshalJSON() - if err == nil { - // copy JSON into buffer, checking validity. - err = Compact(&e.Buffer, b) - } - if err != nil { - e.error(&MarshalerError{v.Type(), err}) - } - return - } - - switch v := v.(type) { - case *reflect.BoolValue: - x := v.Get() - if x { - e.WriteString("true") - } else { - e.WriteString("false") - } - - case *reflect.IntValue: - e.WriteString(strconv.Itoa64(v.Get())) - - case *reflect.UintValue: - e.WriteString(strconv.Uitoa64(v.Get())) - - case *reflect.FloatValue: - e.WriteString(strconv.FtoaN(v.Get(), 'g', -1, v.Type().Bits())) - - case *reflect.StringValue: - e.string(v.Get()) - - case *reflect.StructValue: - e.WriteByte('{') - t := v.Type().(*reflect.StructType) - n := v.NumField() - first := true - for i := 0; i < n; i++ { - f := t.Field(i) - if f.PkgPath != "" { - continue - } - if first { - first = false - } else { - e.WriteByte(',') - } - if isValidTag(f.Tag) { - e.string(f.Tag) - } else { - e.string(f.Name) - } - e.WriteByte(':') - e.reflectValue(v.Field(i)) - } - e.WriteByte('}') - - case *reflect.MapValue: - if _, ok := v.Type().(*reflect.MapType).Key().(*reflect.StringType); !ok { - e.error(&UnsupportedTypeError{v.Type()}) - } - if v.IsNil() { - e.WriteString("null") - break - } - e.WriteByte('{') - var sv stringValues = v.Keys() - sort.Sort(sv) - for i, k := range sv { - if i > 0 { - e.WriteByte(',') - } - e.string(k.(*reflect.StringValue).Get()) - e.WriteByte(':') - e.reflectValue(v.Elem(k)) - } - e.WriteByte('}') - - case reflect.ArrayOrSliceValue: - if v.Type() == byteSliceType { - e.WriteByte('"') - s := v.Interface().([]byte) - if len(s) < 1024 { - // for small buffers, using Encode directly is much faster. - dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) - base64.StdEncoding.Encode(dst, s) - e.Write(dst) - } else { - // for large buffers, avoid unnecessary extra temporary - // buffer space. - enc := base64.NewEncoder(base64.StdEncoding, e) - enc.Write(s) - enc.Close() - } - e.WriteByte('"') - break - } - e.WriteByte('[') - n := v.Len() - for i := 0; i < n; i++ { - if i > 0 { - e.WriteByte(',') - } - e.reflectValue(v.Elem(i)) - } - e.WriteByte(']') - - case interfaceOrPtrValue: - if v.IsNil() { - e.WriteString("null") - return - } - e.reflectValue(v.Elem()) - - default: - e.error(&UnsupportedTypeError{v.Type()}) - } - return -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - return true -} - -// stringValues is a slice of reflect.Value holding *reflect.StringValue. -// It implements the methods to sort by string. -type stringValues []reflect.Value - -func (sv stringValues) Len() int { return len(sv) } -func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } -func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } -func (sv stringValues) get(i int) string { return sv[i].(*reflect.StringValue).Get() } - -func (e *encodeState) string(s string) { - e.WriteByte('"') - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if 0x20 <= b && b != '\\' && b != '"' { - i++ - continue - } - if start < i { - e.WriteString(s[start:i]) - } - if b == '\\' || b == '"' { - e.WriteByte('\\') - e.WriteByte(b) - } else { - e.WriteString(`\u00`) - e.WriteByte(hex[b>>4]) - e.WriteByte(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - e.error(&InvalidUTF8Error{s}) - } - i += size - } - if start < len(s) { - e.WriteString(s[start:]) - } - e.WriteByte('"') -} diff --git a/src/cmd/fix/testdata/reflect.encode.go.out b/src/cmd/fix/testdata/reflect.encode.go.out deleted file mode 100644 index 9a13a75ab7..0000000000 --- a/src/cmd/fix/testdata/reflect.encode.go.out +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2010 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. - -// The json package implements encoding and decoding of JSON objects as -// defined in RFC 4627. -package json - -import ( - "bytes" - "encoding/base64" - "os" - "reflect" - "runtime" - "sort" - "strconv" - "unicode" - "utf8" -) - -// Marshal returns the JSON encoding of v. -// -// Marshal traverses the value v recursively. -// If an encountered value implements the Marshaler interface, -// Marshal calls its MarshalJSON method to produce JSON. -// -// Otherwise, Marshal uses the following type-dependent default encodings: -// -// Boolean values encode as JSON booleans. -// -// Floating point and integer values encode as JSON numbers. -// -// String values encode as JSON strings, with each invalid UTF-8 sequence -// replaced by the encoding of the Unicode replacement character U+FFFD. -// -// Array and slice values encode as JSON arrays, except that -// []byte encodes as a base64-encoded string. -// -// Struct values encode as JSON objects. Each struct field becomes -// a member of the object. By default the object's key name is the -// struct field name. If the struct field has a non-empty tag consisting -// of only Unicode letters, digits, and underscores, that tag will be used -// as the name instead. Only exported fields will be encoded. -// -// Map values encode as JSON objects. -// The map's key type must be string; the object keys are used directly -// as map keys. -// -// Pointer values encode as the value pointed to. -// A nil pointer encodes as the null JSON object. -// -// Interface values encode as the value contained in the interface. -// A nil interface value encodes as the null JSON object. -// -// Channel, complex, and function values cannot be encoded in JSON. -// Attempting to encode such a value causes Marshal to return -// an InvalidTypeError. -// -// JSON cannot represent cyclic data structures and Marshal does not -// handle them. Passing cyclic structures to Marshal will result in -// an infinite recursion. -// -func Marshal(v interface{}) ([]byte, os.Error) { - e := &encodeState{} - err := e.marshal(v) - if err != nil { - return nil, err - } - return e.Bytes(), nil -} - -// MarshalIndent is like Marshal but applies Indent to format the output. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, os.Error) { - b, err := Marshal(v) - if err != nil { - return nil, err - } - var buf bytes.Buffer - err = Indent(&buf, b, prefix, indent) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// MarshalForHTML is like Marshal but applies HTMLEscape to the output. -func MarshalForHTML(v interface{}) ([]byte, os.Error) { - b, err := Marshal(v) - if err != nil { - return nil, err - } - var buf bytes.Buffer - HTMLEscape(&buf, b) - return buf.Bytes(), nil -} - -// HTMLEscape appends to dst the JSON-encoded src with <, >, and & -// characters inside string literals changed to \u003c, \u003e, \u0026 -// so that the JSON will be safe to embed inside HTML <script> tags. -// For historical reasons, web browsers don't honor standard HTML -// escaping within <script> tags, so an alternative JSON encoding must -// be used. -func HTMLEscape(dst *bytes.Buffer, src []byte) { - // < > & can only appear in string literals, - // so just scan the string one byte at a time. - start := 0 - for i, c := range src { - if c == '<' || c == '>' || c == '&' { - if start < i { - dst.Write(src[start:i]) - } - dst.WriteString(`\u00`) - dst.WriteByte(hex[c>>4]) - dst.WriteByte(hex[c&0xF]) - start = i + 1 - } - } - if start < len(src) { - dst.Write(src[start:]) - } -} - -// Marshaler is the interface implemented by objects that -// can marshal themselves into valid JSON. -type Marshaler interface { - MarshalJSON() ([]byte, os.Error) -} - -type UnsupportedTypeError struct { - Type reflect.Type -} - -func (e *UnsupportedTypeError) String() string { - return "json: unsupported type: " + e.Type.String() -} - -type InvalidUTF8Error struct { - S string -} - -func (e *InvalidUTF8Error) String() string { - return "json: invalid UTF-8 in string: " + strconv.Quote(e.S) -} - -type MarshalerError struct { - Type reflect.Type - Error os.Error -} - -func (e *MarshalerError) String() string { - return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Error.String() -} - -type interfaceOrPtrValue interface { - IsNil() bool - Elem() reflect.Value -} - -var hex = "0123456789abcdef" - -// An encodeState encodes JSON into a bytes.Buffer. -type encodeState struct { - bytes.Buffer // accumulated output -} - -func (e *encodeState) marshal(v interface{}) (err os.Error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(os.Error) - } - }() - e.reflectValue(reflect.ValueOf(v)) - return nil -} - -func (e *encodeState) error(err os.Error) { - panic(err) -} - -var byteSliceType = reflect.TypeOf([]byte(nil)) - -func (e *encodeState) reflectValue(v reflect.Value) { - if !v.IsValid() { - e.WriteString("null") - return - } - - if j, ok := v.Interface().(Marshaler); ok { - b, err := j.MarshalJSON() - if err == nil { - // copy JSON into buffer, checking validity. - err = Compact(&e.Buffer, b) - } - if err != nil { - e.error(&MarshalerError{v.Type(), err}) - } - return - } - - switch v.Kind() { - case reflect.Bool: - x := v.Bool() - if x { - e.WriteString("true") - } else { - e.WriteString("false") - } - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - e.WriteString(strconv.Itoa64(v.Int())) - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - e.WriteString(strconv.Uitoa64(v.Uint())) - - case reflect.Float32, reflect.Float64: - e.WriteString(strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits())) - - case reflect.String: - e.string(v.String()) - - case reflect.Struct: - e.WriteByte('{') - t := v.Type() - n := v.NumField() - first := true - for i := 0; i < n; i++ { - f := t.Field(i) - if f.PkgPath != "" { - continue - } - if first { - first = false - } else { - e.WriteByte(',') - } - if isValidTag(f.Tag) { - e.string(f.Tag) - } else { - e.string(f.Name) - } - e.WriteByte(':') - e.reflectValue(v.Field(i)) - } - e.WriteByte('}') - - case reflect.Map: - if v.Type().Key().Kind() != reflect.String { - e.error(&UnsupportedTypeError{v.Type()}) - } - if v.IsNil() { - e.WriteString("null") - break - } - e.WriteByte('{') - var sv stringValues = v.MapKeys() - sort.Sort(sv) - for i, k := range sv { - if i > 0 { - e.WriteByte(',') - } - e.string(k.String()) - e.WriteByte(':') - e.reflectValue(v.MapIndex(k)) - } - e.WriteByte('}') - - case reflect.Array, reflect.Slice: - if v.Type() == byteSliceType { - e.WriteByte('"') - s := v.Interface().([]byte) - if len(s) < 1024 { - // for small buffers, using Encode directly is much faster. - dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) - base64.StdEncoding.Encode(dst, s) - e.Write(dst) - } else { - // for large buffers, avoid unnecessary extra temporary - // buffer space. - enc := base64.NewEncoder(base64.StdEncoding, e) - enc.Write(s) - enc.Close() - } - e.WriteByte('"') - break - } - e.WriteByte('[') - n := v.Len() - for i := 0; i < n; i++ { - if i > 0 { - e.WriteByte(',') - } - e.reflectValue(v.Index(i)) - } - e.WriteByte(']') - - case interfaceOrPtrValue: - if v.IsNil() { - e.WriteString("null") - return - } - e.reflectValue(v.Elem()) - - default: - e.error(&UnsupportedTypeError{v.Type()}) - } - return -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - return true -} - -// stringValues is a slice of reflect.Value holding *reflect.StringValue. -// It implements the methods to sort by string. -type stringValues []reflect.Value - -func (sv stringValues) Len() int { return len(sv) } -func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } -func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) } -func (sv stringValues) get(i int) string { return sv[i].String() } - -func (e *encodeState) string(s string) { - e.WriteByte('"') - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if 0x20 <= b && b != '\\' && b != '"' { - i++ - continue - } - if start < i { - e.WriteString(s[start:i]) - } - if b == '\\' || b == '"' { - e.WriteByte('\\') - e.WriteByte(b) - } else { - e.WriteString(`\u00`) - e.WriteByte(hex[b>>4]) - e.WriteByte(hex[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - e.error(&InvalidUTF8Error{s}) - } - i += size - } - if start < len(s) { - e.WriteString(s[start:]) - } - e.WriteByte('"') -} diff --git a/src/cmd/fix/testdata/reflect.encoder.go.in b/src/cmd/fix/testdata/reflect.encoder.go.in deleted file mode 100644 index 702f6dc068..0000000000 --- a/src/cmd/fix/testdata/reflect.encoder.go.in +++ /dev/null @@ -1,240 +0,0 @@ -// 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. - -package gob - -import ( - "bytes" - "io" - "os" - "reflect" - "sync" -) - -// An Encoder manages the transmission of type and data information to the -// other side of a connection. -type Encoder struct { - mutex sync.Mutex // each item must be sent atomically - w []io.Writer // where to send the data - sent map[reflect.Type]typeId // which types we've already sent - countState *encoderState // stage for writing counts - freeList *encoderState // list of free encoderStates; avoids reallocation - buf []byte // for collecting the output. - byteBuf bytes.Buffer // buffer for top-level encoderState - err os.Error -} - -// NewEncoder returns a new encoder that will transmit on the io.Writer. -func NewEncoder(w io.Writer) *Encoder { - enc := new(Encoder) - enc.w = []io.Writer{w} - enc.sent = make(map[reflect.Type]typeId) - enc.countState = enc.newEncoderState(new(bytes.Buffer)) - return enc -} - -// writer() returns the innermost writer the encoder is using -func (enc *Encoder) writer() io.Writer { - return enc.w[len(enc.w)-1] -} - -// pushWriter adds a writer to the encoder. -func (enc *Encoder) pushWriter(w io.Writer) { - enc.w = append(enc.w, w) -} - -// popWriter pops the innermost writer. -func (enc *Encoder) popWriter() { - enc.w = enc.w[0 : len(enc.w)-1] -} - -func (enc *Encoder) badType(rt reflect.Type) { - enc.setError(os.NewError("gob: can't encode type " + rt.String())) -} - -func (enc *Encoder) setError(err os.Error) { - if enc.err == nil { // remember the first. - enc.err = err - } -} - -// writeMessage sends the data item preceded by a unsigned count of its length. -func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { - enc.countState.encodeUint(uint64(b.Len())) - // Build the buffer. - countLen := enc.countState.b.Len() - total := countLen + b.Len() - if total > len(enc.buf) { - enc.buf = make([]byte, total+1000) // extra for growth - } - // Place the length before the data. - // TODO(r): avoid the extra copy here. - enc.countState.b.Read(enc.buf[0:countLen]) - // Now the data. - b.Read(enc.buf[countLen:total]) - // Write the data. - _, err := w.Write(enc.buf[0:total]) - if err != nil { - enc.setError(err) - } -} - -// sendActualType sends the requested type, without further investigation, unless -// it's been sent before. -func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) { - if _, alreadySent := enc.sent[actual]; alreadySent { - return false - } - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - // Send the pair (-id, type) - // Id: - state.encodeInt(-int64(info.id)) - // Type: - enc.encode(state.b, reflect.NewValue(info.wire), wireTypeUserInfo) - enc.writeMessage(w, state.b) - if enc.err != nil { - return - } - - // Remember we've sent this type, both what the user gave us and the base type. - enc.sent[ut.base] = info.id - if ut.user != ut.base { - enc.sent[ut.user] = info.id - } - // Now send the inner types - switch st := actual.(type) { - case *reflect.StructType: - for i := 0; i < st.NumField(); i++ { - enc.sendType(w, state, st.Field(i).Type) - } - case reflect.ArrayOrSliceType: - enc.sendType(w, state, st.Elem()) - } - return true -} - -// sendType sends the type info to the other side, if necessary. -func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) { - ut := userType(origt) - if ut.isGobEncoder { - // The rules are different: regardless of the underlying type's representation, - // we need to tell the other side that this exact type is a GobEncoder. - return enc.sendActualType(w, state, ut, ut.user) - } - - // It's a concrete value, so drill down to the base type. - switch rt := ut.base.(type) { - default: - // Basic types and interfaces do not need to be described. - return - case *reflect.SliceType: - // If it's []uint8, don't send; it's considered basic. - if rt.Elem().Kind() == reflect.Uint8 { - return - } - // Otherwise we do send. - break - case *reflect.ArrayType: - // arrays must be sent so we know their lengths and element types. - break - case *reflect.MapType: - // maps must be sent so we know their lengths and key/value types. - break - case *reflect.StructType: - // structs must be sent so we know their fields. - break - case *reflect.ChanType, *reflect.FuncType: - // Probably a bad field in a struct. - enc.badType(rt) - return - } - - return enc.sendActualType(w, state, ut, ut.base) -} - -// Encode transmits the data item represented by the empty interface value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) Encode(e interface{}) os.Error { - return enc.EncodeValue(reflect.NewValue(e)) -} - -// sendTypeDescriptor makes sure the remote side knows about this type. -// It will send a descriptor if this is the first time the type has been -// sent. -func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) { - // Make sure the type is known to the other side. - // First, have we already sent this type? - rt := ut.base - if ut.isGobEncoder { - rt = ut.user - } - if _, alreadySent := enc.sent[rt]; !alreadySent { - // No, so send it. - sent := enc.sendType(w, state, rt) - if enc.err != nil { - return - } - // If the type info has still not been transmitted, it means we have - // a singleton basic type (int, []byte etc.) at top level. We don't - // need to send the type info but we do need to update enc.sent. - if !sent { - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - enc.sent[rt] = info.id - } - } -} - -// sendTypeId sends the id, which must have already been defined. -func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) { - // Identify the type of this top-level value. - state.encodeInt(int64(enc.sent[ut.base])) -} - -// EncodeValue transmits the data item represented by the reflection value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) EncodeValue(value reflect.Value) os.Error { - // Make sure we're single-threaded through here, so multiple - // goroutines can share an encoder. - enc.mutex.Lock() - defer enc.mutex.Unlock() - - // Remove any nested writers remaining due to previous errors. - enc.w = enc.w[0:1] - - ut, err := validUserType(value.Type()) - if err != nil { - return err - } - - enc.err = nil - enc.byteBuf.Reset() - state := enc.newEncoderState(&enc.byteBuf) - - enc.sendTypeDescriptor(enc.writer(), state, ut) - enc.sendTypeId(state, ut) - if enc.err != nil { - return enc.err - } - - // Encode the object. - enc.encode(state.b, value, ut) - if enc.err == nil { - enc.writeMessage(enc.writer(), state.b) - } - - enc.freeEncoderState(state) - return enc.err -} diff --git a/src/cmd/fix/testdata/reflect.encoder.go.out b/src/cmd/fix/testdata/reflect.encoder.go.out deleted file mode 100644 index f1a7b98f16..0000000000 --- a/src/cmd/fix/testdata/reflect.encoder.go.out +++ /dev/null @@ -1,240 +0,0 @@ -// 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. - -package gob - -import ( - "bytes" - "io" - "os" - "reflect" - "sync" -) - -// An Encoder manages the transmission of type and data information to the -// other side of a connection. -type Encoder struct { - mutex sync.Mutex // each item must be sent atomically - w []io.Writer // where to send the data - sent map[reflect.Type]typeId // which types we've already sent - countState *encoderState // stage for writing counts - freeList *encoderState // list of free encoderStates; avoids reallocation - buf []byte // for collecting the output. - byteBuf bytes.Buffer // buffer for top-level encoderState - err os.Error -} - -// NewEncoder returns a new encoder that will transmit on the io.Writer. -func NewEncoder(w io.Writer) *Encoder { - enc := new(Encoder) - enc.w = []io.Writer{w} - enc.sent = make(map[reflect.Type]typeId) - enc.countState = enc.newEncoderState(new(bytes.Buffer)) - return enc -} - -// writer() returns the innermost writer the encoder is using -func (enc *Encoder) writer() io.Writer { - return enc.w[len(enc.w)-1] -} - -// pushWriter adds a writer to the encoder. -func (enc *Encoder) pushWriter(w io.Writer) { - enc.w = append(enc.w, w) -} - -// popWriter pops the innermost writer. -func (enc *Encoder) popWriter() { - enc.w = enc.w[0 : len(enc.w)-1] -} - -func (enc *Encoder) badType(rt reflect.Type) { - enc.setError(os.NewError("gob: can't encode type " + rt.String())) -} - -func (enc *Encoder) setError(err os.Error) { - if enc.err == nil { // remember the first. - enc.err = err - } -} - -// writeMessage sends the data item preceded by a unsigned count of its length. -func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { - enc.countState.encodeUint(uint64(b.Len())) - // Build the buffer. - countLen := enc.countState.b.Len() - total := countLen + b.Len() - if total > len(enc.buf) { - enc.buf = make([]byte, total+1000) // extra for growth - } - // Place the length before the data. - // TODO(r): avoid the extra copy here. - enc.countState.b.Read(enc.buf[0:countLen]) - // Now the data. - b.Read(enc.buf[countLen:total]) - // Write the data. - _, err := w.Write(enc.buf[0:total]) - if err != nil { - enc.setError(err) - } -} - -// sendActualType sends the requested type, without further investigation, unless -// it's been sent before. -func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) { - if _, alreadySent := enc.sent[actual]; alreadySent { - return false - } - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - // Send the pair (-id, type) - // Id: - state.encodeInt(-int64(info.id)) - // Type: - enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo) - enc.writeMessage(w, state.b) - if enc.err != nil { - return - } - - // Remember we've sent this type, both what the user gave us and the base type. - enc.sent[ut.base] = info.id - if ut.user != ut.base { - enc.sent[ut.user] = info.id - } - // Now send the inner types - switch st := actual; st.Kind() { - case reflect.Struct: - for i := 0; i < st.NumField(); i++ { - enc.sendType(w, state, st.Field(i).Type) - } - case reflect.Array, reflect.Slice: - enc.sendType(w, state, st.Elem()) - } - return true -} - -// sendType sends the type info to the other side, if necessary. -func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) { - ut := userType(origt) - if ut.isGobEncoder { - // The rules are different: regardless of the underlying type's representation, - // we need to tell the other side that this exact type is a GobEncoder. - return enc.sendActualType(w, state, ut, ut.user) - } - - // It's a concrete value, so drill down to the base type. - switch rt := ut.base; rt.Kind() { - default: - // Basic types and interfaces do not need to be described. - return - case reflect.Slice: - // If it's []uint8, don't send; it's considered basic. - if rt.Elem().Kind() == reflect.Uint8 { - return - } - // Otherwise we do send. - break - case reflect.Array: - // arrays must be sent so we know their lengths and element types. - break - case reflect.Map: - // maps must be sent so we know their lengths and key/value types. - break - case reflect.Struct: - // structs must be sent so we know their fields. - break - case reflect.Chan, reflect.Func: - // Probably a bad field in a struct. - enc.badType(rt) - return - } - - return enc.sendActualType(w, state, ut, ut.base) -} - -// Encode transmits the data item represented by the empty interface value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) Encode(e interface{}) os.Error { - return enc.EncodeValue(reflect.ValueOf(e)) -} - -// sendTypeDescriptor makes sure the remote side knows about this type. -// It will send a descriptor if this is the first time the type has been -// sent. -func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) { - // Make sure the type is known to the other side. - // First, have we already sent this type? - rt := ut.base - if ut.isGobEncoder { - rt = ut.user - } - if _, alreadySent := enc.sent[rt]; !alreadySent { - // No, so send it. - sent := enc.sendType(w, state, rt) - if enc.err != nil { - return - } - // If the type info has still not been transmitted, it means we have - // a singleton basic type (int, []byte etc.) at top level. We don't - // need to send the type info but we do need to update enc.sent. - if !sent { - typeLock.Lock() - info, err := getTypeInfo(ut) - typeLock.Unlock() - if err != nil { - enc.setError(err) - return - } - enc.sent[rt] = info.id - } - } -} - -// sendTypeId sends the id, which must have already been defined. -func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) { - // Identify the type of this top-level value. - state.encodeInt(int64(enc.sent[ut.base])) -} - -// EncodeValue transmits the data item represented by the reflection value, -// guaranteeing that all necessary type information has been transmitted first. -func (enc *Encoder) EncodeValue(value reflect.Value) os.Error { - // Make sure we're single-threaded through here, so multiple - // goroutines can share an encoder. - enc.mutex.Lock() - defer enc.mutex.Unlock() - - // Remove any nested writers remaining due to previous errors. - enc.w = enc.w[0:1] - - ut, err := validUserType(value.Type()) - if err != nil { - return err - } - - enc.err = nil - enc.byteBuf.Reset() - state := enc.newEncoderState(&enc.byteBuf) - - enc.sendTypeDescriptor(enc.writer(), state, ut) - enc.sendTypeId(state, ut) - if enc.err != nil { - return enc.err - } - - // Encode the object. - enc.encode(state.b, value, ut) - if enc.err == nil { - enc.writeMessage(enc.writer(), state.b) - } - - enc.freeEncoderState(state) - return enc.err -} diff --git a/src/cmd/fix/testdata/reflect.export.go.in b/src/cmd/fix/testdata/reflect.export.go.in deleted file mode 100644 index 722387ac58..0000000000 --- a/src/cmd/fix/testdata/reflect.export.go.in +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2010 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. - -/* - The netchan package implements type-safe networked channels: - it allows the two ends of a channel to appear on different - computers connected by a network. It does this by transporting - data sent to a channel on one machine so it can be recovered - by a receive of a channel of the same type on the other. - - An exporter publishes a set of channels by name. An importer - connects to the exporting machine and imports the channels - by name. After importing the channels, the two machines can - use the channels in the usual way. - - Networked channels are not synchronized; they always behave - as if they are buffered channels of at least one element. -*/ -package netchan - -// BUG: can't use range clause to receive when using ImportNValues to limit the count. - -import ( - "io" - "log" - "net" - "os" - "reflect" - "strconv" - "sync" -) - -// Export - -// expLog is a logging convenience function. The first argument must be a string. -func expLog(args ...interface{}) { - args[0] = "netchan export: " + args[0].(string) - log.Print(args...) -} - -// An Exporter allows a set of channels to be published on a single -// network port. A single machine may have multiple Exporters -// but they must use different ports. -type Exporter struct { - *clientSet -} - -type expClient struct { - *encDec - exp *Exporter - chans map[int]*netChan // channels in use by client - mu sync.Mutex // protects remaining fields - errored bool // client has been sent an error - seqNum int64 // sequences messages sent to client; has value of highest sent - ackNum int64 // highest sequence number acknowledged - seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu -} - -func newClient(exp *Exporter, conn io.ReadWriter) *expClient { - client := new(expClient) - client.exp = exp - client.encDec = newEncDec(conn) - client.seqNum = 0 - client.ackNum = 0 - client.chans = make(map[int]*netChan) - return client -} - -func (client *expClient) sendError(hdr *header, err string) { - error := &error{err} - expLog("sending error to client:", error.Error) - client.encode(hdr, payError, error) // ignore any encode error, hope client gets it - client.mu.Lock() - client.errored = true - client.mu.Unlock() -} - -func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan { - exp := client.exp - exp.mu.Lock() - ech, ok := exp.names[name] - exp.mu.Unlock() - if !ok { - client.sendError(hdr, "no such channel: "+name) - return nil - } - if ech.dir != dir { - client.sendError(hdr, "wrong direction for channel: "+name) - return nil - } - nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count) - client.chans[hdr.Id] = nch - return nch -} - -func (client *expClient) getChan(hdr *header, dir Dir) *netChan { - nch := client.chans[hdr.Id] - if nch == nil { - return nil - } - if nch.dir != dir { - client.sendError(hdr, "wrong direction for channel: "+nch.name) - } - return nch -} - -// The function run manages sends and receives for a single client. For each -// (client Recv) request, this will launch a serveRecv goroutine to deliver -// the data for that channel, while (client Send) requests are handled as -// data arrives from the client. -func (client *expClient) run() { - hdr := new(header) - hdrValue := reflect.NewValue(hdr) - req := new(request) - reqValue := reflect.NewValue(req) - error := new(error) - for { - *hdr = header{} - if err := client.decode(hdrValue); err != nil { - if err != os.EOF { - expLog("error decoding client header:", err) - } - break - } - switch hdr.PayloadType { - case payRequest: - *req = request{} - if err := client.decode(reqValue); err != nil { - expLog("error decoding client request:", err) - break - } - if req.Size < 1 { - panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values") - } - switch req.Dir { - case Recv: - // look up channel before calling serveRecv to - // avoid a lock around client.chans. - if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil { - go client.serveRecv(nch, *hdr, req.Count) - } - case Send: - client.newChan(hdr, Recv, req.Name, req.Size, req.Count) - // The actual sends will have payload type payData. - // TODO: manage the count? - default: - error.Error = "request: can't handle channel direction" - expLog(error.Error, req.Dir) - client.encode(hdr, payError, error) - } - case payData: - client.serveSend(*hdr) - case payClosed: - client.serveClosed(*hdr) - case payAck: - client.mu.Lock() - if client.ackNum != hdr.SeqNum-1 { - // Since the sequence number is incremented and the message is sent - // in a single instance of locking client.mu, the messages are guaranteed - // to be sent in order. Therefore receipt of acknowledgement N means - // all messages <=N have been seen by the recipient. We check anyway. - expLog("sequence out of order:", client.ackNum, hdr.SeqNum) - } - if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. - client.ackNum = hdr.SeqNum - } - client.mu.Unlock() - case payAckSend: - if nch := client.getChan(hdr, Send); nch != nil { - nch.acked() - } - default: - log.Fatal("netchan export: unknown payload type", hdr.PayloadType) - } - } - client.exp.delClient(client) -} - -// Send all the data on a single channel to a client asking for a Recv. -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) { - for { - val, ok := nch.recv() - if !ok { - if err := client.encode(&hdr, payClosed, nil); err != nil { - expLog("error encoding server closed message:", err) - } - break - } - // We hold the lock during transmission to guarantee messages are - // sent in sequence number order. Also, we increment first so the - // value of client.SeqNum is the value of the highest used sequence - // number, not one beyond. - client.mu.Lock() - client.seqNum++ - hdr.SeqNum = client.seqNum - client.seqLock.Lock() // guarantee ordering of messages - client.mu.Unlock() - err := client.encode(&hdr, payData, val.Interface()) - client.seqLock.Unlock() - if err != nil { - expLog("error encoding client response:", err) - client.sendError(&hdr, err.String()) - break - } - // Negative count means run forever. - if count >= 0 { - if count--; count <= 0 { - break - } - } - } -} - -// Receive and deliver locally one item from a client asking for a Send -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveSend(hdr header) { - nch := client.getChan(&hdr, Recv) - if nch == nil { - return - } - // Create a new value for each received item. - val := reflect.MakeZero(nch.ch.Type().(*reflect.ChanType).Elem()) - if err := client.decode(val); err != nil { - expLog("value decode:", err, "; type ", nch.ch.Type()) - return - } - nch.send(val) -} - -// Report that client has closed the channel that is sending to us. -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveClosed(hdr header) { - nch := client.getChan(&hdr, Recv) - if nch == nil { - return - } - nch.close() -} - -func (client *expClient) unackedCount() int64 { - client.mu.Lock() - n := client.seqNum - client.ackNum - client.mu.Unlock() - return n -} - -func (client *expClient) seq() int64 { - client.mu.Lock() - n := client.seqNum - client.mu.Unlock() - return n -} - -func (client *expClient) ack() int64 { - client.mu.Lock() - n := client.seqNum - client.mu.Unlock() - return n -} - -// Serve waits for incoming connections on the listener -// and serves the Exporter's channels on each. -// It blocks until the listener is closed. -func (exp *Exporter) Serve(listener net.Listener) { - for { - conn, err := listener.Accept() - if err != nil { - expLog("listen:", err) - break - } - go exp.ServeConn(conn) - } -} - -// ServeConn exports the Exporter's channels on conn. -// It blocks until the connection is terminated. -func (exp *Exporter) ServeConn(conn io.ReadWriter) { - exp.addClient(conn).run() -} - -// NewExporter creates a new Exporter that exports a set of channels. -func NewExporter() *Exporter { - e := &Exporter{ - clientSet: &clientSet{ - names: make(map[string]*chanDir), - clients: make(map[unackedCounter]bool), - }, - } - return e -} - -// ListenAndServe exports the exporter's channels through the -// given network and local address defined as in net.Listen. -func (exp *Exporter) ListenAndServe(network, localaddr string) os.Error { - listener, err := net.Listen(network, localaddr) - if err != nil { - return err - } - go exp.Serve(listener) - return nil -} - -// addClient creates a new expClient and records its existence -func (exp *Exporter) addClient(conn io.ReadWriter) *expClient { - client := newClient(exp, conn) - exp.mu.Lock() - exp.clients[client] = true - exp.mu.Unlock() - return client -} - -// delClient forgets the client existed -func (exp *Exporter) delClient(client *expClient) { - exp.mu.Lock() - exp.clients[client] = false, false - exp.mu.Unlock() -} - -// Drain waits until all messages sent from this exporter/importer, including -// those not yet sent to any client and possibly including those sent while -// Drain was executing, have been received by the importer. In short, it -// waits until all the exporter's messages have been received by a client. -// If the timeout (measured in nanoseconds) is positive and Drain takes -// longer than that to complete, an error is returned. -func (exp *Exporter) Drain(timeout int64) os.Error { - // This wrapper function is here so the method's comment will appear in godoc. - return exp.clientSet.drain(timeout) -} - -// Sync waits until all clients of the exporter have received the messages -// that were sent at the time Sync was invoked. Unlike Drain, it does not -// wait for messages sent while it is running or messages that have not been -// dispatched to any client. If the timeout (measured in nanoseconds) is -// positive and Sync takes longer than that to complete, an error is -// returned. -func (exp *Exporter) Sync(timeout int64) os.Error { - // This wrapper function is here so the method's comment will appear in godoc. - return exp.clientSet.sync(timeout) -} - -func checkChan(chT interface{}, dir Dir) (*reflect.ChanValue, os.Error) { - chanType, ok := reflect.Typeof(chT).(*reflect.ChanType) - if !ok { - return nil, os.NewError("not a channel") - } - if dir != Send && dir != Recv { - return nil, os.NewError("unknown channel direction") - } - switch chanType.Dir() { - case reflect.BothDir: - case reflect.SendDir: - if dir != Recv { - return nil, os.NewError("to import/export with Send, must provide <-chan") - } - case reflect.RecvDir: - if dir != Send { - return nil, os.NewError("to import/export with Recv, must provide chan<-") - } - } - return reflect.NewValue(chT).(*reflect.ChanValue), nil -} - -// Export exports a channel of a given type and specified direction. The -// channel to be exported is provided in the call and may be of arbitrary -// channel type. -// Despite the literal signature, the effective signature is -// Export(name string, chT chan T, dir Dir) -func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error { - ch, err := checkChan(chT, dir) - if err != nil { - return err - } - exp.mu.Lock() - defer exp.mu.Unlock() - _, present := exp.names[name] - if present { - return os.NewError("channel name already being exported:" + name) - } - exp.names[name] = &chanDir{ch, dir} - return nil -} - -// Hangup disassociates the named channel from the Exporter and closes -// the channel. Messages in flight for the channel may be dropped. -func (exp *Exporter) Hangup(name string) os.Error { - exp.mu.Lock() - chDir, ok := exp.names[name] - if ok { - exp.names[name] = nil, false - } - // TODO drop all instances of channel from client sets - exp.mu.Unlock() - if !ok { - return os.NewError("netchan export: hangup: no such channel: " + name) - } - chDir.ch.Close() - return nil -} diff --git a/src/cmd/fix/testdata/reflect.export.go.out b/src/cmd/fix/testdata/reflect.export.go.out deleted file mode 100644 index d1324f3465..0000000000 --- a/src/cmd/fix/testdata/reflect.export.go.out +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2010 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. - -/* - The netchan package implements type-safe networked channels: - it allows the two ends of a channel to appear on different - computers connected by a network. It does this by transporting - data sent to a channel on one machine so it can be recovered - by a receive of a channel of the same type on the other. - - An exporter publishes a set of channels by name. An importer - connects to the exporting machine and imports the channels - by name. After importing the channels, the two machines can - use the channels in the usual way. - - Networked channels are not synchronized; they always behave - as if they are buffered channels of at least one element. -*/ -package netchan - -// BUG: can't use range clause to receive when using ImportNValues to limit the count. - -import ( - "io" - "log" - "net" - "os" - "reflect" - "strconv" - "sync" -) - -// Export - -// expLog is a logging convenience function. The first argument must be a string. -func expLog(args ...interface{}) { - args[0] = "netchan export: " + args[0].(string) - log.Print(args...) -} - -// An Exporter allows a set of channels to be published on a single -// network port. A single machine may have multiple Exporters -// but they must use different ports. -type Exporter struct { - *clientSet -} - -type expClient struct { - *encDec - exp *Exporter - chans map[int]*netChan // channels in use by client - mu sync.Mutex // protects remaining fields - errored bool // client has been sent an error - seqNum int64 // sequences messages sent to client; has value of highest sent - ackNum int64 // highest sequence number acknowledged - seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu -} - -func newClient(exp *Exporter, conn io.ReadWriter) *expClient { - client := new(expClient) - client.exp = exp - client.encDec = newEncDec(conn) - client.seqNum = 0 - client.ackNum = 0 - client.chans = make(map[int]*netChan) - return client -} - -func (client *expClient) sendError(hdr *header, err string) { - error := &error{err} - expLog("sending error to client:", error.Error) - client.encode(hdr, payError, error) // ignore any encode error, hope client gets it - client.mu.Lock() - client.errored = true - client.mu.Unlock() -} - -func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan { - exp := client.exp - exp.mu.Lock() - ech, ok := exp.names[name] - exp.mu.Unlock() - if !ok { - client.sendError(hdr, "no such channel: "+name) - return nil - } - if ech.dir != dir { - client.sendError(hdr, "wrong direction for channel: "+name) - return nil - } - nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count) - client.chans[hdr.Id] = nch - return nch -} - -func (client *expClient) getChan(hdr *header, dir Dir) *netChan { - nch := client.chans[hdr.Id] - if nch == nil { - return nil - } - if nch.dir != dir { - client.sendError(hdr, "wrong direction for channel: "+nch.name) - } - return nch -} - -// The function run manages sends and receives for a single client. For each -// (client Recv) request, this will launch a serveRecv goroutine to deliver -// the data for that channel, while (client Send) requests are handled as -// data arrives from the client. -func (client *expClient) run() { - hdr := new(header) - hdrValue := reflect.ValueOf(hdr) - req := new(request) - reqValue := reflect.ValueOf(req) - error := new(error) - for { - *hdr = header{} - if err := client.decode(hdrValue); err != nil { - if err != os.EOF { - expLog("error decoding client header:", err) - } - break - } - switch hdr.PayloadType { - case payRequest: - *req = request{} - if err := client.decode(reqValue); err != nil { - expLog("error decoding client request:", err) - break - } - if req.Size < 1 { - panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values") - } - switch req.Dir { - case Recv: - // look up channel before calling serveRecv to - // avoid a lock around client.chans. - if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil { - go client.serveRecv(nch, *hdr, req.Count) - } - case Send: - client.newChan(hdr, Recv, req.Name, req.Size, req.Count) - // The actual sends will have payload type payData. - // TODO: manage the count? - default: - error.Error = "request: can't handle channel direction" - expLog(error.Error, req.Dir) - client.encode(hdr, payError, error) - } - case payData: - client.serveSend(*hdr) - case payClosed: - client.serveClosed(*hdr) - case payAck: - client.mu.Lock() - if client.ackNum != hdr.SeqNum-1 { - // Since the sequence number is incremented and the message is sent - // in a single instance of locking client.mu, the messages are guaranteed - // to be sent in order. Therefore receipt of acknowledgement N means - // all messages <=N have been seen by the recipient. We check anyway. - expLog("sequence out of order:", client.ackNum, hdr.SeqNum) - } - if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. - client.ackNum = hdr.SeqNum - } - client.mu.Unlock() - case payAckSend: - if nch := client.getChan(hdr, Send); nch != nil { - nch.acked() - } - default: - log.Fatal("netchan export: unknown payload type", hdr.PayloadType) - } - } - client.exp.delClient(client) -} - -// Send all the data on a single channel to a client asking for a Recv. -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) { - for { - val, ok := nch.recv() - if !ok { - if err := client.encode(&hdr, payClosed, nil); err != nil { - expLog("error encoding server closed message:", err) - } - break - } - // We hold the lock during transmission to guarantee messages are - // sent in sequence number order. Also, we increment first so the - // value of client.SeqNum is the value of the highest used sequence - // number, not one beyond. - client.mu.Lock() - client.seqNum++ - hdr.SeqNum = client.seqNum - client.seqLock.Lock() // guarantee ordering of messages - client.mu.Unlock() - err := client.encode(&hdr, payData, val.Interface()) - client.seqLock.Unlock() - if err != nil { - expLog("error encoding client response:", err) - client.sendError(&hdr, err.String()) - break - } - // Negative count means run forever. - if count >= 0 { - if count--; count <= 0 { - break - } - } - } -} - -// Receive and deliver locally one item from a client asking for a Send -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveSend(hdr header) { - nch := client.getChan(&hdr, Recv) - if nch == nil { - return - } - // Create a new value for each received item. - val := reflect.Zero(nch.ch.Type().Elem()) - if err := client.decode(val); err != nil { - expLog("value decode:", err, "; type ", nch.ch.Type()) - return - } - nch.send(val) -} - -// Report that client has closed the channel that is sending to us. -// The header is passed by value to avoid issues of overwriting. -func (client *expClient) serveClosed(hdr header) { - nch := client.getChan(&hdr, Recv) - if nch == nil { - return - } - nch.close() -} - -func (client *expClient) unackedCount() int64 { - client.mu.Lock() - n := client.seqNum - client.ackNum - client.mu.Unlock() - return n -} - -func (client *expClient) seq() int64 { - client.mu.Lock() - n := client.seqNum - client.mu.Unlock() - return n -} - -func (client *expClient) ack() int64 { - client.mu.Lock() - n := client.seqNum - client.mu.Unlock() - return n -} - -// Serve waits for incoming connections on the listener -// and serves the Exporter's channels on each. -// It blocks until the listener is closed. -func (exp *Exporter) Serve(listener net.Listener) { - for { - conn, err := listener.Accept() - if err != nil { - expLog("listen:", err) - break - } - go exp.ServeConn(conn) - } -} - -// ServeConn exports the Exporter's channels on conn. -// It blocks until the connection is terminated. -func (exp *Exporter) ServeConn(conn io.ReadWriter) { - exp.addClient(conn).run() -} - -// NewExporter creates a new Exporter that exports a set of channels. -func NewExporter() *Exporter { - e := &Exporter{ - clientSet: &clientSet{ - names: make(map[string]*chanDir), - clients: make(map[unackedCounter]bool), - }, - } - return e -} - -// ListenAndServe exports the exporter's channels through the -// given network and local address defined as in net.Listen. -func (exp *Exporter) ListenAndServe(network, localaddr string) os.Error { - listener, err := net.Listen(network, localaddr) - if err != nil { - return err - } - go exp.Serve(listener) - return nil -} - -// addClient creates a new expClient and records its existence -func (exp *Exporter) addClient(conn io.ReadWriter) *expClient { - client := newClient(exp, conn) - exp.mu.Lock() - exp.clients[client] = true - exp.mu.Unlock() - return client -} - -// delClient forgets the client existed -func (exp *Exporter) delClient(client *expClient) { - exp.mu.Lock() - exp.clients[client] = false, false - exp.mu.Unlock() -} - -// Drain waits until all messages sent from this exporter/importer, including -// those not yet sent to any client and possibly including those sent while -// Drain was executing, have been received by the importer. In short, it -// waits until all the exporter's messages have been received by a client. -// If the timeout (measured in nanoseconds) is positive and Drain takes -// longer than that to complete, an error is returned. -func (exp *Exporter) Drain(timeout int64) os.Error { - // This wrapper function is here so the method's comment will appear in godoc. - return exp.clientSet.drain(timeout) -} - -// Sync waits until all clients of the exporter have received the messages -// that were sent at the time Sync was invoked. Unlike Drain, it does not -// wait for messages sent while it is running or messages that have not been -// dispatched to any client. If the timeout (measured in nanoseconds) is -// positive and Sync takes longer than that to complete, an error is -// returned. -func (exp *Exporter) Sync(timeout int64) os.Error { - // This wrapper function is here so the method's comment will appear in godoc. - return exp.clientSet.sync(timeout) -} - -func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) { - chanType := reflect.TypeOf(chT) - if chanType.Kind() != reflect.Chan { - return reflect.Value{}, os.NewError("not a channel") - } - if dir != Send && dir != Recv { - return reflect.Value{}, os.NewError("unknown channel direction") - } - switch chanType.ChanDir() { - case reflect.BothDir: - case reflect.SendDir: - if dir != Recv { - return reflect.Value{}, os.NewError("to import/export with Send, must provide <-chan") - } - case reflect.RecvDir: - if dir != Send { - return reflect.Value{}, os.NewError("to import/export with Recv, must provide chan<-") - } - } - return reflect.ValueOf(chT), nil -} - -// Export exports a channel of a given type and specified direction. The -// channel to be exported is provided in the call and may be of arbitrary -// channel type. -// Despite the literal signature, the effective signature is -// Export(name string, chT chan T, dir Dir) -func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error { - ch, err := checkChan(chT, dir) - if err != nil { - return err - } - exp.mu.Lock() - defer exp.mu.Unlock() - _, present := exp.names[name] - if present { - return os.NewError("channel name already being exported:" + name) - } - exp.names[name] = &chanDir{ch, dir} - return nil -} - -// Hangup disassociates the named channel from the Exporter and closes -// the channel. Messages in flight for the channel may be dropped. -func (exp *Exporter) Hangup(name string) os.Error { - exp.mu.Lock() - chDir, ok := exp.names[name] - if ok { - exp.names[name] = nil, false - } - // TODO drop all instances of channel from client sets - exp.mu.Unlock() - if !ok { - return os.NewError("netchan export: hangup: no such channel: " + name) - } - chDir.ch.Close() - return nil -} diff --git a/src/cmd/fix/testdata/reflect.print.go.in b/src/cmd/fix/testdata/reflect.print.go.in deleted file mode 100644 index 14cf2b215c..0000000000 --- a/src/cmd/fix/testdata/reflect.print.go.in +++ /dev/null @@ -1,944 +0,0 @@ -// 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. - -package fmt - -import ( - "bytes" - "io" - "os" - "reflect" - "utf8" -) - -// Some constants in the form of bytes, to avoid string overhead. -// Needlessly fastidious, I suppose. -var ( - commaSpaceBytes = []byte(", ") - nilAngleBytes = []byte("<nil>") - nilParenBytes = []byte("(nil)") - nilBytes = []byte("nil") - mapBytes = []byte("map[") - missingBytes = []byte("(MISSING)") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - widthBytes = []byte("%!(BADWIDTH)") - precBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") -) - -// State represents the printer state passed to custom formatters. -// It provides access to the io.Writer interface plus information about -// the flags and options for the operand's format specifier. -type State interface { - // Write is the function to call to emit formatted output to be printed. - Write(b []byte) (ret int, err os.Error) - // Width returns the value of the width option and whether it has been set. - Width() (wid int, ok bool) - // Precision returns the value of the precision option and whether it has been set. - Precision() (prec int, ok bool) - - // Flag returns whether the flag c, a character, has been set. - Flag(int) bool -} - -// Formatter is the interface implemented by values with a custom formatter. -// The implementation of Format may call Sprintf or Fprintf(f) etc. -// to generate its output. -type Formatter interface { - Format(f State, c int) -} - -// Stringer is implemented by any value that has a String method(), -// which defines the ``native'' format for that value. -// The String method is used to print values passed as an operand -// to a %s or %v format or to an unformatted printer such as Print. -type Stringer interface { - String() string -} - -// GoStringer is implemented by any value that has a GoString() method, -// which defines the Go syntax for that value. -// The GoString method is used to print values passed as an operand -// to a %#v format. -type GoStringer interface { - GoString() string -} - -type pp struct { - n int - buf bytes.Buffer - runeBuf [utf8.UTFMax]byte - fmt fmt -} - -// A cache holds a set of reusable objects. -// The buffered channel holds the currently available objects. -// If more are needed, the cache creates them by calling new. -type cache struct { - saved chan interface{} - new func() interface{} -} - -func (c *cache) put(x interface{}) { - select { - case c.saved <- x: - // saved in cache - default: - // discard - } -} - -func (c *cache) get() interface{} { - select { - case x := <-c.saved: - return x // reused from cache - default: - return c.new() - } - panic("not reached") -} - -func newCache(f func() interface{}) *cache { - return &cache{make(chan interface{}, 100), f} -} - -var ppFree = newCache(func() interface{} { return new(pp) }) - -// Allocate a new pp struct or grab a cached one. -func newPrinter() *pp { - p := ppFree.get().(*pp) - p.fmt.init(&p.buf) - return p -} - -// Save used pp structs in ppFree; avoids an allocation per invocation. -func (p *pp) free() { - // Don't hold on to pp structs with large buffers. - if cap(p.buf.Bytes()) > 1024 { - return - } - p.buf.Reset() - ppFree.put(p) -} - -func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent } - -func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent } - -func (p *pp) Flag(b int) bool { - switch b { - case '-': - return p.fmt.minus - case '+': - return p.fmt.plus - case '#': - return p.fmt.sharp - case ' ': - return p.fmt.space - case '0': - return p.fmt.zero - } - return false -} - -func (p *pp) add(c int) { - p.buf.WriteRune(c) -} - -// Implement Write so we can call Fprintf on a pp (through State), for -// recursive use in custom verbs. -func (p *pp) Write(b []byte) (ret int, err os.Error) { - return p.buf.Write(b) -} - -// These routines end in 'f' and take a format string. - -// Fprintf formats according to a format specifier and writes to w. -// It returns the number of bytes written and any write error encountered. -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrintf(format, a) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Printf formats according to a format specifier and writes to standard output. -// It returns the number of bytes written and any write error encountered. -func Printf(format string, a ...interface{}) (n int, errno os.Error) { - n, errno = Fprintf(os.Stdout, format, a...) - return n, errno -} - -// Sprintf formats according to a format specifier and returns the resulting string. -func Sprintf(format string, a ...interface{}) string { - p := newPrinter() - p.doPrintf(format, a) - s := p.buf.String() - p.free() - return s -} - -// Errorf formats according to a format specifier and returns the string -// converted to an os.ErrorString, which satisfies the os.Error interface. -func Errorf(format string, a ...interface{}) os.Error { - return os.NewError(Sprintf(format, a...)) -} - -// These routines do not take a format string - -// Fprint formats using the default formats for its operands and writes to w. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Fprint(w io.Writer, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrint(a, false, false) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Print formats using the default formats for its operands and writes to standard output. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Print(a ...interface{}) (n int, errno os.Error) { - n, errno = Fprint(os.Stdout, a...) - return n, errno -} - -// Sprint formats using the default formats for its operands and returns the resulting string. -// Spaces are added between operands when neither is a string. -func Sprint(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, false, false) - s := p.buf.String() - p.free() - return s -} - -// These routines end in 'ln', do not take a format string, -// always add spaces between operands, and add a newline -// after the last operand. - -// Fprintln formats using the default formats for its operands and writes to w. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Fprintln(w io.Writer, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrint(a, true, true) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Println formats using the default formats for its operands and writes to standard output. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Println(a ...interface{}) (n int, errno os.Error) { - n, errno = Fprintln(os.Stdout, a...) - return n, errno -} - -// Sprintln formats using the default formats for its operands and returns the resulting string. -// Spaces are always added between operands and a newline is appended. -func Sprintln(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, true, true) - s := p.buf.String() - p.free() - return s -} - -// Get the i'th arg of the struct value. -// If the arg itself is an interface, return a value for -// the thing inside the interface, not the interface itself. -func getField(v *reflect.StructValue, i int) reflect.Value { - val := v.Field(i) - if i, ok := val.(*reflect.InterfaceValue); ok { - if inter := i.Interface(); inter != nil { - return reflect.NewValue(inter) - } - } - return val -} - -// Convert ASCII to integer. n is 0 (and got is false) if no number present. -func parsenum(s string, start, end int) (num int, isnum bool, newi int) { - if start >= end { - return 0, false, end - } - for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ { - num = num*10 + int(s[newi]-'0') - isnum = true - } - return -} - -func (p *pp) unknownType(v interface{}) { - if v == nil { - p.buf.Write(nilAngleBytes) - return - } - p.buf.WriteByte('?') - p.buf.WriteString(reflect.Typeof(v).String()) - p.buf.WriteByte('?') -} - -func (p *pp) badVerb(verb int, val interface{}) { - p.add('%') - p.add('!') - p.add(verb) - p.add('(') - if val == nil { - p.buf.Write(nilAngleBytes) - } else { - p.buf.WriteString(reflect.Typeof(val).String()) - p.add('=') - p.printField(val, 'v', false, false, 0) - } - p.add(')') -} - -func (p *pp) fmtBool(v bool, verb int, value interface{}) { - switch verb { - case 't', 'v': - p.fmt.fmt_boolean(v) - default: - p.badVerb(verb, value) - } -} - -// fmtC formats a rune for the 'c' format. -func (p *pp) fmtC(c int64) { - rune := int(c) // Check for overflow. - if int64(rune) != c { - rune = utf8.RuneError - } - w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], rune) - p.fmt.pad(p.runeBuf[0:w]) -} - -func (p *pp) fmtInt64(v int64, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.integer(v, 2, signed, ldigits) - case 'c': - p.fmtC(v) - case 'd', 'v': - p.fmt.integer(v, 10, signed, ldigits) - case 'o': - p.fmt.integer(v, 8, signed, ldigits) - case 'x': - p.fmt.integer(v, 16, signed, ldigits) - case 'U': - p.fmtUnicode(v) - case 'X': - p.fmt.integer(v, 16, signed, udigits) - default: - p.badVerb(verb, value) - } -} - -// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or -// not, as requested, by temporarily setting the sharp flag. -func (p *pp) fmt0x64(v uint64, leading0x bool) { - sharp := p.fmt.sharp - p.fmt.sharp = leading0x - p.fmt.integer(int64(v), 16, unsigned, ldigits) - p.fmt.sharp = sharp -} - -// fmtUnicode formats a uint64 in U+1234 form by -// temporarily turning on the unicode flag and tweaking the precision. -func (p *pp) fmtUnicode(v int64) { - precPresent := p.fmt.precPresent - prec := p.fmt.prec - if !precPresent { - // If prec is already set, leave it alone; otherwise 4 is minimum. - p.fmt.prec = 4 - p.fmt.precPresent = true - } - p.fmt.unicode = true // turn on U+ - p.fmt.integer(int64(v), 16, unsigned, udigits) - p.fmt.unicode = false - p.fmt.prec = prec - p.fmt.precPresent = precPresent -} - -func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { - switch verb { - case 'b': - p.fmt.integer(int64(v), 2, unsigned, ldigits) - case 'c': - p.fmtC(int64(v)) - case 'd': - p.fmt.integer(int64(v), 10, unsigned, ldigits) - case 'v': - if goSyntax { - p.fmt0x64(v, true) - } else { - p.fmt.integer(int64(v), 10, unsigned, ldigits) - } - case 'o': - p.fmt.integer(int64(v), 8, unsigned, ldigits) - case 'x': - p.fmt.integer(int64(v), 16, unsigned, ldigits) - case 'X': - p.fmt.integer(int64(v), 16, unsigned, udigits) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat32(v float32, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.fmt_fb32(v) - case 'e': - p.fmt.fmt_e32(v) - case 'E': - p.fmt.fmt_E32(v) - case 'f': - p.fmt.fmt_f32(v) - case 'g', 'v': - p.fmt.fmt_g32(v) - case 'G': - p.fmt.fmt_G32(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat64(v float64, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.fmt_fb64(v) - case 'e': - p.fmt.fmt_e64(v) - case 'E': - p.fmt.fmt_E64(v) - case 'f': - p.fmt.fmt_f64(v) - case 'g', 'v': - p.fmt.fmt_g64(v) - case 'G': - p.fmt.fmt_G64(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex64(v complex64, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c64(v, verb) - case 'v': - p.fmt.fmt_c64(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex128(v complex128, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c128(v, verb) - case 'v': - p.fmt.fmt_c128(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) { - switch verb { - case 'v': - if goSyntax { - p.fmt.fmt_q(v) - } else { - p.fmt.fmt_s(v) - } - case 's': - p.fmt.fmt_s(v) - case 'x': - p.fmt.fmt_sx(v) - case 'X': - p.fmt.fmt_sX(v) - case 'q': - p.fmt.fmt_q(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}) { - if verb == 'v' || verb == 'd' { - if goSyntax { - p.buf.Write(bytesBytes) - } else { - p.buf.WriteByte('[') - } - for i, c := range v { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(c, 'v', p.fmt.plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - return - } - s := string(v) - switch verb { - case 's': - p.fmt.fmt_s(s) - case 'x': - p.fmt.fmt_sx(s) - case 'X': - p.fmt.fmt_sX(s) - case 'q': - p.fmt.fmt_q(s) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) { - var u uintptr - switch value.(type) { - case *reflect.ChanValue, *reflect.FuncValue, *reflect.MapValue, *reflect.PtrValue, *reflect.SliceValue, *reflect.UnsafePointerValue: - u = value.Pointer() - default: - p.badVerb(verb, field) - return - } - if goSyntax { - p.add('(') - p.buf.WriteString(reflect.Typeof(field).String()) - p.add(')') - p.add('(') - if u == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(u), true) - } - p.add(')') - } else { - p.fmt0x64(uint64(u), !p.fmt.sharp) - } -} - -var ( - intBits = reflect.Typeof(0).Bits() - floatBits = reflect.Typeof(0.0).Bits() - complexBits = reflect.Typeof(1i).Bits() - uintptrBits = reflect.Typeof(uintptr(0)).Bits() -) - -func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) { - if field == nil { - if verb == 'T' || verb == 'v' { - p.buf.Write(nilAngleBytes) - } else { - p.badVerb(verb, field) - } - return false - } - - // Special processing considerations. - // %T (the value's type) and %p (its address) are special; we always do them first. - switch verb { - case 'T': - p.printField(reflect.Typeof(field).String(), 's', false, false, 0) - return false - case 'p': - p.fmtPointer(field, reflect.NewValue(field), verb, goSyntax) - return false - } - // Is it a Formatter? - if formatter, ok := field.(Formatter); ok { - formatter.Format(p, verb) - return false // this value is not a string - - } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } - // If we're doing Go syntax and the field knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false - if stringer, ok := field.(GoStringer); ok { - // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false, field) - return false // this value is not a string - } - } else { - // Is it a Stringer? - if stringer, ok := field.(Stringer); ok { - p.printField(stringer.String(), verb, plus, false, depth) - return false // this value is not a string - } - } - - // Some types can be done without reflection. - switch f := field.(type) { - case bool: - p.fmtBool(f, verb, field) - return false - case float32: - p.fmtFloat32(f, verb, field) - return false - case float64: - p.fmtFloat64(f, verb, field) - return false - case complex64: - p.fmtComplex64(complex64(f), verb, field) - return false - case complex128: - p.fmtComplex128(f, verb, field) - return false - case int: - p.fmtInt64(int64(f), verb, field) - return false - case int8: - p.fmtInt64(int64(f), verb, field) - return false - case int16: - p.fmtInt64(int64(f), verb, field) - return false - case int32: - p.fmtInt64(int64(f), verb, field) - return false - case int64: - p.fmtInt64(f, verb, field) - return false - case uint: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint8: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint16: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint32: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint64: - p.fmtUint64(f, verb, goSyntax, field) - return false - case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case string: - p.fmtString(f, verb, goSyntax, field) - return verb == 's' || verb == 'v' - case []byte: - p.fmtBytes(f, verb, goSyntax, depth, field) - return verb == 's' - } - - // Need to use reflection - value := reflect.NewValue(field) - -BigSwitch: - switch f := value.(type) { - case *reflect.BoolValue: - p.fmtBool(f.Get(), verb, field) - case *reflect.IntValue: - p.fmtInt64(f.Get(), verb, field) - case *reflect.UintValue: - p.fmtUint64(uint64(f.Get()), verb, goSyntax, field) - case *reflect.FloatValue: - if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Get()), verb, field) - } else { - p.fmtFloat64(float64(f.Get()), verb, field) - } - case *reflect.ComplexValue: - if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Get()), verb, field) - } else { - p.fmtComplex128(complex128(f.Get()), verb, field) - } - case *reflect.StringValue: - p.fmtString(f.Get(), verb, goSyntax, field) - case *reflect.MapValue: - if goSyntax { - p.buf.WriteString(f.Type().String()) - p.buf.WriteByte('{') - } else { - p.buf.Write(mapBytes) - } - keys := f.Keys() - for i, key := range keys { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(key.Interface(), verb, plus, goSyntax, depth+1) - p.buf.WriteByte(':') - p.printField(f.Elem(key).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case *reflect.StructValue: - if goSyntax { - p.buf.WriteString(reflect.Typeof(field).String()) - } - p.add('{') - v := f - t := v.Type().(*reflect.StructType) - for i := 0; i < v.NumField(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - if plus || goSyntax { - if f := t.Field(i); f.Name != "" { - p.buf.WriteString(f.Name) - p.buf.WriteByte(':') - } - } - p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1) - } - p.buf.WriteByte('}') - case *reflect.InterfaceValue: - value := f.Elem() - if value == nil { - if goSyntax { - p.buf.WriteString(reflect.Typeof(field).String()) - p.buf.Write(nilParenBytes) - } else { - p.buf.Write(nilAngleBytes) - } - } else { - return p.printField(value.Interface(), verb, plus, goSyntax, depth+1) - } - case reflect.ArrayOrSliceValue: - // Byte slices are special. - if f.Type().(reflect.ArrayOrSliceType).Elem().Kind() == reflect.Uint8 { - // We know it's a slice of bytes, but we also know it does not have static type - // []byte, or it would have been caught above. Therefore we cannot convert - // it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have - // that type, and we can't write an expression of the right type and do a - // conversion because we don't have a static way to write the right type. - // So we build a slice by hand. This is a rare case but it would be nice - // if reflection could help a little more. - bytes := make([]byte, f.Len()) - for i := range bytes { - bytes[i] = byte(f.Elem(i).(*reflect.UintValue).Get()) - } - p.fmtBytes(bytes, verb, goSyntax, depth, field) - return verb == 's' - } - if goSyntax { - p.buf.WriteString(reflect.Typeof(field).String()) - p.buf.WriteByte('{') - } else { - p.buf.WriteByte('[') - } - for i := 0; i < f.Len(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(f.Elem(i).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case *reflect.PtrValue: - v := f.Get() - // pointer to array or slice or struct? ok at top level - // but not embedded (avoid loops) - if v != 0 && depth == 0 { - switch a := f.Elem().(type) { - case reflect.ArrayOrSliceValue: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - case *reflect.StructValue: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - } - } - if goSyntax { - p.buf.WriteByte('(') - p.buf.WriteString(reflect.Typeof(field).String()) - p.buf.WriteByte(')') - p.buf.WriteByte('(') - if v == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(v), true) - } - p.buf.WriteByte(')') - break - } - if v == 0 { - p.buf.Write(nilAngleBytes) - break - } - p.fmt0x64(uint64(v), true) - case *reflect.ChanValue, *reflect.FuncValue, *reflect.UnsafePointerValue: - p.fmtPointer(field, value, verb, goSyntax) - default: - p.unknownType(f) - } - return false -} - -// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int. -func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, newi, newfieldnum int) { - newi, newfieldnum = end, fieldnum - if i < end && fieldnum < len(a) { - num, isInt = a[fieldnum].(int) - newi, newfieldnum = i+1, fieldnum+1 - } - return -} - -func (p *pp) doPrintf(format string, a []interface{}) { - end := len(format) - fieldnum := 0 // we process one field per non-trivial format - for i := 0; i < end; { - lasti := i - for i < end && format[i] != '%' { - i++ - } - if i > lasti { - p.buf.WriteString(format[lasti:i]) - } - if i >= end { - // done processing format string - break - } - - // Process one verb - i++ - // flags and widths - p.fmt.clearflags() - F: - for ; i < end; i++ { - switch format[i] { - case '#': - p.fmt.sharp = true - case '0': - p.fmt.zero = true - case '+': - p.fmt.plus = true - case '-': - p.fmt.minus = true - case ' ': - p.fmt.space = true - default: - break F - } - } - // do we have width? - if i < end && format[i] == '*' { - p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum) - if !p.fmt.widPresent { - p.buf.Write(widthBytes) - } - } else { - p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end) - } - // do we have precision? - if i < end && format[i] == '.' { - if format[i+1] == '*' { - p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum) - if !p.fmt.precPresent { - p.buf.Write(precBytes) - } - } else { - p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end) - } - } - if i >= end { - p.buf.Write(noVerbBytes) - continue - } - c, w := utf8.DecodeRuneInString(format[i:]) - i += w - // percent is special - absorbs no operand - if c == '%' { - p.buf.WriteByte('%') // We ignore width and prec. - continue - } - if fieldnum >= len(a) { // out of operands - p.buf.WriteByte('%') - p.add(c) - p.buf.Write(missingBytes) - continue - } - field := a[fieldnum] - fieldnum++ - - goSyntax := c == 'v' && p.fmt.sharp - plus := c == 'v' && p.fmt.plus - p.printField(field, c, plus, goSyntax, 0) - } - - if fieldnum < len(a) { - p.buf.Write(extraBytes) - for ; fieldnum < len(a); fieldnum++ { - field := a[fieldnum] - if field != nil { - p.buf.WriteString(reflect.Typeof(field).String()) - p.buf.WriteByte('=') - } - p.printField(field, 'v', false, false, 0) - if fieldnum+1 < len(a) { - p.buf.Write(commaSpaceBytes) - } - } - p.buf.WriteByte(')') - } -} - -func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { - prevString := false - for fieldnum := 0; fieldnum < len(a); fieldnum++ { - p.fmt.clearflags() - // always add spaces if we're doing println - field := a[fieldnum] - if fieldnum > 0 { - isString := field != nil && reflect.Typeof(field).Kind() == reflect.String - if addspace || !isString && !prevString { - p.buf.WriteByte(' ') - } - } - prevString = p.printField(field, 'v', false, false, 0) - } - if addnewline { - p.buf.WriteByte('\n') - } -} diff --git a/src/cmd/fix/testdata/reflect.print.go.out b/src/cmd/fix/testdata/reflect.print.go.out deleted file mode 100644 index e4e4c73687..0000000000 --- a/src/cmd/fix/testdata/reflect.print.go.out +++ /dev/null @@ -1,944 +0,0 @@ -// 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. - -package fmt - -import ( - "bytes" - "io" - "os" - "reflect" - "utf8" -) - -// Some constants in the form of bytes, to avoid string overhead. -// Needlessly fastidious, I suppose. -var ( - commaSpaceBytes = []byte(", ") - nilAngleBytes = []byte("<nil>") - nilParenBytes = []byte("(nil)") - nilBytes = []byte("nil") - mapBytes = []byte("map[") - missingBytes = []byte("(MISSING)") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - widthBytes = []byte("%!(BADWIDTH)") - precBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") -) - -// State represents the printer state passed to custom formatters. -// It provides access to the io.Writer interface plus information about -// the flags and options for the operand's format specifier. -type State interface { - // Write is the function to call to emit formatted output to be printed. - Write(b []byte) (ret int, err os.Error) - // Width returns the value of the width option and whether it has been set. - Width() (wid int, ok bool) - // Precision returns the value of the precision option and whether it has been set. - Precision() (prec int, ok bool) - - // Flag returns whether the flag c, a character, has been set. - Flag(int) bool -} - -// Formatter is the interface implemented by values with a custom formatter. -// The implementation of Format may call Sprintf or Fprintf(f) etc. -// to generate its output. -type Formatter interface { - Format(f State, c int) -} - -// Stringer is implemented by any value that has a String method(), -// which defines the ``native'' format for that value. -// The String method is used to print values passed as an operand -// to a %s or %v format or to an unformatted printer such as Print. -type Stringer interface { - String() string -} - -// GoStringer is implemented by any value that has a GoString() method, -// which defines the Go syntax for that value. -// The GoString method is used to print values passed as an operand -// to a %#v format. -type GoStringer interface { - GoString() string -} - -type pp struct { - n int - buf bytes.Buffer - runeBuf [utf8.UTFMax]byte - fmt fmt -} - -// A cache holds a set of reusable objects. -// The buffered channel holds the currently available objects. -// If more are needed, the cache creates them by calling new. -type cache struct { - saved chan interface{} - new func() interface{} -} - -func (c *cache) put(x interface{}) { - select { - case c.saved <- x: - // saved in cache - default: - // discard - } -} - -func (c *cache) get() interface{} { - select { - case x := <-c.saved: - return x // reused from cache - default: - return c.new() - } - panic("not reached") -} - -func newCache(f func() interface{}) *cache { - return &cache{make(chan interface{}, 100), f} -} - -var ppFree = newCache(func() interface{} { return new(pp) }) - -// Allocate a new pp struct or grab a cached one. -func newPrinter() *pp { - p := ppFree.get().(*pp) - p.fmt.init(&p.buf) - return p -} - -// Save used pp structs in ppFree; avoids an allocation per invocation. -func (p *pp) free() { - // Don't hold on to pp structs with large buffers. - if cap(p.buf.Bytes()) > 1024 { - return - } - p.buf.Reset() - ppFree.put(p) -} - -func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent } - -func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent } - -func (p *pp) Flag(b int) bool { - switch b { - case '-': - return p.fmt.minus - case '+': - return p.fmt.plus - case '#': - return p.fmt.sharp - case ' ': - return p.fmt.space - case '0': - return p.fmt.zero - } - return false -} - -func (p *pp) add(c int) { - p.buf.WriteRune(c) -} - -// Implement Write so we can call Fprintf on a pp (through State), for -// recursive use in custom verbs. -func (p *pp) Write(b []byte) (ret int, err os.Error) { - return p.buf.Write(b) -} - -// These routines end in 'f' and take a format string. - -// Fprintf formats according to a format specifier and writes to w. -// It returns the number of bytes written and any write error encountered. -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrintf(format, a) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Printf formats according to a format specifier and writes to standard output. -// It returns the number of bytes written and any write error encountered. -func Printf(format string, a ...interface{}) (n int, errno os.Error) { - n, errno = Fprintf(os.Stdout, format, a...) - return n, errno -} - -// Sprintf formats according to a format specifier and returns the resulting string. -func Sprintf(format string, a ...interface{}) string { - p := newPrinter() - p.doPrintf(format, a) - s := p.buf.String() - p.free() - return s -} - -// Errorf formats according to a format specifier and returns the string -// converted to an os.ErrorString, which satisfies the os.Error interface. -func Errorf(format string, a ...interface{}) os.Error { - return os.NewError(Sprintf(format, a...)) -} - -// These routines do not take a format string - -// Fprint formats using the default formats for its operands and writes to w. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Fprint(w io.Writer, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrint(a, false, false) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Print formats using the default formats for its operands and writes to standard output. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Print(a ...interface{}) (n int, errno os.Error) { - n, errno = Fprint(os.Stdout, a...) - return n, errno -} - -// Sprint formats using the default formats for its operands and returns the resulting string. -// Spaces are added between operands when neither is a string. -func Sprint(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, false, false) - s := p.buf.String() - p.free() - return s -} - -// These routines end in 'ln', do not take a format string, -// always add spaces between operands, and add a newline -// after the last operand. - -// Fprintln formats using the default formats for its operands and writes to w. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Fprintln(w io.Writer, a ...interface{}) (n int, error os.Error) { - p := newPrinter() - p.doPrint(a, true, true) - n64, error := p.buf.WriteTo(w) - p.free() - return int(n64), error -} - -// Println formats using the default formats for its operands and writes to standard output. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Println(a ...interface{}) (n int, errno os.Error) { - n, errno = Fprintln(os.Stdout, a...) - return n, errno -} - -// Sprintln formats using the default formats for its operands and returns the resulting string. -// Spaces are always added between operands and a newline is appended. -func Sprintln(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, true, true) - s := p.buf.String() - p.free() - return s -} - -// Get the i'th arg of the struct value. -// If the arg itself is an interface, return a value for -// the thing inside the interface, not the interface itself. -func getField(v reflect.Value, i int) reflect.Value { - val := v.Field(i) - if i := val; i.Kind() == reflect.Interface { - if inter := i.Interface(); inter != nil { - return reflect.ValueOf(inter) - } - } - return val -} - -// Convert ASCII to integer. n is 0 (and got is false) if no number present. -func parsenum(s string, start, end int) (num int, isnum bool, newi int) { - if start >= end { - return 0, false, end - } - for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ { - num = num*10 + int(s[newi]-'0') - isnum = true - } - return -} - -func (p *pp) unknownType(v interface{}) { - if v == nil { - p.buf.Write(nilAngleBytes) - return - } - p.buf.WriteByte('?') - p.buf.WriteString(reflect.TypeOf(v).String()) - p.buf.WriteByte('?') -} - -func (p *pp) badVerb(verb int, val interface{}) { - p.add('%') - p.add('!') - p.add(verb) - p.add('(') - if val == nil { - p.buf.Write(nilAngleBytes) - } else { - p.buf.WriteString(reflect.TypeOf(val).String()) - p.add('=') - p.printField(val, 'v', false, false, 0) - } - p.add(')') -} - -func (p *pp) fmtBool(v bool, verb int, value interface{}) { - switch verb { - case 't', 'v': - p.fmt.fmt_boolean(v) - default: - p.badVerb(verb, value) - } -} - -// fmtC formats a rune for the 'c' format. -func (p *pp) fmtC(c int64) { - rune := int(c) // Check for overflow. - if int64(rune) != c { - rune = utf8.RuneError - } - w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], rune) - p.fmt.pad(p.runeBuf[0:w]) -} - -func (p *pp) fmtInt64(v int64, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.integer(v, 2, signed, ldigits) - case 'c': - p.fmtC(v) - case 'd', 'v': - p.fmt.integer(v, 10, signed, ldigits) - case 'o': - p.fmt.integer(v, 8, signed, ldigits) - case 'x': - p.fmt.integer(v, 16, signed, ldigits) - case 'U': - p.fmtUnicode(v) - case 'X': - p.fmt.integer(v, 16, signed, udigits) - default: - p.badVerb(verb, value) - } -} - -// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or -// not, as requested, by temporarily setting the sharp flag. -func (p *pp) fmt0x64(v uint64, leading0x bool) { - sharp := p.fmt.sharp - p.fmt.sharp = leading0x - p.fmt.integer(int64(v), 16, unsigned, ldigits) - p.fmt.sharp = sharp -} - -// fmtUnicode formats a uint64 in U+1234 form by -// temporarily turning on the unicode flag and tweaking the precision. -func (p *pp) fmtUnicode(v int64) { - precPresent := p.fmt.precPresent - prec := p.fmt.prec - if !precPresent { - // If prec is already set, leave it alone; otherwise 4 is minimum. - p.fmt.prec = 4 - p.fmt.precPresent = true - } - p.fmt.unicode = true // turn on U+ - p.fmt.integer(int64(v), 16, unsigned, udigits) - p.fmt.unicode = false - p.fmt.prec = prec - p.fmt.precPresent = precPresent -} - -func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { - switch verb { - case 'b': - p.fmt.integer(int64(v), 2, unsigned, ldigits) - case 'c': - p.fmtC(int64(v)) - case 'd': - p.fmt.integer(int64(v), 10, unsigned, ldigits) - case 'v': - if goSyntax { - p.fmt0x64(v, true) - } else { - p.fmt.integer(int64(v), 10, unsigned, ldigits) - } - case 'o': - p.fmt.integer(int64(v), 8, unsigned, ldigits) - case 'x': - p.fmt.integer(int64(v), 16, unsigned, ldigits) - case 'X': - p.fmt.integer(int64(v), 16, unsigned, udigits) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat32(v float32, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.fmt_fb32(v) - case 'e': - p.fmt.fmt_e32(v) - case 'E': - p.fmt.fmt_E32(v) - case 'f': - p.fmt.fmt_f32(v) - case 'g', 'v': - p.fmt.fmt_g32(v) - case 'G': - p.fmt.fmt_G32(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat64(v float64, verb int, value interface{}) { - switch verb { - case 'b': - p.fmt.fmt_fb64(v) - case 'e': - p.fmt.fmt_e64(v) - case 'E': - p.fmt.fmt_E64(v) - case 'f': - p.fmt.fmt_f64(v) - case 'g', 'v': - p.fmt.fmt_g64(v) - case 'G': - p.fmt.fmt_G64(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex64(v complex64, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c64(v, verb) - case 'v': - p.fmt.fmt_c64(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex128(v complex128, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c128(v, verb) - case 'v': - p.fmt.fmt_c128(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) { - switch verb { - case 'v': - if goSyntax { - p.fmt.fmt_q(v) - } else { - p.fmt.fmt_s(v) - } - case 's': - p.fmt.fmt_s(v) - case 'x': - p.fmt.fmt_sx(v) - case 'X': - p.fmt.fmt_sX(v) - case 'q': - p.fmt.fmt_q(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}) { - if verb == 'v' || verb == 'd' { - if goSyntax { - p.buf.Write(bytesBytes) - } else { - p.buf.WriteByte('[') - } - for i, c := range v { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(c, 'v', p.fmt.plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - return - } - s := string(v) - switch verb { - case 's': - p.fmt.fmt_s(s) - case 'x': - p.fmt.fmt_sx(s) - case 'X': - p.fmt.fmt_sX(s) - case 'q': - p.fmt.fmt_q(s) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) { - var u uintptr - switch value.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - u = value.Pointer() - default: - p.badVerb(verb, field) - return - } - if goSyntax { - p.add('(') - p.buf.WriteString(reflect.TypeOf(field).String()) - p.add(')') - p.add('(') - if u == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(u), true) - } - p.add(')') - } else { - p.fmt0x64(uint64(u), !p.fmt.sharp) - } -} - -var ( - intBits = reflect.TypeOf(0).Bits() - floatBits = reflect.TypeOf(0.0).Bits() - complexBits = reflect.TypeOf(1i).Bits() - uintptrBits = reflect.TypeOf(uintptr(0)).Bits() -) - -func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) { - if field == nil { - if verb == 'T' || verb == 'v' { - p.buf.Write(nilAngleBytes) - } else { - p.badVerb(verb, field) - } - return false - } - - // Special processing considerations. - // %T (the value's type) and %p (its address) are special; we always do them first. - switch verb { - case 'T': - p.printField(reflect.TypeOf(field).String(), 's', false, false, 0) - return false - case 'p': - p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax) - return false - } - // Is it a Formatter? - if formatter, ok := field.(Formatter); ok { - formatter.Format(p, verb) - return false // this value is not a string - - } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } - // If we're doing Go syntax and the field knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false - if stringer, ok := field.(GoStringer); ok { - // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false, field) - return false // this value is not a string - } - } else { - // Is it a Stringer? - if stringer, ok := field.(Stringer); ok { - p.printField(stringer.String(), verb, plus, false, depth) - return false // this value is not a string - } - } - - // Some types can be done without reflection. - switch f := field.(type) { - case bool: - p.fmtBool(f, verb, field) - return false - case float32: - p.fmtFloat32(f, verb, field) - return false - case float64: - p.fmtFloat64(f, verb, field) - return false - case complex64: - p.fmtComplex64(complex64(f), verb, field) - return false - case complex128: - p.fmtComplex128(f, verb, field) - return false - case int: - p.fmtInt64(int64(f), verb, field) - return false - case int8: - p.fmtInt64(int64(f), verb, field) - return false - case int16: - p.fmtInt64(int64(f), verb, field) - return false - case int32: - p.fmtInt64(int64(f), verb, field) - return false - case int64: - p.fmtInt64(f, verb, field) - return false - case uint: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint8: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint16: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint32: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint64: - p.fmtUint64(f, verb, goSyntax, field) - return false - case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case string: - p.fmtString(f, verb, goSyntax, field) - return verb == 's' || verb == 'v' - case []byte: - p.fmtBytes(f, verb, goSyntax, depth, field) - return verb == 's' - } - - // Need to use reflection - value := reflect.ValueOf(field) - -BigSwitch: - switch f := value; f.Kind() { - case reflect.Bool: - p.fmtBool(f.Bool(), verb, field) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p.fmtInt64(f.Int(), verb, field) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(uint64(f.Uint()), verb, goSyntax, field) - case reflect.Float32, reflect.Float64: - if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Float()), verb, field) - } else { - p.fmtFloat64(float64(f.Float()), verb, field) - } - case reflect.Complex64, reflect.Complex128: - if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Complex()), verb, field) - } else { - p.fmtComplex128(complex128(f.Complex()), verb, field) - } - case reflect.String: - p.fmtString(f.String(), verb, goSyntax, field) - case reflect.Map: - if goSyntax { - p.buf.WriteString(f.Type().String()) - p.buf.WriteByte('{') - } else { - p.buf.Write(mapBytes) - } - keys := f.MapKeys() - for i, key := range keys { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(key.Interface(), verb, plus, goSyntax, depth+1) - p.buf.WriteByte(':') - p.printField(f.MapIndex(key).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case reflect.Struct: - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - } - p.add('{') - v := f - t := v.Type() - for i := 0; i < v.NumField(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - if plus || goSyntax { - if f := t.Field(i); f.Name != "" { - p.buf.WriteString(f.Name) - p.buf.WriteByte(':') - } - } - p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1) - } - p.buf.WriteByte('}') - case reflect.Interface: - value := f.Elem() - if !value.IsValid() { - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.Write(nilParenBytes) - } else { - p.buf.Write(nilAngleBytes) - } - } else { - return p.printField(value.Interface(), verb, plus, goSyntax, depth+1) - } - case reflect.Array, reflect.Slice: - // Byte slices are special. - if f.Type().Elem().Kind() == reflect.Uint8 { - // We know it's a slice of bytes, but we also know it does not have static type - // []byte, or it would have been caught above. Therefore we cannot convert - // it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have - // that type, and we can't write an expression of the right type and do a - // conversion because we don't have a static way to write the right type. - // So we build a slice by hand. This is a rare case but it would be nice - // if reflection could help a little more. - bytes := make([]byte, f.Len()) - for i := range bytes { - bytes[i] = byte(f.Index(i).Uint()) - } - p.fmtBytes(bytes, verb, goSyntax, depth, field) - return verb == 's' - } - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte('{') - } else { - p.buf.WriteByte('[') - } - for i := 0; i < f.Len(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(f.Index(i).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case reflect.Ptr: - v := f.Pointer() - // pointer to array or slice or struct? ok at top level - // but not embedded (avoid loops) - if v != 0 && depth == 0 { - switch a := f.Elem(); a.Kind() { - case reflect.Array, reflect.Slice: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - case reflect.Struct: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - } - } - if goSyntax { - p.buf.WriteByte('(') - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte(')') - p.buf.WriteByte('(') - if v == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(v), true) - } - p.buf.WriteByte(')') - break - } - if v == 0 { - p.buf.Write(nilAngleBytes) - break - } - p.fmt0x64(uint64(v), true) - case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(field, value, verb, goSyntax) - default: - p.unknownType(f) - } - return false -} - -// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int. -func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, newi, newfieldnum int) { - newi, newfieldnum = end, fieldnum - if i < end && fieldnum < len(a) { - num, isInt = a[fieldnum].(int) - newi, newfieldnum = i+1, fieldnum+1 - } - return -} - -func (p *pp) doPrintf(format string, a []interface{}) { - end := len(format) - fieldnum := 0 // we process one field per non-trivial format - for i := 0; i < end; { - lasti := i - for i < end && format[i] != '%' { - i++ - } - if i > lasti { - p.buf.WriteString(format[lasti:i]) - } - if i >= end { - // done processing format string - break - } - - // Process one verb - i++ - // flags and widths - p.fmt.clearflags() - F: - for ; i < end; i++ { - switch format[i] { - case '#': - p.fmt.sharp = true - case '0': - p.fmt.zero = true - case '+': - p.fmt.plus = true - case '-': - p.fmt.minus = true - case ' ': - p.fmt.space = true - default: - break F - } - } - // do we have width? - if i < end && format[i] == '*' { - p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum) - if !p.fmt.widPresent { - p.buf.Write(widthBytes) - } - } else { - p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end) - } - // do we have precision? - if i < end && format[i] == '.' { - if format[i+1] == '*' { - p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum) - if !p.fmt.precPresent { - p.buf.Write(precBytes) - } - } else { - p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end) - } - } - if i >= end { - p.buf.Write(noVerbBytes) - continue - } - c, w := utf8.DecodeRuneInString(format[i:]) - i += w - // percent is special - absorbs no operand - if c == '%' { - p.buf.WriteByte('%') // We ignore width and prec. - continue - } - if fieldnum >= len(a) { // out of operands - p.buf.WriteByte('%') - p.add(c) - p.buf.Write(missingBytes) - continue - } - field := a[fieldnum] - fieldnum++ - - goSyntax := c == 'v' && p.fmt.sharp - plus := c == 'v' && p.fmt.plus - p.printField(field, c, plus, goSyntax, 0) - } - - if fieldnum < len(a) { - p.buf.Write(extraBytes) - for ; fieldnum < len(a); fieldnum++ { - field := a[fieldnum] - if field != nil { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte('=') - } - p.printField(field, 'v', false, false, 0) - if fieldnum+1 < len(a) { - p.buf.Write(commaSpaceBytes) - } - } - p.buf.WriteByte(')') - } -} - -func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { - prevString := false - for fieldnum := 0; fieldnum < len(a); fieldnum++ { - p.fmt.clearflags() - // always add spaces if we're doing println - field := a[fieldnum] - if fieldnum > 0 { - isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String - if addspace || !isString && !prevString { - p.buf.WriteByte(' ') - } - } - prevString = p.printField(field, 'v', false, false, 0) - } - if addnewline { - p.buf.WriteByte('\n') - } -} diff --git a/src/cmd/fix/testdata/reflect.quick.go.in b/src/cmd/fix/testdata/reflect.quick.go.in deleted file mode 100644 index a5568b0483..0000000000 --- a/src/cmd/fix/testdata/reflect.quick.go.in +++ /dev/null @@ -1,364 +0,0 @@ -// 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. - -// This package implements utility functions to help with black box testing. -package quick - -import ( - "flag" - "fmt" - "math" - "os" - "rand" - "reflect" - "strings" -) - -var defaultMaxCount *int = flag.Int("quickchecks", 100, "The default number of iterations for each check") - -// A Generator can generate random values of its own type. -type Generator interface { - // Generate returns a random instance of the type on which it is a - // method using the size as a size hint. - Generate(rand *rand.Rand, size int) reflect.Value -} - -// randFloat32 generates a random float taking the full range of a float32. -func randFloat32(rand *rand.Rand) float32 { - f := rand.Float64() * math.MaxFloat32 - if rand.Int()&1 == 1 { - f = -f - } - return float32(f) -} - -// randFloat64 generates a random float taking the full range of a float64. -func randFloat64(rand *rand.Rand) float64 { - f := rand.Float64() - if rand.Int()&1 == 1 { - f = -f - } - return f -} - -// randInt64 returns a random integer taking half the range of an int64. -func randInt64(rand *rand.Rand) int64 { return rand.Int63() - 1<<62 } - -// complexSize is the maximum length of arbitrary values that contain other -// values. -const complexSize = 50 - -// Value returns an arbitrary value of the given type. -// If the type implements the Generator interface, that will be used. -// Note: in order to create arbitrary values for structs, all the members must be public. -func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) { - if m, ok := reflect.MakeZero(t).Interface().(Generator); ok { - return m.Generate(rand, complexSize), true - } - - switch concrete := t.(type) { - case *reflect.BoolType: - return reflect.NewValue(rand.Int()&1 == 0), true - case *reflect.FloatType, *reflect.IntType, *reflect.UintType, *reflect.ComplexType: - switch t.Kind() { - case reflect.Float32: - return reflect.NewValue(randFloat32(rand)), true - case reflect.Float64: - return reflect.NewValue(randFloat64(rand)), true - case reflect.Complex64: - return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true - case reflect.Complex128: - return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true - case reflect.Int16: - return reflect.NewValue(int16(randInt64(rand))), true - case reflect.Int32: - return reflect.NewValue(int32(randInt64(rand))), true - case reflect.Int64: - return reflect.NewValue(randInt64(rand)), true - case reflect.Int8: - return reflect.NewValue(int8(randInt64(rand))), true - case reflect.Int: - return reflect.NewValue(int(randInt64(rand))), true - case reflect.Uint16: - return reflect.NewValue(uint16(randInt64(rand))), true - case reflect.Uint32: - return reflect.NewValue(uint32(randInt64(rand))), true - case reflect.Uint64: - return reflect.NewValue(uint64(randInt64(rand))), true - case reflect.Uint8: - return reflect.NewValue(uint8(randInt64(rand))), true - case reflect.Uint: - return reflect.NewValue(uint(randInt64(rand))), true - case reflect.Uintptr: - return reflect.NewValue(uintptr(randInt64(rand))), true - } - case *reflect.MapType: - numElems := rand.Intn(complexSize) - m := reflect.MakeMap(concrete) - for i := 0; i < numElems; i++ { - key, ok1 := Value(concrete.Key(), rand) - value, ok2 := Value(concrete.Elem(), rand) - if !ok1 || !ok2 { - return nil, false - } - m.SetElem(key, value) - } - return m, true - case *reflect.PtrType: - v, ok := Value(concrete.Elem(), rand) - if !ok { - return nil, false - } - p := reflect.MakeZero(concrete) - p.(*reflect.PtrValue).PointTo(v) - return p, true - case *reflect.SliceType: - numElems := rand.Intn(complexSize) - s := reflect.MakeSlice(concrete, numElems, numElems) - for i := 0; i < numElems; i++ { - v, ok := Value(concrete.Elem(), rand) - if !ok { - return nil, false - } - s.Elem(i).SetValue(v) - } - return s, true - case *reflect.StringType: - numChars := rand.Intn(complexSize) - codePoints := make([]int, numChars) - for i := 0; i < numChars; i++ { - codePoints[i] = rand.Intn(0x10ffff) - } - return reflect.NewValue(string(codePoints)), true - case *reflect.StructType: - s := reflect.MakeZero(t).(*reflect.StructValue) - for i := 0; i < s.NumField(); i++ { - v, ok := Value(concrete.Field(i).Type, rand) - if !ok { - return nil, false - } - s.Field(i).SetValue(v) - } - return s, true - default: - return nil, false - } - - return -} - -// A Config structure contains options for running a test. -type Config struct { - // MaxCount sets the maximum number of iterations. If zero, - // MaxCountScale is used. - MaxCount int - // MaxCountScale is a non-negative scale factor applied to the default - // maximum. If zero, the default is unchanged. - MaxCountScale float64 - // If non-nil, rand is a source of random numbers. Otherwise a default - // pseudo-random source will be used. - Rand *rand.Rand - // If non-nil, Values is a function which generates a slice of arbitrary - // Values that are congruent with the arguments to the function being - // tested. Otherwise, Values is used to generate the values. - Values func([]reflect.Value, *rand.Rand) -} - -var defaultConfig Config - -// getRand returns the *rand.Rand to use for a given Config. -func (c *Config) getRand() *rand.Rand { - if c.Rand == nil { - return rand.New(rand.NewSource(0)) - } - return c.Rand -} - -// getMaxCount returns the maximum number of iterations to run for a given -// Config. -func (c *Config) getMaxCount() (maxCount int) { - maxCount = c.MaxCount - if maxCount == 0 { - if c.MaxCountScale != 0 { - maxCount = int(c.MaxCountScale * float64(*defaultMaxCount)) - } else { - maxCount = *defaultMaxCount - } - } - - return -} - -// A SetupError is the result of an error in the way that check is being -// used, independent of the functions being tested. -type SetupError string - -func (s SetupError) String() string { return string(s) } - -// A CheckError is the result of Check finding an error. -type CheckError struct { - Count int - In []interface{} -} - -func (s *CheckError) String() string { - return fmt.Sprintf("#%d: failed on input %s", s.Count, toString(s.In)) -} - -// A CheckEqualError is the result CheckEqual finding an error. -type CheckEqualError struct { - CheckError - Out1 []interface{} - Out2 []interface{} -} - -func (s *CheckEqualError) String() string { - return fmt.Sprintf("#%d: failed on input %s. Output 1: %s. Output 2: %s", s.Count, toString(s.In), toString(s.Out1), toString(s.Out2)) -} - -// Check looks for an input to f, any function that returns bool, -// such that f returns false. It calls f repeatedly, with arbitrary -// values for each argument. If f returns false on a given input, -// Check returns that input as a *CheckError. -// For example: -// -// func TestOddMultipleOfThree(t *testing.T) { -// f := func(x int) bool { -// y := OddMultipleOfThree(x) -// return y%2 == 1 && y%3 == 0 -// } -// if err := quick.Check(f, nil); err != nil { -// t.Error(err) -// } -// } -func Check(function interface{}, config *Config) (err os.Error) { - if config == nil { - config = &defaultConfig - } - - f, fType, ok := functionAndType(function) - if !ok { - err = SetupError("argument is not a function") - return - } - - if fType.NumOut() != 1 { - err = SetupError("function returns more than one value.") - return - } - if _, ok := fType.Out(0).(*reflect.BoolType); !ok { - err = SetupError("function does not return a bool") - return - } - - arguments := make([]reflect.Value, fType.NumIn()) - rand := config.getRand() - maxCount := config.getMaxCount() - - for i := 0; i < maxCount; i++ { - err = arbitraryValues(arguments, fType, config, rand) - if err != nil { - return - } - - if !f.Call(arguments)[0].(*reflect.BoolValue).Get() { - err = &CheckError{i + 1, toInterfaces(arguments)} - return - } - } - - return -} - -// CheckEqual looks for an input on which f and g return different results. -// It calls f and g repeatedly with arbitrary values for each argument. -// If f and g return different answers, CheckEqual returns a *CheckEqualError -// describing the input and the outputs. -func CheckEqual(f, g interface{}, config *Config) (err os.Error) { - if config == nil { - config = &defaultConfig - } - - x, xType, ok := functionAndType(f) - if !ok { - err = SetupError("f is not a function") - return - } - y, yType, ok := functionAndType(g) - if !ok { - err = SetupError("g is not a function") - return - } - - if xType != yType { - err = SetupError("functions have different types") - return - } - - arguments := make([]reflect.Value, xType.NumIn()) - rand := config.getRand() - maxCount := config.getMaxCount() - - for i := 0; i < maxCount; i++ { - err = arbitraryValues(arguments, xType, config, rand) - if err != nil { - return - } - - xOut := toInterfaces(x.Call(arguments)) - yOut := toInterfaces(y.Call(arguments)) - - if !reflect.DeepEqual(xOut, yOut) { - err = &CheckEqualError{CheckError{i + 1, toInterfaces(arguments)}, xOut, yOut} - return - } - } - - return -} - -// arbitraryValues writes Values to args such that args contains Values -// suitable for calling f. -func arbitraryValues(args []reflect.Value, f *reflect.FuncType, config *Config, rand *rand.Rand) (err os.Error) { - if config.Values != nil { - config.Values(args, rand) - return - } - - for j := 0; j < len(args); j++ { - var ok bool - args[j], ok = Value(f.In(j), rand) - if !ok { - err = SetupError(fmt.Sprintf("cannot create arbitrary value of type %s for argument %d", f.In(j), j)) - return - } - } - - return -} - -func functionAndType(f interface{}) (v *reflect.FuncValue, t *reflect.FuncType, ok bool) { - v, ok = reflect.NewValue(f).(*reflect.FuncValue) - if !ok { - return - } - t = v.Type().(*reflect.FuncType) - return -} - -func toInterfaces(values []reflect.Value) []interface{} { - ret := make([]interface{}, len(values)) - for i, v := range values { - ret[i] = v.Interface() - } - return ret -} - -func toString(interfaces []interface{}) string { - s := make([]string, len(interfaces)) - for i, v := range interfaces { - s[i] = fmt.Sprintf("%#v", v) - } - return strings.Join(s, ", ") -} diff --git a/src/cmd/fix/testdata/reflect.quick.go.out b/src/cmd/fix/testdata/reflect.quick.go.out deleted file mode 100644 index c62305b832..0000000000 --- a/src/cmd/fix/testdata/reflect.quick.go.out +++ /dev/null @@ -1,365 +0,0 @@ -// 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. - -// This package implements utility functions to help with black box testing. -package quick - -import ( - "flag" - "fmt" - "math" - "os" - "rand" - "reflect" - "strings" -) - -var defaultMaxCount *int = flag.Int("quickchecks", 100, "The default number of iterations for each check") - -// A Generator can generate random values of its own type. -type Generator interface { - // Generate returns a random instance of the type on which it is a - // method using the size as a size hint. - Generate(rand *rand.Rand, size int) reflect.Value -} - -// randFloat32 generates a random float taking the full range of a float32. -func randFloat32(rand *rand.Rand) float32 { - f := rand.Float64() * math.MaxFloat32 - if rand.Int()&1 == 1 { - f = -f - } - return float32(f) -} - -// randFloat64 generates a random float taking the full range of a float64. -func randFloat64(rand *rand.Rand) float64 { - f := rand.Float64() - if rand.Int()&1 == 1 { - f = -f - } - return f -} - -// randInt64 returns a random integer taking half the range of an int64. -func randInt64(rand *rand.Rand) int64 { return rand.Int63() - 1<<62 } - -// complexSize is the maximum length of arbitrary values that contain other -// values. -const complexSize = 50 - -// Value returns an arbitrary value of the given type. -// If the type implements the Generator interface, that will be used. -// Note: in order to create arbitrary values for structs, all the members must be public. -func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) { - if m, ok := reflect.Zero(t).Interface().(Generator); ok { - return m.Generate(rand, complexSize), true - } - - switch concrete := t; concrete.Kind() { - case reflect.Bool: - return reflect.ValueOf(rand.Int()&1 == 0), true - case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Complex64, reflect.Complex128: - switch t.Kind() { - case reflect.Float32: - return reflect.ValueOf(randFloat32(rand)), true - case reflect.Float64: - return reflect.ValueOf(randFloat64(rand)), true - case reflect.Complex64: - return reflect.ValueOf(complex(randFloat32(rand), randFloat32(rand))), true - case reflect.Complex128: - return reflect.ValueOf(complex(randFloat64(rand), randFloat64(rand))), true - case reflect.Int16: - return reflect.ValueOf(int16(randInt64(rand))), true - case reflect.Int32: - return reflect.ValueOf(int32(randInt64(rand))), true - case reflect.Int64: - return reflect.ValueOf(randInt64(rand)), true - case reflect.Int8: - return reflect.ValueOf(int8(randInt64(rand))), true - case reflect.Int: - return reflect.ValueOf(int(randInt64(rand))), true - case reflect.Uint16: - return reflect.ValueOf(uint16(randInt64(rand))), true - case reflect.Uint32: - return reflect.ValueOf(uint32(randInt64(rand))), true - case reflect.Uint64: - return reflect.ValueOf(uint64(randInt64(rand))), true - case reflect.Uint8: - return reflect.ValueOf(uint8(randInt64(rand))), true - case reflect.Uint: - return reflect.ValueOf(uint(randInt64(rand))), true - case reflect.Uintptr: - return reflect.ValueOf(uintptr(randInt64(rand))), true - } - case reflect.Map: - numElems := rand.Intn(complexSize) - m := reflect.MakeMap(concrete) - for i := 0; i < numElems; i++ { - key, ok1 := Value(concrete.Key(), rand) - value, ok2 := Value(concrete.Elem(), rand) - if !ok1 || !ok2 { - return reflect.Value{}, false - } - m.SetMapIndex(key, value) - } - return m, true - case reflect.Ptr: - v, ok := Value(concrete.Elem(), rand) - if !ok { - return reflect.Value{}, false - } - p := reflect.Zero(concrete) - p.Set(v.Addr()) - return p, true - case reflect.Slice: - numElems := rand.Intn(complexSize) - s := reflect.MakeSlice(concrete, numElems, numElems) - for i := 0; i < numElems; i++ { - v, ok := Value(concrete.Elem(), rand) - if !ok { - return reflect.Value{}, false - } - s.Index(i).Set(v) - } - return s, true - case reflect.String: - numChars := rand.Intn(complexSize) - codePoints := make([]int, numChars) - for i := 0; i < numChars; i++ { - codePoints[i] = rand.Intn(0x10ffff) - } - return reflect.ValueOf(string(codePoints)), true - case reflect.Struct: - s := reflect.Zero(t) - for i := 0; i < s.NumField(); i++ { - v, ok := Value(concrete.Field(i).Type, rand) - if !ok { - return reflect.Value{}, false - } - s.Field(i).Set(v) - } - return s, true - default: - return reflect.Value{}, false - } - - return -} - -// A Config structure contains options for running a test. -type Config struct { - // MaxCount sets the maximum number of iterations. If zero, - // MaxCountScale is used. - MaxCount int - // MaxCountScale is a non-negative scale factor applied to the default - // maximum. If zero, the default is unchanged. - MaxCountScale float64 - // If non-nil, rand is a source of random numbers. Otherwise a default - // pseudo-random source will be used. - Rand *rand.Rand - // If non-nil, Values is a function which generates a slice of arbitrary - // Values that are congruent with the arguments to the function being - // tested. Otherwise, Values is used to generate the values. - Values func([]reflect.Value, *rand.Rand) -} - -var defaultConfig Config - -// getRand returns the *rand.Rand to use for a given Config. -func (c *Config) getRand() *rand.Rand { - if c.Rand == nil { - return rand.New(rand.NewSource(0)) - } - return c.Rand -} - -// getMaxCount returns the maximum number of iterations to run for a given -// Config. -func (c *Config) getMaxCount() (maxCount int) { - maxCount = c.MaxCount - if maxCount == 0 { - if c.MaxCountScale != 0 { - maxCount = int(c.MaxCountScale * float64(*defaultMaxCount)) - } else { - maxCount = *defaultMaxCount - } - } - - return -} - -// A SetupError is the result of an error in the way that check is being -// used, independent of the functions being tested. -type SetupError string - -func (s SetupError) String() string { return string(s) } - -// A CheckError is the result of Check finding an error. -type CheckError struct { - Count int - In []interface{} -} - -func (s *CheckError) String() string { - return fmt.Sprintf("#%d: failed on input %s", s.Count, toString(s.In)) -} - -// A CheckEqualError is the result CheckEqual finding an error. -type CheckEqualError struct { - CheckError - Out1 []interface{} - Out2 []interface{} -} - -func (s *CheckEqualError) String() string { - return fmt.Sprintf("#%d: failed on input %s. Output 1: %s. Output 2: %s", s.Count, toString(s.In), toString(s.Out1), toString(s.Out2)) -} - -// Check looks for an input to f, any function that returns bool, -// such that f returns false. It calls f repeatedly, with arbitrary -// values for each argument. If f returns false on a given input, -// Check returns that input as a *CheckError. -// For example: -// -// func TestOddMultipleOfThree(t *testing.T) { -// f := func(x int) bool { -// y := OddMultipleOfThree(x) -// return y%2 == 1 && y%3 == 0 -// } -// if err := quick.Check(f, nil); err != nil { -// t.Error(err) -// } -// } -func Check(function interface{}, config *Config) (err os.Error) { - if config == nil { - config = &defaultConfig - } - - f, fType, ok := functionAndType(function) - if !ok { - err = SetupError("argument is not a function") - return - } - - if fType.NumOut() != 1 { - err = SetupError("function returns more than one value.") - return - } - if fType.Out(0).Kind() != reflect.Bool { - err = SetupError("function does not return a bool") - return - } - - arguments := make([]reflect.Value, fType.NumIn()) - rand := config.getRand() - maxCount := config.getMaxCount() - - for i := 0; i < maxCount; i++ { - err = arbitraryValues(arguments, fType, config, rand) - if err != nil { - return - } - - if !f.Call(arguments)[0].Bool() { - err = &CheckError{i + 1, toInterfaces(arguments)} - return - } - } - - return -} - -// CheckEqual looks for an input on which f and g return different results. -// It calls f and g repeatedly with arbitrary values for each argument. -// If f and g return different answers, CheckEqual returns a *CheckEqualError -// describing the input and the outputs. -func CheckEqual(f, g interface{}, config *Config) (err os.Error) { - if config == nil { - config = &defaultConfig - } - - x, xType, ok := functionAndType(f) - if !ok { - err = SetupError("f is not a function") - return - } - y, yType, ok := functionAndType(g) - if !ok { - err = SetupError("g is not a function") - return - } - - if xType != yType { - err = SetupError("functions have different types") - return - } - - arguments := make([]reflect.Value, xType.NumIn()) - rand := config.getRand() - maxCount := config.getMaxCount() - - for i := 0; i < maxCount; i++ { - err = arbitraryValues(arguments, xType, config, rand) - if err != nil { - return - } - - xOut := toInterfaces(x.Call(arguments)) - yOut := toInterfaces(y.Call(arguments)) - - if !reflect.DeepEqual(xOut, yOut) { - err = &CheckEqualError{CheckError{i + 1, toInterfaces(arguments)}, xOut, yOut} - return - } - } - - return -} - -// arbitraryValues writes Values to args such that args contains Values -// suitable for calling f. -func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand *rand.Rand) (err os.Error) { - if config.Values != nil { - config.Values(args, rand) - return - } - - for j := 0; j < len(args); j++ { - var ok bool - args[j], ok = Value(f.In(j), rand) - if !ok { - err = SetupError(fmt.Sprintf("cannot create arbitrary value of type %s for argument %d", f.In(j), j)) - return - } - } - - return -} - -func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) { - v = reflect.ValueOf(f) - ok = v.Kind() == reflect.Func - if !ok { - return - } - t = v.Type() - return -} - -func toInterfaces(values []reflect.Value) []interface{} { - ret := make([]interface{}, len(values)) - for i, v := range values { - ret[i] = v.Interface() - } - return ret -} - -func toString(interfaces []interface{}) string { - s := make([]string, len(interfaces)) - for i, v := range interfaces { - s[i] = fmt.Sprintf("%#v", v) - } - return strings.Join(s, ", ") -} diff --git a/src/cmd/fix/testdata/reflect.read.go.in b/src/cmd/fix/testdata/reflect.read.go.in deleted file mode 100644 index 487994ac6e..0000000000 --- a/src/cmd/fix/testdata/reflect.read.go.in +++ /dev/null @@ -1,620 +0,0 @@ -// 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. - -package xml - -import ( - "bytes" - "fmt" - "io" - "os" - "reflect" - "strconv" - "strings" - "unicode" - "utf8" -) - -// BUG(rsc): Mapping between XML elements and data structures is inherently flawed: -// an XML element is an order-dependent collection of anonymous -// values, while a data structure is an order-independent collection -// of named values. -// See package json for a textual representation more suitable -// to data structures. - -// Unmarshal parses an XML element from r and uses the -// reflect library to fill in an arbitrary struct, slice, or string -// pointed at by val. Well-formed data that does not fit -// into val is discarded. -// -// For example, given these definitions: -// -// type Email struct { -// Where string "attr" -// Addr string -// } -// -// type Result struct { -// XMLName xml.Name "result" -// Name string -// Phone string -// Email []Email -// Groups []string "group>value" -// } -// -// result := Result{Name: "name", Phone: "phone", Email: nil} -// -// unmarshalling the XML input -// -// <result> -// <email where="home"> -// <addr>gre@example.com</addr> -// </email> -// <email where='work'> -// <addr>gre@work.com</addr> -// </email> -// <name>Grace R. Emlin</name> -// <group> -// <value>Friends</value> -// <value>Squash</value> -// </group> -// <address>123 Main Street</address> -// </result> -// -// via Unmarshal(r, &result) is equivalent to assigning -// -// r = Result{xml.Name{"", "result"}, -// "Grace R. Emlin", // name -// "phone", // no phone given -// []Email{ -// Email{"home", "gre@example.com"}, -// Email{"work", "gre@work.com"}, -// }, -// []string{"Friends", "Squash"}, -// } -// -// Note that the field r.Phone has not been modified and -// that the XML <address> element was discarded. Also, the field -// Groups was assigned considering the element path provided in the -// field tag. -// -// Because Unmarshal uses the reflect package, it can only -// assign to upper case fields. Unmarshal uses a case-insensitive -// comparison to match XML element names to struct field names. -// -// Unmarshal maps an XML element to a struct using the following rules: -// -// * If the struct has a field of type []byte or string with tag "innerxml", -// Unmarshal accumulates the raw XML nested inside the element -// in that field. The rest of the rules still apply. -// -// * If the struct has a field named XMLName of type xml.Name, -// Unmarshal records the element name in that field. -// -// * If the XMLName field has an associated tag string of the form -// "tag" or "namespace-URL tag", the XML element must have -// the given tag (and, optionally, name space) or else Unmarshal -// returns an error. -// -// * If the XML element has an attribute whose name matches a -// struct field of type string with tag "attr", Unmarshal records -// the attribute value in that field. -// -// * If the XML element contains character data, that data is -// accumulated in the first struct field that has tag "chardata". -// The struct field may have type []byte or string. -// If there is no such field, the character data is discarded. -// -// * If the XML element contains a sub-element whose name matches -// the prefix of a struct field tag formatted as "a>b>c", unmarshal -// will descend into the XML structure looking for elements with the -// given names, and will map the innermost elements to that struct field. -// A struct field tag starting with ">" is equivalent to one starting -// with the field name followed by ">". -// -// * If the XML element contains a sub-element whose name -// matches a struct field whose tag is neither "attr" nor "chardata", -// Unmarshal maps the sub-element to that struct field. -// Otherwise, if the struct has a field named Any, unmarshal -// maps the sub-element to that struct field. -// -// Unmarshal maps an XML element to a string or []byte by saving the -// concatenation of that element's character data in the string or []byte. -// -// Unmarshal maps an XML element to a slice by extending the length -// of the slice and mapping the element to the newly created value. -// -// Unmarshal maps an XML element to a bool by setting it to the boolean -// value represented by the string. -// -// Unmarshal maps an XML element to an integer or floating-point -// field by setting the field to the result of interpreting the string -// value in decimal. There is no check for overflow. -// -// Unmarshal maps an XML element to an xml.Name by recording the -// element name. -// -// Unmarshal maps an XML element to a pointer by setting the pointer -// to a freshly allocated value and then mapping the element to that value. -// -func Unmarshal(r io.Reader, val interface{}) os.Error { - v, ok := reflect.NewValue(val).(*reflect.PtrValue) - if !ok { - return os.NewError("non-pointer passed to Unmarshal") - } - p := NewParser(r) - elem := v.Elem() - err := p.unmarshal(elem, nil) - if err != nil { - return err - } - return nil -} - -// An UnmarshalError represents an error in the unmarshalling process. -type UnmarshalError string - -func (e UnmarshalError) String() string { return string(e) } - -// A TagPathError represents an error in the unmarshalling process -// caused by the use of field tags with conflicting paths. -type TagPathError struct { - Struct reflect.Type - Field1, Tag1 string - Field2, Tag2 string -} - -func (e *TagPathError) String() string { - return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2) -} - -// The Parser's Unmarshal method is like xml.Unmarshal -// except that it can be passed a pointer to the initial start element, -// useful when a client reads some raw XML tokens itself -// but also defers to Unmarshal for some elements. -// Passing a nil start element indicates that Unmarshal should -// read the token stream to find the start element. -func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error { - v, ok := reflect.NewValue(val).(*reflect.PtrValue) - if !ok { - return os.NewError("non-pointer passed to Unmarshal") - } - return p.unmarshal(v.Elem(), start) -} - -// fieldName strips invalid characters from an XML name -// to create a valid Go struct name. It also converts the -// name to lower case letters. -func fieldName(original string) string { - - var i int - //remove leading underscores - for i = 0; i < len(original) && original[i] == '_'; i++ { - } - - return strings.Map( - func(x int) int { - if x == '_' || unicode.IsDigit(x) || unicode.IsLetter(x) { - return unicode.ToLower(x) - } - return -1 - }, - original[i:]) -} - -// Unmarshal a single XML element into val. -func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error { - // Find start element if we need it. - if start == nil { - for { - tok, err := p.Token() - if err != nil { - return err - } - if t, ok := tok.(StartElement); ok { - start = &t - break - } - } - } - - if pv, ok := val.(*reflect.PtrValue); ok { - if pv.Get() == 0 { - zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem()) - pv.PointTo(zv) - val = zv - } else { - val = pv.Elem() - } - } - - var ( - data []byte - saveData reflect.Value - comment []byte - saveComment reflect.Value - saveXML reflect.Value - saveXMLIndex int - saveXMLData []byte - sv *reflect.StructValue - styp *reflect.StructType - fieldPaths map[string]pathInfo - ) - - switch v := val.(type) { - default: - return os.NewError("unknown type " + v.Type().String()) - - case *reflect.SliceValue: - typ := v.Type().(*reflect.SliceType) - if typ.Elem().Kind() == reflect.Uint8 { - // []byte - saveData = v - break - } - - // Slice of element values. - // Grow slice. - n := v.Len() - if n >= v.Cap() { - ncap := 2 * n - if ncap < 4 { - ncap = 4 - } - new := reflect.MakeSlice(typ, n, ncap) - reflect.Copy(new, v) - v.Set(new) - } - v.SetLen(n + 1) - - // Recur to read element into slice. - if err := p.unmarshal(v.Elem(n), start); err != nil { - v.SetLen(n) - return err - } - return nil - - case *reflect.BoolValue, *reflect.FloatValue, *reflect.IntValue, *reflect.UintValue, *reflect.StringValue: - saveData = v - - case *reflect.StructValue: - if _, ok := v.Interface().(Name); ok { - v.Set(reflect.NewValue(start.Name).(*reflect.StructValue)) - break - } - - sv = v - typ := sv.Type().(*reflect.StructType) - styp = typ - // Assign name. - if f, ok := typ.FieldByName("XMLName"); ok { - // Validate element name. - if f.Tag != "" { - tag := f.Tag - ns := "" - i := strings.LastIndex(tag, " ") - if i >= 0 { - ns, tag = tag[0:i], tag[i+1:] - } - if tag != start.Name.Local { - return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">") - } - if ns != "" && ns != start.Name.Space { - e := "expected element <" + tag + "> in name space " + ns + " but have " - if start.Name.Space == "" { - e += "no name space" - } else { - e += start.Name.Space - } - return UnmarshalError(e) - } - } - - // Save - v := sv.FieldByIndex(f.Index) - if _, ok := v.Interface().(Name); !ok { - return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name") - } - v.(*reflect.StructValue).Set(reflect.NewValue(start.Name).(*reflect.StructValue)) - } - - // Assign attributes. - // Also, determine whether we need to save character data or comments. - for i, n := 0, typ.NumField(); i < n; i++ { - f := typ.Field(i) - switch f.Tag { - case "attr": - strv, ok := sv.FieldByIndex(f.Index).(*reflect.StringValue) - if !ok { - return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string") - } - // Look for attribute. - val := "" - k := strings.ToLower(f.Name) - for _, a := range start.Attr { - if fieldName(a.Name.Local) == k { - val = a.Value - break - } - } - strv.Set(val) - - case "comment": - if saveComment == nil { - saveComment = sv.FieldByIndex(f.Index) - } - - case "chardata": - if saveData == nil { - saveData = sv.FieldByIndex(f.Index) - } - - case "innerxml": - if saveXML == nil { - saveXML = sv.FieldByIndex(f.Index) - if p.saved == nil { - saveXMLIndex = 0 - p.saved = new(bytes.Buffer) - } else { - saveXMLIndex = p.savedOffset() - } - } - - default: - if strings.Contains(f.Tag, ">") { - if fieldPaths == nil { - fieldPaths = make(map[string]pathInfo) - } - path := strings.ToLower(f.Tag) - if strings.HasPrefix(f.Tag, ">") { - path = strings.ToLower(f.Name) + path - } - if strings.HasSuffix(f.Tag, ">") { - path = path[:len(path)-1] - } - err := addFieldPath(sv, fieldPaths, path, f.Index) - if err != nil { - return err - } - } - } - } - } - - // Find end element. - // Process sub-elements along the way. -Loop: - for { - var savedOffset int - if saveXML != nil { - savedOffset = p.savedOffset() - } - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - // Sub-element. - // Look up by tag name. - if sv != nil { - k := fieldName(t.Name.Local) - - if fieldPaths != nil { - if _, found := fieldPaths[k]; found { - if err := p.unmarshalPaths(sv, fieldPaths, k, &t); err != nil { - return err - } - continue Loop - } - } - - match := func(s string) bool { - // check if the name matches ignoring case - if strings.ToLower(s) != k { - return false - } - // now check that it's public - c, _ := utf8.DecodeRuneInString(s) - return unicode.IsUpper(c) - } - - f, found := styp.FieldByNameFunc(match) - if !found { // fall back to mop-up field named "Any" - f, found = styp.FieldByName("Any") - } - if found { - if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil { - return err - } - continue Loop - } - } - // Not saving sub-element but still have to skip over it. - if err := p.Skip(); err != nil { - return err - } - - case EndElement: - if saveXML != nil { - saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset] - if saveXMLIndex == 0 { - p.saved = nil - } - } - break Loop - - case CharData: - if saveData != nil { - data = append(data, t...) - } - - case Comment: - if saveComment != nil { - comment = append(comment, t...) - } - } - } - - var err os.Error - // Helper functions for integer and unsigned integer conversions - var itmp int64 - getInt64 := func() bool { - itmp, err = strconv.Atoi64(string(data)) - // TODO: should check sizes - return err == nil - } - var utmp uint64 - getUint64 := func() bool { - utmp, err = strconv.Atoui64(string(data)) - // TODO: check for overflow? - return err == nil - } - var ftmp float64 - getFloat64 := func() bool { - ftmp, err = strconv.Atof64(string(data)) - // TODO: check for overflow? - return err == nil - } - - // Save accumulated data and comments - switch t := saveData.(type) { - case nil: - // Probably a comment, handled below - default: - return os.NewError("cannot happen: unknown type " + t.Type().String()) - case *reflect.IntValue: - if !getInt64() { - return err - } - t.Set(itmp) - case *reflect.UintValue: - if !getUint64() { - return err - } - t.Set(utmp) - case *reflect.FloatValue: - if !getFloat64() { - return err - } - t.Set(ftmp) - case *reflect.BoolValue: - value, err := strconv.Atob(strings.TrimSpace(string(data))) - if err != nil { - return err - } - t.Set(value) - case *reflect.StringValue: - t.Set(string(data)) - case *reflect.SliceValue: - t.Set(reflect.NewValue(data).(*reflect.SliceValue)) - } - - switch t := saveComment.(type) { - case *reflect.StringValue: - t.Set(string(comment)) - case *reflect.SliceValue: - t.Set(reflect.NewValue(comment).(*reflect.SliceValue)) - } - - switch t := saveXML.(type) { - case *reflect.StringValue: - t.Set(string(saveXMLData)) - case *reflect.SliceValue: - t.Set(reflect.NewValue(saveXMLData).(*reflect.SliceValue)) - } - - return nil -} - -type pathInfo struct { - fieldIdx []int - complete bool -} - -// addFieldPath takes an element path such as "a>b>c" and fills the -// paths map with all paths leading to it ("a", "a>b", and "a>b>c"). -// It is okay for paths to share a common, shorter prefix but not ok -// for one path to itself be a prefix of another. -func addFieldPath(sv *reflect.StructValue, paths map[string]pathInfo, path string, fieldIdx []int) os.Error { - if info, found := paths[path]; found { - return tagError(sv, info.fieldIdx, fieldIdx) - } - paths[path] = pathInfo{fieldIdx, true} - for { - i := strings.LastIndex(path, ">") - if i < 0 { - break - } - path = path[:i] - if info, found := paths[path]; found { - if info.complete { - return tagError(sv, info.fieldIdx, fieldIdx) - } - } else { - paths[path] = pathInfo{fieldIdx, false} - } - } - return nil - -} - -func tagError(sv *reflect.StructValue, idx1 []int, idx2 []int) os.Error { - t := sv.Type().(*reflect.StructType) - f1 := t.FieldByIndex(idx1) - f2 := t.FieldByIndex(idx2) - return &TagPathError{t, f1.Name, f1.Tag, f2.Name, f2.Tag} -} - -// unmarshalPaths walks down an XML structure looking for -// wanted paths, and calls unmarshal on them. -func (p *Parser) unmarshalPaths(sv *reflect.StructValue, paths map[string]pathInfo, path string, start *StartElement) os.Error { - if info, _ := paths[path]; info.complete { - return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start) - } - for { - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - k := path + ">" + fieldName(t.Name.Local) - if _, found := paths[k]; found { - if err := p.unmarshalPaths(sv, paths, k, &t); err != nil { - return err - } - continue - } - if err := p.Skip(); err != nil { - return err - } - case EndElement: - return nil - } - } - panic("unreachable") -} - -// Have already read a start element. -// Read tokens until we find the end element. -// Token is taking care of making sure the -// end element matches the start element we saw. -func (p *Parser) Skip() os.Error { - for { - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - if err := p.Skip(); err != nil { - return err - } - case EndElement: - return nil - } - } - panic("unreachable") -} diff --git a/src/cmd/fix/testdata/reflect.read.go.out b/src/cmd/fix/testdata/reflect.read.go.out deleted file mode 100644 index a6b126744c..0000000000 --- a/src/cmd/fix/testdata/reflect.read.go.out +++ /dev/null @@ -1,620 +0,0 @@ -// 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. - -package xml - -import ( - "bytes" - "fmt" - "io" - "os" - "reflect" - "strconv" - "strings" - "unicode" - "utf8" -) - -// BUG(rsc): Mapping between XML elements and data structures is inherently flawed: -// an XML element is an order-dependent collection of anonymous -// values, while a data structure is an order-independent collection -// of named values. -// See package json for a textual representation more suitable -// to data structures. - -// Unmarshal parses an XML element from r and uses the -// reflect library to fill in an arbitrary struct, slice, or string -// pointed at by val. Well-formed data that does not fit -// into val is discarded. -// -// For example, given these definitions: -// -// type Email struct { -// Where string "attr" -// Addr string -// } -// -// type Result struct { -// XMLName xml.Name "result" -// Name string -// Phone string -// Email []Email -// Groups []string "group>value" -// } -// -// result := Result{Name: "name", Phone: "phone", Email: nil} -// -// unmarshalling the XML input -// -// <result> -// <email where="home"> -// <addr>gre@example.com</addr> -// </email> -// <email where='work'> -// <addr>gre@work.com</addr> -// </email> -// <name>Grace R. Emlin</name> -// <group> -// <value>Friends</value> -// <value>Squash</value> -// </group> -// <address>123 Main Street</address> -// </result> -// -// via Unmarshal(r, &result) is equivalent to assigning -// -// r = Result{xml.Name{"", "result"}, -// "Grace R. Emlin", // name -// "phone", // no phone given -// []Email{ -// Email{"home", "gre@example.com"}, -// Email{"work", "gre@work.com"}, -// }, -// []string{"Friends", "Squash"}, -// } -// -// Note that the field r.Phone has not been modified and -// that the XML <address> element was discarded. Also, the field -// Groups was assigned considering the element path provided in the -// field tag. -// -// Because Unmarshal uses the reflect package, it can only -// assign to upper case fields. Unmarshal uses a case-insensitive -// comparison to match XML element names to struct field names. -// -// Unmarshal maps an XML element to a struct using the following rules: -// -// * If the struct has a field of type []byte or string with tag "innerxml", -// Unmarshal accumulates the raw XML nested inside the element -// in that field. The rest of the rules still apply. -// -// * If the struct has a field named XMLName of type xml.Name, -// Unmarshal records the element name in that field. -// -// * If the XMLName field has an associated tag string of the form -// "tag" or "namespace-URL tag", the XML element must have -// the given tag (and, optionally, name space) or else Unmarshal -// returns an error. -// -// * If the XML element has an attribute whose name matches a -// struct field of type string with tag "attr", Unmarshal records -// the attribute value in that field. -// -// * If the XML element contains character data, that data is -// accumulated in the first struct field that has tag "chardata". -// The struct field may have type []byte or string. -// If there is no such field, the character data is discarded. -// -// * If the XML element contains a sub-element whose name matches -// the prefix of a struct field tag formatted as "a>b>c", unmarshal -// will descend into the XML structure looking for elements with the -// given names, and will map the innermost elements to that struct field. -// A struct field tag starting with ">" is equivalent to one starting -// with the field name followed by ">". -// -// * If the XML element contains a sub-element whose name -// matches a struct field whose tag is neither "attr" nor "chardata", -// Unmarshal maps the sub-element to that struct field. -// Otherwise, if the struct has a field named Any, unmarshal -// maps the sub-element to that struct field. -// -// Unmarshal maps an XML element to a string or []byte by saving the -// concatenation of that element's character data in the string or []byte. -// -// Unmarshal maps an XML element to a slice by extending the length -// of the slice and mapping the element to the newly created value. -// -// Unmarshal maps an XML element to a bool by setting it to the boolean -// value represented by the string. -// -// Unmarshal maps an XML element to an integer or floating-point -// field by setting the field to the result of interpreting the string -// value in decimal. There is no check for overflow. -// -// Unmarshal maps an XML element to an xml.Name by recording the -// element name. -// -// Unmarshal maps an XML element to a pointer by setting the pointer -// to a freshly allocated value and then mapping the element to that value. -// -func Unmarshal(r io.Reader, val interface{}) os.Error { - v := reflect.ValueOf(val) - if v.Kind() != reflect.Ptr { - return os.NewError("non-pointer passed to Unmarshal") - } - p := NewParser(r) - elem := v.Elem() - err := p.unmarshal(elem, nil) - if err != nil { - return err - } - return nil -} - -// An UnmarshalError represents an error in the unmarshalling process. -type UnmarshalError string - -func (e UnmarshalError) String() string { return string(e) } - -// A TagPathError represents an error in the unmarshalling process -// caused by the use of field tags with conflicting paths. -type TagPathError struct { - Struct reflect.Type - Field1, Tag1 string - Field2, Tag2 string -} - -func (e *TagPathError) String() string { - return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2) -} - -// The Parser's Unmarshal method is like xml.Unmarshal -// except that it can be passed a pointer to the initial start element, -// useful when a client reads some raw XML tokens itself -// but also defers to Unmarshal for some elements. -// Passing a nil start element indicates that Unmarshal should -// read the token stream to find the start element. -func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error { - v := reflect.ValueOf(val) - if v.Kind() != reflect.Ptr { - return os.NewError("non-pointer passed to Unmarshal") - } - return p.unmarshal(v.Elem(), start) -} - -// fieldName strips invalid characters from an XML name -// to create a valid Go struct name. It also converts the -// name to lower case letters. -func fieldName(original string) string { - - var i int - //remove leading underscores - for i = 0; i < len(original) && original[i] == '_'; i++ { - } - - return strings.Map( - func(x int) int { - if x == '_' || unicode.IsDigit(x) || unicode.IsLetter(x) { - return unicode.ToLower(x) - } - return -1 - }, - original[i:]) -} - -// Unmarshal a single XML element into val. -func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error { - // Find start element if we need it. - if start == nil { - for { - tok, err := p.Token() - if err != nil { - return err - } - if t, ok := tok.(StartElement); ok { - start = &t - break - } - } - } - - if pv := val; pv.Kind() == reflect.Ptr { - if pv.Pointer() == 0 { - zv := reflect.Zero(pv.Type().Elem()) - pv.Set(zv.Addr()) - val = zv - } else { - val = pv.Elem() - } - } - - var ( - data []byte - saveData reflect.Value - comment []byte - saveComment reflect.Value - saveXML reflect.Value - saveXMLIndex int - saveXMLData []byte - sv reflect.Value - styp reflect.Type - fieldPaths map[string]pathInfo - ) - - switch v := val; v.Kind() { - default: - return os.NewError("unknown type " + v.Type().String()) - - case reflect.Slice: - typ := v.Type() - if typ.Elem().Kind() == reflect.Uint8 { - // []byte - saveData = v - break - } - - // Slice of element values. - // Grow slice. - n := v.Len() - if n >= v.Cap() { - ncap := 2 * n - if ncap < 4 { - ncap = 4 - } - new := reflect.MakeSlice(typ, n, ncap) - reflect.Copy(new, v) - v.Set(new) - } - v.SetLen(n + 1) - - // Recur to read element into slice. - if err := p.unmarshal(v.Index(n), start); err != nil { - v.SetLen(n) - return err - } - return nil - - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String: - saveData = v - - case reflect.Struct: - if _, ok := v.Interface().(Name); ok { - v.Set(reflect.ValueOf(start.Name)) - break - } - - sv = v - typ := sv.Type() - styp = typ - // Assign name. - if f, ok := typ.FieldByName("XMLName"); ok { - // Validate element name. - if f.Tag != "" { - tag := f.Tag - ns := "" - i := strings.LastIndex(tag, " ") - if i >= 0 { - ns, tag = tag[0:i], tag[i+1:] - } - if tag != start.Name.Local { - return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">") - } - if ns != "" && ns != start.Name.Space { - e := "expected element <" + tag + "> in name space " + ns + " but have " - if start.Name.Space == "" { - e += "no name space" - } else { - e += start.Name.Space - } - return UnmarshalError(e) - } - } - - // Save - v := sv.FieldByIndex(f.Index) - if _, ok := v.Interface().(Name); !ok { - return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name") - } - v.Set(reflect.ValueOf(start.Name)) - } - - // Assign attributes. - // Also, determine whether we need to save character data or comments. - for i, n := 0, typ.NumField(); i < n; i++ { - f := typ.Field(i) - switch f.Tag { - case "attr": - strv := sv.FieldByIndex(f.Index) - if strv.Kind() != reflect.String { - return UnmarshalError(sv.Type().String() + " field " + f.Name + " has attr tag but is not type string") - } - // Look for attribute. - val := "" - k := strings.ToLower(f.Name) - for _, a := range start.Attr { - if fieldName(a.Name.Local) == k { - val = a.Value - break - } - } - strv.SetString(val) - - case "comment": - if !saveComment.IsValid() { - saveComment = sv.FieldByIndex(f.Index) - } - - case "chardata": - if !saveData.IsValid() { - saveData = sv.FieldByIndex(f.Index) - } - - case "innerxml": - if !saveXML.IsValid() { - saveXML = sv.FieldByIndex(f.Index) - if p.saved == nil { - saveXMLIndex = 0 - p.saved = new(bytes.Buffer) - } else { - saveXMLIndex = p.savedOffset() - } - } - - default: - if strings.Contains(f.Tag, ">") { - if fieldPaths == nil { - fieldPaths = make(map[string]pathInfo) - } - path := strings.ToLower(f.Tag) - if strings.HasPrefix(f.Tag, ">") { - path = strings.ToLower(f.Name) + path - } - if strings.HasSuffix(f.Tag, ">") { - path = path[:len(path)-1] - } - err := addFieldPath(sv, fieldPaths, path, f.Index) - if err != nil { - return err - } - } - } - } - } - - // Find end element. - // Process sub-elements along the way. -Loop: - for { - var savedOffset int - if saveXML.IsValid() { - savedOffset = p.savedOffset() - } - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - // Sub-element. - // Look up by tag name. - if sv.IsValid() { - k := fieldName(t.Name.Local) - - if fieldPaths != nil { - if _, found := fieldPaths[k]; found { - if err := p.unmarshalPaths(sv, fieldPaths, k, &t); err != nil { - return err - } - continue Loop - } - } - - match := func(s string) bool { - // check if the name matches ignoring case - if strings.ToLower(s) != k { - return false - } - // now check that it's public - c, _ := utf8.DecodeRuneInString(s) - return unicode.IsUpper(c) - } - - f, found := styp.FieldByNameFunc(match) - if !found { // fall back to mop-up field named "Any" - f, found = styp.FieldByName("Any") - } - if found { - if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil { - return err - } - continue Loop - } - } - // Not saving sub-element but still have to skip over it. - if err := p.Skip(); err != nil { - return err - } - - case EndElement: - if saveXML.IsValid() { - saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset] - if saveXMLIndex == 0 { - p.saved = nil - } - } - break Loop - - case CharData: - if saveData.IsValid() { - data = append(data, t...) - } - - case Comment: - if saveComment.IsValid() { - comment = append(comment, t...) - } - } - } - - var err os.Error - // Helper functions for integer and unsigned integer conversions - var itmp int64 - getInt64 := func() bool { - itmp, err = strconv.Atoi64(string(data)) - // TODO: should check sizes - return err == nil - } - var utmp uint64 - getUint64 := func() bool { - utmp, err = strconv.Atoui64(string(data)) - // TODO: check for overflow? - return err == nil - } - var ftmp float64 - getFloat64 := func() bool { - ftmp, err = strconv.Atof64(string(data)) - // TODO: check for overflow? - return err == nil - } - - // Save accumulated data and comments - switch t := saveData; t.Kind() { - case reflect.Invalid: - // Probably a comment, handled below - default: - return os.NewError("cannot happen: unknown type " + t.Type().String()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if !getInt64() { - return err - } - t.SetInt(itmp) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - if !getUint64() { - return err - } - t.SetUint(utmp) - case reflect.Float32, reflect.Float64: - if !getFloat64() { - return err - } - t.SetFloat(ftmp) - case reflect.Bool: - value, err := strconv.Atob(strings.TrimSpace(string(data))) - if err != nil { - return err - } - t.SetBool(value) - case reflect.String: - t.SetString(string(data)) - case reflect.Slice: - t.Set(reflect.ValueOf(data)) - } - - switch t := saveComment; t.Kind() { - case reflect.String: - t.SetString(string(comment)) - case reflect.Slice: - t.Set(reflect.ValueOf(comment)) - } - - switch t := saveXML; t.Kind() { - case reflect.String: - t.SetString(string(saveXMLData)) - case reflect.Slice: - t.Set(reflect.ValueOf(saveXMLData)) - } - - return nil -} - -type pathInfo struct { - fieldIdx []int - complete bool -} - -// addFieldPath takes an element path such as "a>b>c" and fills the -// paths map with all paths leading to it ("a", "a>b", and "a>b>c"). -// It is okay for paths to share a common, shorter prefix but not ok -// for one path to itself be a prefix of another. -func addFieldPath(sv reflect.Value, paths map[string]pathInfo, path string, fieldIdx []int) os.Error { - if info, found := paths[path]; found { - return tagError(sv, info.fieldIdx, fieldIdx) - } - paths[path] = pathInfo{fieldIdx, true} - for { - i := strings.LastIndex(path, ">") - if i < 0 { - break - } - path = path[:i] - if info, found := paths[path]; found { - if info.complete { - return tagError(sv, info.fieldIdx, fieldIdx) - } - } else { - paths[path] = pathInfo{fieldIdx, false} - } - } - return nil - -} - -func tagError(sv reflect.Value, idx1 []int, idx2 []int) os.Error { - t := sv.Type() - f1 := t.FieldByIndex(idx1) - f2 := t.FieldByIndex(idx2) - return &TagPathError{t, f1.Name, f1.Tag, f2.Name, f2.Tag} -} - -// unmarshalPaths walks down an XML structure looking for -// wanted paths, and calls unmarshal on them. -func (p *Parser) unmarshalPaths(sv reflect.Value, paths map[string]pathInfo, path string, start *StartElement) os.Error { - if info, _ := paths[path]; info.complete { - return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start) - } - for { - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - k := path + ">" + fieldName(t.Name.Local) - if _, found := paths[k]; found { - if err := p.unmarshalPaths(sv, paths, k, &t); err != nil { - return err - } - continue - } - if err := p.Skip(); err != nil { - return err - } - case EndElement: - return nil - } - } - panic("unreachable") -} - -// Have already read a start element. -// Read tokens until we find the end element. -// Token is taking care of making sure the -// end element matches the start element we saw. -func (p *Parser) Skip() os.Error { - for { - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - if err := p.Skip(); err != nil { - return err - } - case EndElement: - return nil - } - } - panic("unreachable") -} diff --git a/src/cmd/fix/testdata/reflect.scan.go.in b/src/cmd/fix/testdata/reflect.scan.go.in deleted file mode 100644 index 51898181f9..0000000000 --- a/src/cmd/fix/testdata/reflect.scan.go.in +++ /dev/null @@ -1,1082 +0,0 @@ -// Copyright 2010 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. - -package fmt - -import ( - "bytes" - "io" - "math" - "os" - "reflect" - "strconv" - "strings" - "unicode" - "utf8" -) - -// runeUnreader is the interface to something that can unread runes. -// If the object provided to Scan does not satisfy this interface, -// a local buffer will be used to back up the input, but its contents -// will be lost when Scan returns. -type runeUnreader interface { - UnreadRune() os.Error -} - -// ScanState represents the scanner state passed to custom scanners. -// Scanners may do rune-at-a-time scanning or ask the ScanState -// to discover the next space-delimited token. -type ScanState interface { - // ReadRune reads the next rune (Unicode code point) from the input. - // If invoked during Scanln, Fscanln, or Sscanln, ReadRune() will - // return EOF after returning the first '\n' or when reading beyond - // the specified width. - ReadRune() (rune int, size int, err os.Error) - // UnreadRune causes the next call to ReadRune to return the same rune. - UnreadRune() os.Error - // Token skips space in the input if skipSpace is true, then returns the - // run of Unicode code points c satisfying f(c). If f is nil, - // !unicode.IsSpace(c) is used; that is, the token will hold non-space - // characters. Newlines are treated as space unless the scan operation - // is Scanln, Fscanln or Sscanln, in which case a newline is treated as - // EOF. The returned slice points to shared data that may be overwritten - // by the next call to Token, a call to a Scan function using the ScanState - // as input, or when the calling Scan method returns. - Token(skipSpace bool, f func(int) bool) (token []byte, err os.Error) - // Width returns the value of the width option and whether it has been set. - // The unit is Unicode code points. - Width() (wid int, ok bool) - // Because ReadRune is implemented by the interface, Read should never be - // called by the scanning routines and a valid implementation of - // ScanState may choose always to return an error from Read. - Read(buf []byte) (n int, err os.Error) -} - -// Scanner is implemented by any value that has a Scan method, which scans -// the input for the representation of a value and stores the result in the -// receiver, which must be a pointer to be useful. The Scan method is called -// for any argument to Scan, Scanf, or Scanln that implements it. -type Scanner interface { - Scan(state ScanState, verb int) os.Error -} - -// Scan scans text read from standard input, storing successive -// space-separated values into successive arguments. Newlines count -// as space. It returns the number of items successfully scanned. -// If that is less than the number of arguments, err will report why. -func Scan(a ...interface{}) (n int, err os.Error) { - return Fscan(os.Stdin, a...) -} - -// Scanln is similar to Scan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Scanln(a ...interface{}) (n int, err os.Error) { - return Fscanln(os.Stdin, a...) -} - -// Scanf scans text read from standard input, storing successive -// space-separated values into successive arguments as determined by -// the format. It returns the number of items successfully scanned. -func Scanf(format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(os.Stdin, format, a...) -} - -// Sscan scans the argument string, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less -// than the number of arguments, err will report why. -func Sscan(str string, a ...interface{}) (n int, err os.Error) { - return Fscan(strings.NewReader(str), a...) -} - -// Sscanln is similar to Sscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Sscanln(str string, a ...interface{}) (n int, err os.Error) { - return Fscanln(strings.NewReader(str), a...) -} - -// Sscanf scans the argument string, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Sscanf(str string, format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(strings.NewReader(str), format, a...) -} - -// Fscan scans text read from r, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less -// than the number of arguments, err will report why. -func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, true, false) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanln is similar to Fscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, true) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanf scans text read from r, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, false) - n, err = s.doScanf(format, a) - s.free(old) - return -} - -// scanError represents an error generated by the scanning software. -// It's used as a unique signature to identify such errors when recovering. -type scanError struct { - err os.Error -} - -const eof = -1 - -// ss is the internal implementation of ScanState. -type ss struct { - rr io.RuneReader // where to read input - buf bytes.Buffer // token accumulator - peekRune int // one-rune lookahead - prevRune int // last rune returned by ReadRune - count int // runes consumed so far. - atEOF bool // already read EOF - ssave -} - -// ssave holds the parts of ss that need to be -// saved and restored on recursive scans. -type ssave struct { - validSave bool // is or was a part of an actual ss. - nlIsEnd bool // whether newline terminates scan - nlIsSpace bool // whether newline counts as white space - fieldLimit int // max value of ss.count for this field; fieldLimit <= limit - limit int // max value of ss.count. - maxWid int // width of this field. -} - -// The Read method is only in ScanState so that ScanState -// satisfies io.Reader. It will never be called when used as -// intended, so there is no need to make it actually work. -func (s *ss) Read(buf []byte) (n int, err os.Error) { - return 0, os.NewError("ScanState's Read should not be called. Use ReadRune") -} - -func (s *ss) ReadRune() (rune int, size int, err os.Error) { - if s.peekRune >= 0 { - s.count++ - rune = s.peekRune - size = utf8.RuneLen(rune) - s.prevRune = rune - s.peekRune = -1 - return - } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit { - err = os.EOF - return - } - - rune, size, err = s.rr.ReadRune() - if err == nil { - s.count++ - s.prevRune = rune - } else if err == os.EOF { - s.atEOF = true - } - return -} - -func (s *ss) Width() (wid int, ok bool) { - if s.maxWid == hugeWid { - return 0, false - } - return s.maxWid, true -} - -// The public method returns an error; this private one panics. -// If getRune reaches EOF, the return value is EOF (-1). -func (s *ss) getRune() (rune int) { - rune, _, err := s.ReadRune() - if err != nil { - if err == os.EOF { - return eof - } - s.error(err) - } - return -} - -// mustReadRune turns os.EOF into a panic(io.ErrUnexpectedEOF). -// It is called in cases such as string scanning where an EOF is a -// syntax error. -func (s *ss) mustReadRune() (rune int) { - rune = s.getRune() - if rune == eof { - s.error(io.ErrUnexpectedEOF) - } - return -} - -func (s *ss) UnreadRune() os.Error { - if u, ok := s.rr.(runeUnreader); ok { - u.UnreadRune() - } else { - s.peekRune = s.prevRune - } - s.count-- - return nil -} - -func (s *ss) error(err os.Error) { - panic(scanError{err}) -} - -func (s *ss) errorString(err string) { - panic(scanError{os.NewError(err)}) -} - -func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) { - defer func() { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { - err = se.err - } else { - panic(e) - } - } - }() - if f == nil { - f = notSpace - } - s.buf.Reset() - tok = s.token(skipSpace, f) - return -} - -// notSpace is the default scanning function used in Token. -func notSpace(r int) bool { - return !unicode.IsSpace(r) -} - -// readRune is a structure to enable reading UTF-8 encoded code points -// from an io.Reader. It is used if the Reader given to the scanner does -// not already implement io.RuneReader. -type readRune struct { - reader io.Reader - buf [utf8.UTFMax]byte // used only inside ReadRune - pending int // number of bytes in pendBuf; only >0 for bad UTF-8 - pendBuf [utf8.UTFMax]byte // bytes left over -} - -// readByte returns the next byte from the input, which may be -// left over from a previous read if the UTF-8 was ill-formed. -func (r *readRune) readByte() (b byte, err os.Error) { - if r.pending > 0 { - b = r.pendBuf[0] - copy(r.pendBuf[0:], r.pendBuf[1:]) - r.pending-- - return - } - _, err = r.reader.Read(r.pendBuf[0:1]) - return r.pendBuf[0], err -} - -// unread saves the bytes for the next read. -func (r *readRune) unread(buf []byte) { - copy(r.pendBuf[r.pending:], buf) - r.pending += len(buf) -} - -// ReadRune returns the next UTF-8 encoded code point from the -// io.Reader inside r. -func (r *readRune) ReadRune() (rune int, size int, err os.Error) { - r.buf[0], err = r.readByte() - if err != nil { - return 0, 0, err - } - if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case - rune = int(r.buf[0]) - return - } - var n int - for n = 1; !utf8.FullRune(r.buf[0:n]); n++ { - r.buf[n], err = r.readByte() - if err != nil { - if err == os.EOF { - err = nil - break - } - return - } - } - rune, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) - } - return -} - -var ssFree = newCache(func() interface{} { return new(ss) }) - -// Allocate a new ss struct or grab a cached one. -func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { - // If the reader is a *ss, then we've got a recursive - // call to Scan, so re-use the scan state. - s, ok := r.(*ss) - if ok { - old = s.ssave - s.limit = s.fieldLimit - s.nlIsEnd = nlIsEnd || s.nlIsEnd - s.nlIsSpace = nlIsSpace - return - } - - s = ssFree.get().(*ss) - if rr, ok := r.(io.RuneReader); ok { - s.rr = rr - } else { - s.rr = &readRune{reader: r} - } - s.nlIsSpace = nlIsSpace - s.nlIsEnd = nlIsEnd - s.prevRune = -1 - s.peekRune = -1 - s.atEOF = false - s.limit = hugeWid - s.fieldLimit = hugeWid - s.maxWid = hugeWid - s.validSave = true - return -} - -// Save used ss structs in ssFree; avoid an allocation per invocation. -func (s *ss) free(old ssave) { - // If it was used recursively, just restore the old state. - if old.validSave { - s.ssave = old - return - } - // Don't hold on to ss structs with large buffers. - if cap(s.buf.Bytes()) > 1024 { - return - } - s.buf.Reset() - s.rr = nil - ssFree.put(s) -} - -// skipSpace skips spaces and maybe newlines. -func (s *ss) skipSpace(stopAtNewline bool) { - for { - rune := s.getRune() - if rune == eof { - return - } - if rune == '\n' { - if stopAtNewline { - break - } - if s.nlIsSpace { - continue - } - s.errorString("unexpected newline") - return - } - if !unicode.IsSpace(rune) { - s.UnreadRune() - break - } - } -} - -// token returns the next space-delimited string from the input. It -// skips white space. For Scanln, it stops at newlines. For Scan, -// newlines are treated as spaces. -func (s *ss) token(skipSpace bool, f func(int) bool) []byte { - if skipSpace { - s.skipSpace(false) - } - // read until white space or newline - for { - rune := s.getRune() - if rune == eof { - break - } - if !f(rune) { - s.UnreadRune() - break - } - s.buf.WriteRune(rune) - } - return s.buf.Bytes() -} - -// typeError indicates that the type of the operand did not match the format -func (s *ss) typeError(field interface{}, expected string) { - s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String()) -} - -var complexError = os.NewError("syntax error scanning complex number") -var boolError = os.NewError("syntax error scanning boolean") - -// consume reads the next rune in the input and reports whether it is in the ok string. -// If accept is true, it puts the character into the input token. -func (s *ss) consume(ok string, accept bool) bool { - rune := s.getRune() - if rune == eof { - return false - } - if strings.IndexRune(ok, rune) >= 0 { - if accept { - s.buf.WriteRune(rune) - } - return true - } - if rune != eof && accept { - s.UnreadRune() - } - return false -} - -// peek reports whether the next character is in the ok string, without consuming it. -func (s *ss) peek(ok string) bool { - rune := s.getRune() - if rune != eof { - s.UnreadRune() - } - return strings.IndexRune(ok, rune) >= 0 -} - -// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the -// buffer and returns true. Otherwise it return false. -func (s *ss) accept(ok string) bool { - return s.consume(ok, true) -} - -// okVerb verifies that the verb is present in the list, setting s.err appropriately if not. -func (s *ss) okVerb(verb int, okVerbs, typ string) bool { - for _, v := range okVerbs { - if v == verb { - return true - } - } - s.errorString("bad verb %" + string(verb) + " for " + typ) - return false -} - -// scanBool returns the value of the boolean represented by the next token. -func (s *ss) scanBool(verb int) bool { - if !s.okVerb(verb, "tv", "boolean") { - return false - } - // Syntax-checking a boolean is annoying. We're not fastidious about case. - switch s.mustReadRune() { - case '0': - return false - case '1': - return true - case 't', 'T': - if s.accept("rR") && (!s.accept("uU") || !s.accept("eE")) { - s.error(boolError) - } - return true - case 'f', 'F': - if s.accept("aL") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) { - s.error(boolError) - } - return false - } - return false -} - -// Numerical elements -const ( - binaryDigits = "01" - octalDigits = "01234567" - decimalDigits = "0123456789" - hexadecimalDigits = "0123456789aAbBcCdDeEfF" - sign = "+-" - period = "." - exponent = "eEp" -) - -// getBase returns the numeric base represented by the verb and its digit string. -func (s *ss) getBase(verb int) (base int, digits string) { - s.okVerb(verb, "bdoUxXv", "integer") // sets s.err - base = 10 - digits = decimalDigits - switch verb { - case 'b': - base = 2 - digits = binaryDigits - case 'o': - base = 8 - digits = octalDigits - case 'x', 'X', 'U': - base = 16 - digits = hexadecimalDigits - } - return -} - -// scanNumber returns the numerical string with specified digits starting here. -func (s *ss) scanNumber(digits string, haveDigits bool) string { - if !haveDigits && !s.accept(digits) { - s.errorString("expected integer") - } - for s.accept(digits) { - } - return s.buf.String() -} - -// scanRune returns the next rune value in the input. -func (s *ss) scanRune(bitSize int) int64 { - rune := int64(s.mustReadRune()) - n := uint(bitSize) - x := (rune << (64 - n)) >> (64 - n) - if x != rune { - s.errorString("overflow on character value " + string(rune)) - } - return rune -} - -// scanBasePrefix reports whether the integer begins with a 0 or 0x, -// and returns the base, digit string, and whether a zero was found. -// It is called only if the verb is %v. -func (s *ss) scanBasePrefix() (base int, digits string, found bool) { - if !s.peek("0") { - return 10, decimalDigits, false - } - s.accept("0") - found = true // We've put a digit into the token buffer. - // Special cases for '0' && '0x' - base, digits = 8, octalDigits - if s.peek("xX") { - s.consume("xX", false) - base, digits = 16, hexadecimalDigits - } - return -} - -// scanInt returns the value of the integer represented by the next -// token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanInt(verb int, bitSize int) int64 { - if verb == 'c' { - return s.scanRune(bitSize) - } - s.skipSpace(false) - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else { - s.accept(sign) // If there's a sign, it will be left in the token buffer. - if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoi64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("integer overflow on token " + tok) - } - return i -} - -// scanUint returns the value of the unsigned integer represented -// by the next token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanUint(verb int, bitSize int) uint64 { - if verb == 'c' { - return uint64(s.scanRune(bitSize)) - } - s.skipSpace(false) - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoui64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("unsigned integer overflow on token " + tok) - } - return i -} - -// floatToken returns the floating-point number starting here, no longer than swid -// if the width is specified. It's not rigorous about syntax because it doesn't check that -// we have at least some digits, but Atof will do that. -func (s *ss) floatToken() string { - s.buf.Reset() - // NaN? - if s.accept("nN") && s.accept("aA") && s.accept("nN") { - return s.buf.String() - } - // leading sign? - s.accept(sign) - // Inf? - if s.accept("iI") && s.accept("nN") && s.accept("fF") { - return s.buf.String() - } - // digits? - for s.accept(decimalDigits) { - } - // decimal point? - if s.accept(period) { - // fraction? - for s.accept(decimalDigits) { - } - } - // exponent? - if s.accept(exponent) { - // leading sign? - s.accept(sign) - // digits? - for s.accept(decimalDigits) { - } - } - return s.buf.String() -} - -// complexTokens returns the real and imaginary parts of the complex number starting here. -// The number might be parenthesized and has the format (N+Ni) where N is a floating-point -// number and there are no spaces within. -func (s *ss) complexTokens() (real, imag string) { - // TODO: accept N and Ni independently? - parens := s.accept("(") - real = s.floatToken() - s.buf.Reset() - // Must now have a sign. - if !s.accept("+-") { - s.error(complexError) - } - // Sign is now in buffer - imagSign := s.buf.String() - imag = s.floatToken() - if !s.accept("i") { - s.error(complexError) - } - if parens && !s.accept(")") { - s.error(complexError) - } - return real, imagSign + imag -} - -// convertFloat converts the string to a float64value. -func (s *ss) convertFloat(str string, n int) float64 { - if p := strings.Index(str, "p"); p >= 0 { - // Atof doesn't handle power-of-2 exponents, - // but they're easy to evaluate. - f, err := strconv.AtofN(str[:p], n) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - n, err := strconv.Atoi(str[p+1:]) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - return math.Ldexp(f, n) - } - f, err := strconv.AtofN(str, n) - if err != nil { - s.error(err) - } - return f -} - -// convertComplex converts the next token to a complex128 value. -// The atof argument is a type-specific reader for the underlying type. -// If we're reading complex64, atof will parse float32s and convert them -// to float64's to avoid reproducing this code for each complex type. -func (s *ss) scanComplex(verb int, n int) complex128 { - if !s.okVerb(verb, floatVerbs, "complex") { - return 0 - } - s.skipSpace(false) - sreal, simag := s.complexTokens() - real := s.convertFloat(sreal, n/2) - imag := s.convertFloat(simag, n/2) - return complex(real, imag) -} - -// convertString returns the string represented by the next input characters. -// The format of the input is determined by the verb. -func (s *ss) convertString(verb int) (str string) { - if !s.okVerb(verb, "svqx", "string") { - return "" - } - s.skipSpace(false) - switch verb { - case 'q': - str = s.quotedString() - case 'x': - str = s.hexString() - default: - str = string(s.token(true, notSpace)) // %s and %v just return the next word - } - // Empty strings other than with %q are not OK. - if len(str) == 0 && verb != 'q' && s.maxWid > 0 { - s.errorString("Scan: no data for string") - } - return -} - -// quotedString returns the double- or back-quoted string represented by the next input characters. -func (s *ss) quotedString() string { - quote := s.mustReadRune() - switch quote { - case '`': - // Back-quoted: Anything goes until EOF or back quote. - for { - rune := s.mustReadRune() - if rune == quote { - break - } - s.buf.WriteRune(rune) - } - return s.buf.String() - case '"': - // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) - for { - rune := s.mustReadRune() - s.buf.WriteRune(rune) - if rune == '\\' { - // In a legal backslash escape, no matter how long, only the character - // immediately after the escape can itself be a backslash or quote. - // Thus we only need to protect the first character after the backslash. - rune := s.mustReadRune() - s.buf.WriteRune(rune) - } else if rune == '"' { - break - } - } - result, err := strconv.Unquote(s.buf.String()) - if err != nil { - s.error(err) - } - return result - default: - s.errorString("expected quoted string") - } - return "" -} - -// hexDigit returns the value of the hexadecimal digit -func (s *ss) hexDigit(digit int) int { - switch digit { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return digit - '0' - case 'a', 'b', 'c', 'd', 'e', 'f': - return 10 + digit - 'a' - case 'A', 'B', 'C', 'D', 'E', 'F': - return 10 + digit - 'A' - } - s.errorString("Scan: illegal hex digit") - return 0 -} - -// hexByte returns the next hex-encoded (two-character) byte from the input. -// There must be either two hexadecimal digits or a space character in the input. -func (s *ss) hexByte() (b byte, ok bool) { - rune1 := s.getRune() - if rune1 == eof { - return - } - if unicode.IsSpace(rune1) { - s.UnreadRune() - return - } - rune2 := s.mustReadRune() - return byte(s.hexDigit(rune1)<<4 | s.hexDigit(rune2)), true -} - -// hexString returns the space-delimited hexpair-encoded string. -func (s *ss) hexString() string { - for { - b, ok := s.hexByte() - if !ok { - break - } - s.buf.WriteByte(b) - } - if s.buf.Len() == 0 { - s.errorString("Scan: no hex data for %x string") - return "" - } - return s.buf.String() -} - -const floatVerbs = "beEfFgGv" - -const hugeWid = 1 << 30 - -// scanOne scans a single value, deriving the scanner from the type of the argument. -func (s *ss) scanOne(verb int, field interface{}) { - s.buf.Reset() - var err os.Error - // If the parameter has its own Scan method, use that. - if v, ok := field.(Scanner); ok { - err = v.Scan(s, verb) - if err != nil { - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - s.error(err) - } - return - } - switch v := field.(type) { - case *bool: - *v = s.scanBool(verb) - case *complex64: - *v = complex64(s.scanComplex(verb, 64)) - case *complex128: - *v = s.scanComplex(verb, 128) - case *int: - *v = int(s.scanInt(verb, intBits)) - case *int8: - *v = int8(s.scanInt(verb, 8)) - case *int16: - *v = int16(s.scanInt(verb, 16)) - case *int32: - *v = int32(s.scanInt(verb, 32)) - case *int64: - *v = s.scanInt(verb, 64) - case *uint: - *v = uint(s.scanUint(verb, intBits)) - case *uint8: - *v = uint8(s.scanUint(verb, 8)) - case *uint16: - *v = uint16(s.scanUint(verb, 16)) - case *uint32: - *v = uint32(s.scanUint(verb, 32)) - case *uint64: - *v = s.scanUint(verb, 64) - case *uintptr: - *v = uintptr(s.scanUint(verb, uintptrBits)) - // Floats are tricky because you want to scan in the precision of the result, not - // scan in high precision and convert, in order to preserve the correct error condition. - case *float32: - if s.okVerb(verb, floatVerbs, "float32") { - s.skipSpace(false) - *v = float32(s.convertFloat(s.floatToken(), 32)) - } - case *float64: - if s.okVerb(verb, floatVerbs, "float64") { - s.skipSpace(false) - *v = s.convertFloat(s.floatToken(), 64) - } - case *string: - *v = s.convertString(verb) - case *[]byte: - // We scan to string and convert so we get a copy of the data. - // If we scanned to bytes, the slice would point at the buffer. - *v = []byte(s.convertString(verb)) - default: - val := reflect.NewValue(v) - ptr, ok := val.(*reflect.PtrValue) - if !ok { - s.errorString("Scan: type not a pointer: " + val.Type().String()) - return - } - switch v := ptr.Elem().(type) { - case *reflect.BoolValue: - v.Set(s.scanBool(verb)) - case *reflect.IntValue: - v.Set(s.scanInt(verb, v.Type().Bits())) - case *reflect.UintValue: - v.Set(s.scanUint(verb, v.Type().Bits())) - case *reflect.StringValue: - v.Set(s.convertString(verb)) - case *reflect.SliceValue: - // For now, can only handle (renamed) []byte. - typ := v.Type().(*reflect.SliceType) - if typ.Elem().Kind() != reflect.Uint8 { - goto CantHandle - } - str := s.convertString(verb) - v.Set(reflect.MakeSlice(typ, len(str), len(str))) - for i := 0; i < len(str); i++ { - v.Elem(i).(*reflect.UintValue).Set(uint64(str[i])) - } - case *reflect.FloatValue: - s.skipSpace(false) - v.Set(s.convertFloat(s.floatToken(), v.Type().Bits())) - case *reflect.ComplexValue: - v.Set(s.scanComplex(verb, v.Type().Bits())) - default: - CantHandle: - s.errorString("Scan: can't handle type: " + val.Type().String()) - } - } -} - -// errorHandler turns local panics into error returns. EOFs are benign. -func errorHandler(errp *os.Error) { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { // catch local error - if se.err != os.EOF { - *errp = se.err - } - } else { - panic(e) - } - } -} - -// doScan does the real work for scanning without a format string. -func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - for _, field := range a { - s.scanOne('v', field) - numProcessed++ - } - // Check for newline if required. - if !s.nlIsSpace { - for { - rune := s.getRune() - if rune == '\n' || rune == eof { - break - } - if !unicode.IsSpace(rune) { - s.errorString("Scan: expected newline") - break - } - } - } - return -} - -// advance determines whether the next characters in the input match -// those of the format. It returns the number of bytes (sic) consumed -// in the format. Newlines included, all runs of space characters in -// either input or format behave as a single space. This routine also -// handles the %% case. If the return value is zero, either format -// starts with a % (with no following %) or the input is empty. -// If it is negative, the input did not match the string. -func (s *ss) advance(format string) (i int) { - for i < len(format) { - fmtc, w := utf8.DecodeRuneInString(format[i:]) - if fmtc == '%' { - // %% acts like a real percent - nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty - if nextc != '%' { - return - } - i += w // skip the first % - } - sawSpace := false - for unicode.IsSpace(fmtc) && i < len(format) { - sawSpace = true - i += w - fmtc, w = utf8.DecodeRuneInString(format[i:]) - } - if sawSpace { - // There was space in the format, so there should be space (EOF) - // in the input. - inputc := s.getRune() - if inputc == eof { - return - } - if !unicode.IsSpace(inputc) { - // Space in format but not in input: error - s.errorString("expected space in input to match format") - } - s.skipSpace(true) - continue - } - inputc := s.mustReadRune() - if fmtc != inputc { - s.UnreadRune() - return -1 - } - i += w - } - return -} - -// doScanf does the real work when scanning with a format string. -// At the moment, it handles only pointers to basic types. -func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - end := len(format) - 1 - // We process one item per non-trivial format - for i := 0; i <= end; { - w := s.advance(format[i:]) - if w > 0 { - i += w - continue - } - // Either we failed to advance, we have a percent character, or we ran out of input. - if format[i] != '%' { - // Can't advance format. Why not? - if w < 0 { - s.errorString("input does not match format") - } - // Otherwise at EOF; "too many operands" error handled below - break - } - i++ // % is one byte - - // do we have 20 (width)? - var widPresent bool - s.maxWid, widPresent, i = parsenum(format, i, end) - if !widPresent { - s.maxWid = hugeWid - } - s.fieldLimit = s.limit - if f := s.count + s.maxWid; f < s.fieldLimit { - s.fieldLimit = f - } - - c, w := utf8.DecodeRuneInString(format[i:]) - i += w - - if numProcessed >= len(a) { // out of operands - s.errorString("too few operands for format %" + format[i-w:]) - break - } - field := a[numProcessed] - - s.scanOne(c, field) - numProcessed++ - s.fieldLimit = s.limit - } - if numProcessed < len(a) { - s.errorString("too many operands") - } - return -} diff --git a/src/cmd/fix/testdata/reflect.scan.go.out b/src/cmd/fix/testdata/reflect.scan.go.out deleted file mode 100644 index 956c13bde8..0000000000 --- a/src/cmd/fix/testdata/reflect.scan.go.out +++ /dev/null @@ -1,1082 +0,0 @@ -// Copyright 2010 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. - -package fmt - -import ( - "bytes" - "io" - "math" - "os" - "reflect" - "strconv" - "strings" - "unicode" - "utf8" -) - -// runeUnreader is the interface to something that can unread runes. -// If the object provided to Scan does not satisfy this interface, -// a local buffer will be used to back up the input, but its contents -// will be lost when Scan returns. -type runeUnreader interface { - UnreadRune() os.Error -} - -// ScanState represents the scanner state passed to custom scanners. -// Scanners may do rune-at-a-time scanning or ask the ScanState -// to discover the next space-delimited token. -type ScanState interface { - // ReadRune reads the next rune (Unicode code point) from the input. - // If invoked during Scanln, Fscanln, or Sscanln, ReadRune() will - // return EOF after returning the first '\n' or when reading beyond - // the specified width. - ReadRune() (rune int, size int, err os.Error) - // UnreadRune causes the next call to ReadRune to return the same rune. - UnreadRune() os.Error - // Token skips space in the input if skipSpace is true, then returns the - // run of Unicode code points c satisfying f(c). If f is nil, - // !unicode.IsSpace(c) is used; that is, the token will hold non-space - // characters. Newlines are treated as space unless the scan operation - // is Scanln, Fscanln or Sscanln, in which case a newline is treated as - // EOF. The returned slice points to shared data that may be overwritten - // by the next call to Token, a call to a Scan function using the ScanState - // as input, or when the calling Scan method returns. - Token(skipSpace bool, f func(int) bool) (token []byte, err os.Error) - // Width returns the value of the width option and whether it has been set. - // The unit is Unicode code points. - Width() (wid int, ok bool) - // Because ReadRune is implemented by the interface, Read should never be - // called by the scanning routines and a valid implementation of - // ScanState may choose always to return an error from Read. - Read(buf []byte) (n int, err os.Error) -} - -// Scanner is implemented by any value that has a Scan method, which scans -// the input for the representation of a value and stores the result in the -// receiver, which must be a pointer to be useful. The Scan method is called -// for any argument to Scan, Scanf, or Scanln that implements it. -type Scanner interface { - Scan(state ScanState, verb int) os.Error -} - -// Scan scans text read from standard input, storing successive -// space-separated values into successive arguments. Newlines count -// as space. It returns the number of items successfully scanned. -// If that is less than the number of arguments, err will report why. -func Scan(a ...interface{}) (n int, err os.Error) { - return Fscan(os.Stdin, a...) -} - -// Scanln is similar to Scan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Scanln(a ...interface{}) (n int, err os.Error) { - return Fscanln(os.Stdin, a...) -} - -// Scanf scans text read from standard input, storing successive -// space-separated values into successive arguments as determined by -// the format. It returns the number of items successfully scanned. -func Scanf(format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(os.Stdin, format, a...) -} - -// Sscan scans the argument string, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less -// than the number of arguments, err will report why. -func Sscan(str string, a ...interface{}) (n int, err os.Error) { - return Fscan(strings.NewReader(str), a...) -} - -// Sscanln is similar to Sscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Sscanln(str string, a ...interface{}) (n int, err os.Error) { - return Fscanln(strings.NewReader(str), a...) -} - -// Sscanf scans the argument string, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Sscanf(str string, format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(strings.NewReader(str), format, a...) -} - -// Fscan scans text read from r, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less -// than the number of arguments, err will report why. -func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, true, false) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanln is similar to Fscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, true) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanf scans text read from r, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, false) - n, err = s.doScanf(format, a) - s.free(old) - return -} - -// scanError represents an error generated by the scanning software. -// It's used as a unique signature to identify such errors when recovering. -type scanError struct { - err os.Error -} - -const eof = -1 - -// ss is the internal implementation of ScanState. -type ss struct { - rr io.RuneReader // where to read input - buf bytes.Buffer // token accumulator - peekRune int // one-rune lookahead - prevRune int // last rune returned by ReadRune - count int // runes consumed so far. - atEOF bool // already read EOF - ssave -} - -// ssave holds the parts of ss that need to be -// saved and restored on recursive scans. -type ssave struct { - validSave bool // is or was a part of an actual ss. - nlIsEnd bool // whether newline terminates scan - nlIsSpace bool // whether newline counts as white space - fieldLimit int // max value of ss.count for this field; fieldLimit <= limit - limit int // max value of ss.count. - maxWid int // width of this field. -} - -// The Read method is only in ScanState so that ScanState -// satisfies io.Reader. It will never be called when used as -// intended, so there is no need to make it actually work. -func (s *ss) Read(buf []byte) (n int, err os.Error) { - return 0, os.NewError("ScanState's Read should not be called. Use ReadRune") -} - -func (s *ss) ReadRune() (rune int, size int, err os.Error) { - if s.peekRune >= 0 { - s.count++ - rune = s.peekRune - size = utf8.RuneLen(rune) - s.prevRune = rune - s.peekRune = -1 - return - } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit { - err = os.EOF - return - } - - rune, size, err = s.rr.ReadRune() - if err == nil { - s.count++ - s.prevRune = rune - } else if err == os.EOF { - s.atEOF = true - } - return -} - -func (s *ss) Width() (wid int, ok bool) { - if s.maxWid == hugeWid { - return 0, false - } - return s.maxWid, true -} - -// The public method returns an error; this private one panics. -// If getRune reaches EOF, the return value is EOF (-1). -func (s *ss) getRune() (rune int) { - rune, _, err := s.ReadRune() - if err != nil { - if err == os.EOF { - return eof - } - s.error(err) - } - return -} - -// mustReadRune turns os.EOF into a panic(io.ErrUnexpectedEOF). -// It is called in cases such as string scanning where an EOF is a -// syntax error. -func (s *ss) mustReadRune() (rune int) { - rune = s.getRune() - if rune == eof { - s.error(io.ErrUnexpectedEOF) - } - return -} - -func (s *ss) UnreadRune() os.Error { - if u, ok := s.rr.(runeUnreader); ok { - u.UnreadRune() - } else { - s.peekRune = s.prevRune - } - s.count-- - return nil -} - -func (s *ss) error(err os.Error) { - panic(scanError{err}) -} - -func (s *ss) errorString(err string) { - panic(scanError{os.NewError(err)}) -} - -func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) { - defer func() { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { - err = se.err - } else { - panic(e) - } - } - }() - if f == nil { - f = notSpace - } - s.buf.Reset() - tok = s.token(skipSpace, f) - return -} - -// notSpace is the default scanning function used in Token. -func notSpace(r int) bool { - return !unicode.IsSpace(r) -} - -// readRune is a structure to enable reading UTF-8 encoded code points -// from an io.Reader. It is used if the Reader given to the scanner does -// not already implement io.RuneReader. -type readRune struct { - reader io.Reader - buf [utf8.UTFMax]byte // used only inside ReadRune - pending int // number of bytes in pendBuf; only >0 for bad UTF-8 - pendBuf [utf8.UTFMax]byte // bytes left over -} - -// readByte returns the next byte from the input, which may be -// left over from a previous read if the UTF-8 was ill-formed. -func (r *readRune) readByte() (b byte, err os.Error) { - if r.pending > 0 { - b = r.pendBuf[0] - copy(r.pendBuf[0:], r.pendBuf[1:]) - r.pending-- - return - } - _, err = r.reader.Read(r.pendBuf[0:1]) - return r.pendBuf[0], err -} - -// unread saves the bytes for the next read. -func (r *readRune) unread(buf []byte) { - copy(r.pendBuf[r.pending:], buf) - r.pending += len(buf) -} - -// ReadRune returns the next UTF-8 encoded code point from the -// io.Reader inside r. -func (r *readRune) ReadRune() (rune int, size int, err os.Error) { - r.buf[0], err = r.readByte() - if err != nil { - return 0, 0, err - } - if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case - rune = int(r.buf[0]) - return - } - var n int - for n = 1; !utf8.FullRune(r.buf[0:n]); n++ { - r.buf[n], err = r.readByte() - if err != nil { - if err == os.EOF { - err = nil - break - } - return - } - } - rune, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) - } - return -} - -var ssFree = newCache(func() interface{} { return new(ss) }) - -// Allocate a new ss struct or grab a cached one. -func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { - // If the reader is a *ss, then we've got a recursive - // call to Scan, so re-use the scan state. - s, ok := r.(*ss) - if ok { - old = s.ssave - s.limit = s.fieldLimit - s.nlIsEnd = nlIsEnd || s.nlIsEnd - s.nlIsSpace = nlIsSpace - return - } - - s = ssFree.get().(*ss) - if rr, ok := r.(io.RuneReader); ok { - s.rr = rr - } else { - s.rr = &readRune{reader: r} - } - s.nlIsSpace = nlIsSpace - s.nlIsEnd = nlIsEnd - s.prevRune = -1 - s.peekRune = -1 - s.atEOF = false - s.limit = hugeWid - s.fieldLimit = hugeWid - s.maxWid = hugeWid - s.validSave = true - return -} - -// Save used ss structs in ssFree; avoid an allocation per invocation. -func (s *ss) free(old ssave) { - // If it was used recursively, just restore the old state. - if old.validSave { - s.ssave = old - return - } - // Don't hold on to ss structs with large buffers. - if cap(s.buf.Bytes()) > 1024 { - return - } - s.buf.Reset() - s.rr = nil - ssFree.put(s) -} - -// skipSpace skips spaces and maybe newlines. -func (s *ss) skipSpace(stopAtNewline bool) { - for { - rune := s.getRune() - if rune == eof { - return - } - if rune == '\n' { - if stopAtNewline { - break - } - if s.nlIsSpace { - continue - } - s.errorString("unexpected newline") - return - } - if !unicode.IsSpace(rune) { - s.UnreadRune() - break - } - } -} - -// token returns the next space-delimited string from the input. It -// skips white space. For Scanln, it stops at newlines. For Scan, -// newlines are treated as spaces. -func (s *ss) token(skipSpace bool, f func(int) bool) []byte { - if skipSpace { - s.skipSpace(false) - } - // read until white space or newline - for { - rune := s.getRune() - if rune == eof { - break - } - if !f(rune) { - s.UnreadRune() - break - } - s.buf.WriteRune(rune) - } - return s.buf.Bytes() -} - -// typeError indicates that the type of the operand did not match the format -func (s *ss) typeError(field interface{}, expected string) { - s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String()) -} - -var complexError = os.NewError("syntax error scanning complex number") -var boolError = os.NewError("syntax error scanning boolean") - -// consume reads the next rune in the input and reports whether it is in the ok string. -// If accept is true, it puts the character into the input token. -func (s *ss) consume(ok string, accept bool) bool { - rune := s.getRune() - if rune == eof { - return false - } - if strings.IndexRune(ok, rune) >= 0 { - if accept { - s.buf.WriteRune(rune) - } - return true - } - if rune != eof && accept { - s.UnreadRune() - } - return false -} - -// peek reports whether the next character is in the ok string, without consuming it. -func (s *ss) peek(ok string) bool { - rune := s.getRune() - if rune != eof { - s.UnreadRune() - } - return strings.IndexRune(ok, rune) >= 0 -} - -// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the -// buffer and returns true. Otherwise it return false. -func (s *ss) accept(ok string) bool { - return s.consume(ok, true) -} - -// okVerb verifies that the verb is present in the list, setting s.err appropriately if not. -func (s *ss) okVerb(verb int, okVerbs, typ string) bool { - for _, v := range okVerbs { - if v == verb { - return true - } - } - s.errorString("bad verb %" + string(verb) + " for " + typ) - return false -} - -// scanBool returns the value of the boolean represented by the next token. -func (s *ss) scanBool(verb int) bool { - if !s.okVerb(verb, "tv", "boolean") { - return false - } - // Syntax-checking a boolean is annoying. We're not fastidious about case. - switch s.mustReadRune() { - case '0': - return false - case '1': - return true - case 't', 'T': - if s.accept("rR") && (!s.accept("uU") || !s.accept("eE")) { - s.error(boolError) - } - return true - case 'f', 'F': - if s.accept("aL") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) { - s.error(boolError) - } - return false - } - return false -} - -// Numerical elements -const ( - binaryDigits = "01" - octalDigits = "01234567" - decimalDigits = "0123456789" - hexadecimalDigits = "0123456789aAbBcCdDeEfF" - sign = "+-" - period = "." - exponent = "eEp" -) - -// getBase returns the numeric base represented by the verb and its digit string. -func (s *ss) getBase(verb int) (base int, digits string) { - s.okVerb(verb, "bdoUxXv", "integer") // sets s.err - base = 10 - digits = decimalDigits - switch verb { - case 'b': - base = 2 - digits = binaryDigits - case 'o': - base = 8 - digits = octalDigits - case 'x', 'X', 'U': - base = 16 - digits = hexadecimalDigits - } - return -} - -// scanNumber returns the numerical string with specified digits starting here. -func (s *ss) scanNumber(digits string, haveDigits bool) string { - if !haveDigits && !s.accept(digits) { - s.errorString("expected integer") - } - for s.accept(digits) { - } - return s.buf.String() -} - -// scanRune returns the next rune value in the input. -func (s *ss) scanRune(bitSize int) int64 { - rune := int64(s.mustReadRune()) - n := uint(bitSize) - x := (rune << (64 - n)) >> (64 - n) - if x != rune { - s.errorString("overflow on character value " + string(rune)) - } - return rune -} - -// scanBasePrefix reports whether the integer begins with a 0 or 0x, -// and returns the base, digit string, and whether a zero was found. -// It is called only if the verb is %v. -func (s *ss) scanBasePrefix() (base int, digits string, found bool) { - if !s.peek("0") { - return 10, decimalDigits, false - } - s.accept("0") - found = true // We've put a digit into the token buffer. - // Special cases for '0' && '0x' - base, digits = 8, octalDigits - if s.peek("xX") { - s.consume("xX", false) - base, digits = 16, hexadecimalDigits - } - return -} - -// scanInt returns the value of the integer represented by the next -// token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanInt(verb int, bitSize int) int64 { - if verb == 'c' { - return s.scanRune(bitSize) - } - s.skipSpace(false) - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else { - s.accept(sign) // If there's a sign, it will be left in the token buffer. - if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoi64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("integer overflow on token " + tok) - } - return i -} - -// scanUint returns the value of the unsigned integer represented -// by the next token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanUint(verb int, bitSize int) uint64 { - if verb == 'c' { - return uint64(s.scanRune(bitSize)) - } - s.skipSpace(false) - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoui64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("unsigned integer overflow on token " + tok) - } - return i -} - -// floatToken returns the floating-point number starting here, no longer than swid -// if the width is specified. It's not rigorous about syntax because it doesn't check that -// we have at least some digits, but Atof will do that. -func (s *ss) floatToken() string { - s.buf.Reset() - // NaN? - if s.accept("nN") && s.accept("aA") && s.accept("nN") { - return s.buf.String() - } - // leading sign? - s.accept(sign) - // Inf? - if s.accept("iI") && s.accept("nN") && s.accept("fF") { - return s.buf.String() - } - // digits? - for s.accept(decimalDigits) { - } - // decimal point? - if s.accept(period) { - // fraction? - for s.accept(decimalDigits) { - } - } - // exponent? - if s.accept(exponent) { - // leading sign? - s.accept(sign) - // digits? - for s.accept(decimalDigits) { - } - } - return s.buf.String() -} - -// complexTokens returns the real and imaginary parts of the complex number starting here. -// The number might be parenthesized and has the format (N+Ni) where N is a floating-point -// number and there are no spaces within. -func (s *ss) complexTokens() (real, imag string) { - // TODO: accept N and Ni independently? - parens := s.accept("(") - real = s.floatToken() - s.buf.Reset() - // Must now have a sign. - if !s.accept("+-") { - s.error(complexError) - } - // Sign is now in buffer - imagSign := s.buf.String() - imag = s.floatToken() - if !s.accept("i") { - s.error(complexError) - } - if parens && !s.accept(")") { - s.error(complexError) - } - return real, imagSign + imag -} - -// convertFloat converts the string to a float64value. -func (s *ss) convertFloat(str string, n int) float64 { - if p := strings.Index(str, "p"); p >= 0 { - // Atof doesn't handle power-of-2 exponents, - // but they're easy to evaluate. - f, err := strconv.AtofN(str[:p], n) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - n, err := strconv.Atoi(str[p+1:]) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - return math.Ldexp(f, n) - } - f, err := strconv.AtofN(str, n) - if err != nil { - s.error(err) - } - return f -} - -// convertComplex converts the next token to a complex128 value. -// The atof argument is a type-specific reader for the underlying type. -// If we're reading complex64, atof will parse float32s and convert them -// to float64's to avoid reproducing this code for each complex type. -func (s *ss) scanComplex(verb int, n int) complex128 { - if !s.okVerb(verb, floatVerbs, "complex") { - return 0 - } - s.skipSpace(false) - sreal, simag := s.complexTokens() - real := s.convertFloat(sreal, n/2) - imag := s.convertFloat(simag, n/2) - return complex(real, imag) -} - -// convertString returns the string represented by the next input characters. -// The format of the input is determined by the verb. -func (s *ss) convertString(verb int) (str string) { - if !s.okVerb(verb, "svqx", "string") { - return "" - } - s.skipSpace(false) - switch verb { - case 'q': - str = s.quotedString() - case 'x': - str = s.hexString() - default: - str = string(s.token(true, notSpace)) // %s and %v just return the next word - } - // Empty strings other than with %q are not OK. - if len(str) == 0 && verb != 'q' && s.maxWid > 0 { - s.errorString("Scan: no data for string") - } - return -} - -// quotedString returns the double- or back-quoted string represented by the next input characters. -func (s *ss) quotedString() string { - quote := s.mustReadRune() - switch quote { - case '`': - // Back-quoted: Anything goes until EOF or back quote. - for { - rune := s.mustReadRune() - if rune == quote { - break - } - s.buf.WriteRune(rune) - } - return s.buf.String() - case '"': - // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) - for { - rune := s.mustReadRune() - s.buf.WriteRune(rune) - if rune == '\\' { - // In a legal backslash escape, no matter how long, only the character - // immediately after the escape can itself be a backslash or quote. - // Thus we only need to protect the first character after the backslash. - rune := s.mustReadRune() - s.buf.WriteRune(rune) - } else if rune == '"' { - break - } - } - result, err := strconv.Unquote(s.buf.String()) - if err != nil { - s.error(err) - } - return result - default: - s.errorString("expected quoted string") - } - return "" -} - -// hexDigit returns the value of the hexadecimal digit -func (s *ss) hexDigit(digit int) int { - switch digit { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return digit - '0' - case 'a', 'b', 'c', 'd', 'e', 'f': - return 10 + digit - 'a' - case 'A', 'B', 'C', 'D', 'E', 'F': - return 10 + digit - 'A' - } - s.errorString("Scan: illegal hex digit") - return 0 -} - -// hexByte returns the next hex-encoded (two-character) byte from the input. -// There must be either two hexadecimal digits or a space character in the input. -func (s *ss) hexByte() (b byte, ok bool) { - rune1 := s.getRune() - if rune1 == eof { - return - } - if unicode.IsSpace(rune1) { - s.UnreadRune() - return - } - rune2 := s.mustReadRune() - return byte(s.hexDigit(rune1)<<4 | s.hexDigit(rune2)), true -} - -// hexString returns the space-delimited hexpair-encoded string. -func (s *ss) hexString() string { - for { - b, ok := s.hexByte() - if !ok { - break - } - s.buf.WriteByte(b) - } - if s.buf.Len() == 0 { - s.errorString("Scan: no hex data for %x string") - return "" - } - return s.buf.String() -} - -const floatVerbs = "beEfFgGv" - -const hugeWid = 1 << 30 - -// scanOne scans a single value, deriving the scanner from the type of the argument. -func (s *ss) scanOne(verb int, field interface{}) { - s.buf.Reset() - var err os.Error - // If the parameter has its own Scan method, use that. - if v, ok := field.(Scanner); ok { - err = v.Scan(s, verb) - if err != nil { - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - s.error(err) - } - return - } - switch v := field.(type) { - case *bool: - *v = s.scanBool(verb) - case *complex64: - *v = complex64(s.scanComplex(verb, 64)) - case *complex128: - *v = s.scanComplex(verb, 128) - case *int: - *v = int(s.scanInt(verb, intBits)) - case *int8: - *v = int8(s.scanInt(verb, 8)) - case *int16: - *v = int16(s.scanInt(verb, 16)) - case *int32: - *v = int32(s.scanInt(verb, 32)) - case *int64: - *v = s.scanInt(verb, 64) - case *uint: - *v = uint(s.scanUint(verb, intBits)) - case *uint8: - *v = uint8(s.scanUint(verb, 8)) - case *uint16: - *v = uint16(s.scanUint(verb, 16)) - case *uint32: - *v = uint32(s.scanUint(verb, 32)) - case *uint64: - *v = s.scanUint(verb, 64) - case *uintptr: - *v = uintptr(s.scanUint(verb, uintptrBits)) - // Floats are tricky because you want to scan in the precision of the result, not - // scan in high precision and convert, in order to preserve the correct error condition. - case *float32: - if s.okVerb(verb, floatVerbs, "float32") { - s.skipSpace(false) - *v = float32(s.convertFloat(s.floatToken(), 32)) - } - case *float64: - if s.okVerb(verb, floatVerbs, "float64") { - s.skipSpace(false) - *v = s.convertFloat(s.floatToken(), 64) - } - case *string: - *v = s.convertString(verb) - case *[]byte: - // We scan to string and convert so we get a copy of the data. - // If we scanned to bytes, the slice would point at the buffer. - *v = []byte(s.convertString(verb)) - default: - val := reflect.ValueOf(v) - ptr := val - if ptr.Kind() != reflect.Ptr { - s.errorString("Scan: type not a pointer: " + val.Type().String()) - return - } - switch v := ptr.Elem(); v.Kind() { - case reflect.Bool: - v.SetBool(s.scanBool(verb)) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v.SetInt(s.scanInt(verb, v.Type().Bits())) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - v.SetUint(s.scanUint(verb, v.Type().Bits())) - case reflect.String: - v.SetString(s.convertString(verb)) - case reflect.Slice: - // For now, can only handle (renamed) []byte. - typ := v.Type() - if typ.Elem().Kind() != reflect.Uint8 { - goto CantHandle - } - str := s.convertString(verb) - v.Set(reflect.MakeSlice(typ, len(str), len(str))) - for i := 0; i < len(str); i++ { - v.Index(i).SetUint(uint64(str[i])) - } - case reflect.Float32, reflect.Float64: - s.skipSpace(false) - v.SetFloat(s.convertFloat(s.floatToken(), v.Type().Bits())) - case reflect.Complex64, reflect.Complex128: - v.SetComplex(s.scanComplex(verb, v.Type().Bits())) - default: - CantHandle: - s.errorString("Scan: can't handle type: " + val.Type().String()) - } - } -} - -// errorHandler turns local panics into error returns. EOFs are benign. -func errorHandler(errp *os.Error) { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { // catch local error - if se.err != os.EOF { - *errp = se.err - } - } else { - panic(e) - } - } -} - -// doScan does the real work for scanning without a format string. -func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - for _, field := range a { - s.scanOne('v', field) - numProcessed++ - } - // Check for newline if required. - if !s.nlIsSpace { - for { - rune := s.getRune() - if rune == '\n' || rune == eof { - break - } - if !unicode.IsSpace(rune) { - s.errorString("Scan: expected newline") - break - } - } - } - return -} - -// advance determines whether the next characters in the input match -// those of the format. It returns the number of bytes (sic) consumed -// in the format. Newlines included, all runs of space characters in -// either input or format behave as a single space. This routine also -// handles the %% case. If the return value is zero, either format -// starts with a % (with no following %) or the input is empty. -// If it is negative, the input did not match the string. -func (s *ss) advance(format string) (i int) { - for i < len(format) { - fmtc, w := utf8.DecodeRuneInString(format[i:]) - if fmtc == '%' { - // %% acts like a real percent - nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty - if nextc != '%' { - return - } - i += w // skip the first % - } - sawSpace := false - for unicode.IsSpace(fmtc) && i < len(format) { - sawSpace = true - i += w - fmtc, w = utf8.DecodeRuneInString(format[i:]) - } - if sawSpace { - // There was space in the format, so there should be space (EOF) - // in the input. - inputc := s.getRune() - if inputc == eof { - return - } - if !unicode.IsSpace(inputc) { - // Space in format but not in input: error - s.errorString("expected space in input to match format") - } - s.skipSpace(true) - continue - } - inputc := s.mustReadRune() - if fmtc != inputc { - s.UnreadRune() - return -1 - } - i += w - } - return -} - -// doScanf does the real work when scanning with a format string. -// At the moment, it handles only pointers to basic types. -func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - end := len(format) - 1 - // We process one item per non-trivial format - for i := 0; i <= end; { - w := s.advance(format[i:]) - if w > 0 { - i += w - continue - } - // Either we failed to advance, we have a percent character, or we ran out of input. - if format[i] != '%' { - // Can't advance format. Why not? - if w < 0 { - s.errorString("input does not match format") - } - // Otherwise at EOF; "too many operands" error handled below - break - } - i++ // % is one byte - - // do we have 20 (width)? - var widPresent bool - s.maxWid, widPresent, i = parsenum(format, i, end) - if !widPresent { - s.maxWid = hugeWid - } - s.fieldLimit = s.limit - if f := s.count + s.maxWid; f < s.fieldLimit { - s.fieldLimit = f - } - - c, w := utf8.DecodeRuneInString(format[i:]) - i += w - - if numProcessed >= len(a) { // out of operands - s.errorString("too few operands for format %" + format[i-w:]) - break - } - field := a[numProcessed] - - s.scanOne(c, field) - numProcessed++ - s.fieldLimit = s.limit - } - if numProcessed < len(a) { - s.errorString("too many operands") - } - return -} diff --git a/src/cmd/fix/testdata/reflect.script.go.in b/src/cmd/fix/testdata/reflect.script.go.in deleted file mode 100644 index b341b1f896..0000000000 --- a/src/cmd/fix/testdata/reflect.script.go.in +++ /dev/null @@ -1,359 +0,0 @@ -// 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. - -// This package aids in the testing of code that uses channels. -package script - -import ( - "fmt" - "os" - "rand" - "reflect" - "strings" -) - -// An Event is an element in a partially ordered set that either sends a value -// to a channel or expects a value from a channel. -type Event struct { - name string - occurred bool - predecessors []*Event - action action -} - -type action interface { - // getSend returns nil if the action is not a send action. - getSend() sendAction - // getRecv returns nil if the action is not a receive action. - getRecv() recvAction - // getChannel returns the channel that the action operates on. - getChannel() interface{} -} - -type recvAction interface { - recvMatch(interface{}) bool -} - -type sendAction interface { - send() -} - -// isReady returns true if all the predecessors of an Event have occurred. -func (e Event) isReady() bool { - for _, predecessor := range e.predecessors { - if !predecessor.occurred { - return false - } - } - - return true -} - -// A Recv action reads a value from a channel and uses reflect.DeepMatch to -// compare it with an expected value. -type Recv struct { - Channel interface{} - Expected interface{} -} - -func (r Recv) getRecv() recvAction { return r } - -func (Recv) getSend() sendAction { return nil } - -func (r Recv) getChannel() interface{} { return r.Channel } - -func (r Recv) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelRecv) - if !ok || c.channel != r.Channel { - return false - } - - return reflect.DeepEqual(c.value, r.Expected) -} - -// A RecvMatch action reads a value from a channel and calls a function to -// determine if the value matches. -type RecvMatch struct { - Channel interface{} - Match func(interface{}) bool -} - -func (r RecvMatch) getRecv() recvAction { return r } - -func (RecvMatch) getSend() sendAction { return nil } - -func (r RecvMatch) getChannel() interface{} { return r.Channel } - -func (r RecvMatch) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelRecv) - if !ok || c.channel != r.Channel { - return false - } - - return r.Match(c.value) -} - -// A Closed action matches if the given channel is closed. The closing is -// treated as an event, not a state, thus Closed will only match once for a -// given channel. -type Closed struct { - Channel interface{} -} - -func (r Closed) getRecv() recvAction { return r } - -func (Closed) getSend() sendAction { return nil } - -func (r Closed) getChannel() interface{} { return r.Channel } - -func (r Closed) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelClosed) - if !ok || c.channel != r.Channel { - return false - } - - return true -} - -// A Send action sends a value to a channel. The value must match the -// type of the channel exactly unless the channel if of type chan interface{}. -type Send struct { - Channel interface{} - Value interface{} -} - -func (Send) getRecv() recvAction { return nil } - -func (s Send) getSend() sendAction { return s } - -func (s Send) getChannel() interface{} { return s.Channel } - -type empty struct { - x interface{} -} - -func newEmptyInterface(e empty) reflect.Value { - return reflect.NewValue(e).(*reflect.StructValue).Field(0) -} - -func (s Send) send() { - // With reflect.ChanValue.Send, we must match the types exactly. So, if - // s.Channel is a chan interface{} we convert s.Value to an interface{} - // first. - c := reflect.NewValue(s.Channel).(*reflect.ChanValue) - var v reflect.Value - if iface, ok := c.Type().(*reflect.ChanType).Elem().(*reflect.InterfaceType); ok && iface.NumMethod() == 0 { - v = newEmptyInterface(empty{s.Value}) - } else { - v = reflect.NewValue(s.Value) - } - c.Send(v) -} - -// A Close action closes the given channel. -type Close struct { - Channel interface{} -} - -func (Close) getRecv() recvAction { return nil } - -func (s Close) getSend() sendAction { return s } - -func (s Close) getChannel() interface{} { return s.Channel } - -func (s Close) send() { reflect.NewValue(s.Channel).(*reflect.ChanValue).Close() } - -// A ReceivedUnexpected error results if no active Events match a value -// received from a channel. -type ReceivedUnexpected struct { - Value interface{} - ready []*Event -} - -func (r ReceivedUnexpected) String() string { - names := make([]string, len(r.ready)) - for i, v := range r.ready { - names[i] = v.name - } - return fmt.Sprintf("received unexpected value on one of the channels: %#v. Runnable events: %s", r.Value, strings.Join(names, ", ")) -} - -// A SetupError results if there is a error with the configuration of a set of -// Events. -type SetupError string - -func (s SetupError) String() string { return string(s) } - -func NewEvent(name string, predecessors []*Event, action action) *Event { - e := &Event{name, false, predecessors, action} - return e -} - -// Given a set of Events, Perform repeatedly iterates over the set and finds the -// subset of ready Events (that is, all of their predecessors have -// occurred). From that subset, it pseudo-randomly selects an Event to perform. -// If the Event is a send event, the send occurs and Perform recalculates the ready -// set. If the event is a receive event, Perform waits for a value from any of the -// channels that are contained in any of the events. That value is then matched -// against the ready events. The first event that matches is considered to -// have occurred and Perform recalculates the ready set. -// -// Perform continues this until all Events have occurred. -// -// Note that uncollected goroutines may still be reading from any of the -// channels read from after Perform returns. -// -// For example, consider the problem of testing a function that reads values on -// one channel and echos them to two output channels. To test this we would -// create three events: a send event and two receive events. Each of the -// receive events must list the send event as a predecessor but there is no -// ordering between the receive events. -// -// send := NewEvent("send", nil, Send{c, 1}) -// recv1 := NewEvent("recv 1", []*Event{send}, Recv{c, 1}) -// recv2 := NewEvent("recv 2", []*Event{send}, Recv{c, 1}) -// Perform(0, []*Event{send, recv1, recv2}) -// -// At first, only the send event would be in the ready set and thus Perform will -// send a value to the input channel. Now the two receive events are ready and -// Perform will match each of them against the values read from the output channels. -// -// It would be invalid to list one of the receive events as a predecessor of -// the other. At each receive step, all the receive channels are considered, -// thus Perform may see a value from a channel that is not in the current ready -// set and fail. -func Perform(seed int64, events []*Event) (err os.Error) { - r := rand.New(rand.NewSource(seed)) - - channels, err := getChannels(events) - if err != nil { - return - } - multiplex := make(chan interface{}) - for _, channel := range channels { - go recvValues(multiplex, channel) - } - -Outer: - for { - ready, err := readyEvents(events) - if err != nil { - return err - } - - if len(ready) == 0 { - // All events occurred. - break - } - - event := ready[r.Intn(len(ready))] - if send := event.action.getSend(); send != nil { - send.send() - event.occurred = true - continue - } - - v := <-multiplex - for _, event := range ready { - if recv := event.action.getRecv(); recv != nil && recv.recvMatch(v) { - event.occurred = true - continue Outer - } - } - - return ReceivedUnexpected{v, ready} - } - - return nil -} - -// getChannels returns all the channels listed in any receive events. -func getChannels(events []*Event) ([]interface{}, os.Error) { - channels := make([]interface{}, len(events)) - - j := 0 - for _, event := range events { - if recv := event.action.getRecv(); recv == nil { - continue - } - c := event.action.getChannel() - if _, ok := reflect.NewValue(c).(*reflect.ChanValue); !ok { - return nil, SetupError("one of the channel values is not a channel") - } - - duplicate := false - for _, other := range channels[0:j] { - if c == other { - duplicate = true - break - } - } - - if !duplicate { - channels[j] = c - j++ - } - } - - return channels[0:j], nil -} - -// recvValues is a multiplexing helper function. It reads values from the given -// channel repeatedly, wrapping them up as either a channelRecv or -// channelClosed structure, and forwards them to the multiplex channel. -func recvValues(multiplex chan<- interface{}, channel interface{}) { - c := reflect.NewValue(channel).(*reflect.ChanValue) - - for { - v, ok := c.Recv() - if !ok { - multiplex <- channelClosed{channel} - return - } - - multiplex <- channelRecv{channel, v.Interface()} - } -} - -type channelClosed struct { - channel interface{} -} - -type channelRecv struct { - channel interface{} - value interface{} -} - -// readyEvents returns the subset of events that are ready. -func readyEvents(events []*Event) ([]*Event, os.Error) { - ready := make([]*Event, len(events)) - - j := 0 - eventsWaiting := false - for _, event := range events { - if event.occurred { - continue - } - - eventsWaiting = true - if event.isReady() { - ready[j] = event - j++ - } - } - - if j == 0 && eventsWaiting { - names := make([]string, len(events)) - for _, event := range events { - if event.occurred { - continue - } - names[j] = event.name - } - - return nil, SetupError("dependency cycle in events. These events are waiting to run but cannot: " + strings.Join(names, ", ")) - } - - return ready[0:j], nil -} diff --git a/src/cmd/fix/testdata/reflect.script.go.out b/src/cmd/fix/testdata/reflect.script.go.out deleted file mode 100644 index bc5a6a41d9..0000000000 --- a/src/cmd/fix/testdata/reflect.script.go.out +++ /dev/null @@ -1,359 +0,0 @@ -// 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. - -// This package aids in the testing of code that uses channels. -package script - -import ( - "fmt" - "os" - "rand" - "reflect" - "strings" -) - -// An Event is an element in a partially ordered set that either sends a value -// to a channel or expects a value from a channel. -type Event struct { - name string - occurred bool - predecessors []*Event - action action -} - -type action interface { - // getSend returns nil if the action is not a send action. - getSend() sendAction - // getRecv returns nil if the action is not a receive action. - getRecv() recvAction - // getChannel returns the channel that the action operates on. - getChannel() interface{} -} - -type recvAction interface { - recvMatch(interface{}) bool -} - -type sendAction interface { - send() -} - -// isReady returns true if all the predecessors of an Event have occurred. -func (e Event) isReady() bool { - for _, predecessor := range e.predecessors { - if !predecessor.occurred { - return false - } - } - - return true -} - -// A Recv action reads a value from a channel and uses reflect.DeepMatch to -// compare it with an expected value. -type Recv struct { - Channel interface{} - Expected interface{} -} - -func (r Recv) getRecv() recvAction { return r } - -func (Recv) getSend() sendAction { return nil } - -func (r Recv) getChannel() interface{} { return r.Channel } - -func (r Recv) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelRecv) - if !ok || c.channel != r.Channel { - return false - } - - return reflect.DeepEqual(c.value, r.Expected) -} - -// A RecvMatch action reads a value from a channel and calls a function to -// determine if the value matches. -type RecvMatch struct { - Channel interface{} - Match func(interface{}) bool -} - -func (r RecvMatch) getRecv() recvAction { return r } - -func (RecvMatch) getSend() sendAction { return nil } - -func (r RecvMatch) getChannel() interface{} { return r.Channel } - -func (r RecvMatch) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelRecv) - if !ok || c.channel != r.Channel { - return false - } - - return r.Match(c.value) -} - -// A Closed action matches if the given channel is closed. The closing is -// treated as an event, not a state, thus Closed will only match once for a -// given channel. -type Closed struct { - Channel interface{} -} - -func (r Closed) getRecv() recvAction { return r } - -func (Closed) getSend() sendAction { return nil } - -func (r Closed) getChannel() interface{} { return r.Channel } - -func (r Closed) recvMatch(chanEvent interface{}) bool { - c, ok := chanEvent.(channelClosed) - if !ok || c.channel != r.Channel { - return false - } - - return true -} - -// A Send action sends a value to a channel. The value must match the -// type of the channel exactly unless the channel if of type chan interface{}. -type Send struct { - Channel interface{} - Value interface{} -} - -func (Send) getRecv() recvAction { return nil } - -func (s Send) getSend() sendAction { return s } - -func (s Send) getChannel() interface{} { return s.Channel } - -type empty struct { - x interface{} -} - -func newEmptyInterface(e empty) reflect.Value { - return reflect.ValueOf(e).Field(0) -} - -func (s Send) send() { - // With reflect.ChanValue.Send, we must match the types exactly. So, if - // s.Channel is a chan interface{} we convert s.Value to an interface{} - // first. - c := reflect.ValueOf(s.Channel) - var v reflect.Value - if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 { - v = newEmptyInterface(empty{s.Value}) - } else { - v = reflect.ValueOf(s.Value) - } - c.Send(v) -} - -// A Close action closes the given channel. -type Close struct { - Channel interface{} -} - -func (Close) getRecv() recvAction { return nil } - -func (s Close) getSend() sendAction { return s } - -func (s Close) getChannel() interface{} { return s.Channel } - -func (s Close) send() { reflect.ValueOf(s.Channel).Close() } - -// A ReceivedUnexpected error results if no active Events match a value -// received from a channel. -type ReceivedUnexpected struct { - Value interface{} - ready []*Event -} - -func (r ReceivedUnexpected) String() string { - names := make([]string, len(r.ready)) - for i, v := range r.ready { - names[i] = v.name - } - return fmt.Sprintf("received unexpected value on one of the channels: %#v. Runnable events: %s", r.Value, strings.Join(names, ", ")) -} - -// A SetupError results if there is a error with the configuration of a set of -// Events. -type SetupError string - -func (s SetupError) String() string { return string(s) } - -func NewEvent(name string, predecessors []*Event, action action) *Event { - e := &Event{name, false, predecessors, action} - return e -} - -// Given a set of Events, Perform repeatedly iterates over the set and finds the -// subset of ready Events (that is, all of their predecessors have -// occurred). From that subset, it pseudo-randomly selects an Event to perform. -// If the Event is a send event, the send occurs and Perform recalculates the ready -// set. If the event is a receive event, Perform waits for a value from any of the -// channels that are contained in any of the events. That value is then matched -// against the ready events. The first event that matches is considered to -// have occurred and Perform recalculates the ready set. -// -// Perform continues this until all Events have occurred. -// -// Note that uncollected goroutines may still be reading from any of the -// channels read from after Perform returns. -// -// For example, consider the problem of testing a function that reads values on -// one channel and echos them to two output channels. To test this we would -// create three events: a send event and two receive events. Each of the -// receive events must list the send event as a predecessor but there is no -// ordering between the receive events. -// -// send := NewEvent("send", nil, Send{c, 1}) -// recv1 := NewEvent("recv 1", []*Event{send}, Recv{c, 1}) -// recv2 := NewEvent("recv 2", []*Event{send}, Recv{c, 1}) -// Perform(0, []*Event{send, recv1, recv2}) -// -// At first, only the send event would be in the ready set and thus Perform will -// send a value to the input channel. Now the two receive events are ready and -// Perform will match each of them against the values read from the output channels. -// -// It would be invalid to list one of the receive events as a predecessor of -// the other. At each receive step, all the receive channels are considered, -// thus Perform may see a value from a channel that is not in the current ready -// set and fail. -func Perform(seed int64, events []*Event) (err os.Error) { - r := rand.New(rand.NewSource(seed)) - - channels, err := getChannels(events) - if err != nil { - return - } - multiplex := make(chan interface{}) - for _, channel := range channels { - go recvValues(multiplex, channel) - } - -Outer: - for { - ready, err := readyEvents(events) - if err != nil { - return err - } - - if len(ready) == 0 { - // All events occurred. - break - } - - event := ready[r.Intn(len(ready))] - if send := event.action.getSend(); send != nil { - send.send() - event.occurred = true - continue - } - - v := <-multiplex - for _, event := range ready { - if recv := event.action.getRecv(); recv != nil && recv.recvMatch(v) { - event.occurred = true - continue Outer - } - } - - return ReceivedUnexpected{v, ready} - } - - return nil -} - -// getChannels returns all the channels listed in any receive events. -func getChannels(events []*Event) ([]interface{}, os.Error) { - channels := make([]interface{}, len(events)) - - j := 0 - for _, event := range events { - if recv := event.action.getRecv(); recv == nil { - continue - } - c := event.action.getChannel() - if reflect.ValueOf(c).Kind() != reflect.Chan { - return nil, SetupError("one of the channel values is not a channel") - } - - duplicate := false - for _, other := range channels[0:j] { - if c == other { - duplicate = true - break - } - } - - if !duplicate { - channels[j] = c - j++ - } - } - - return channels[0:j], nil -} - -// recvValues is a multiplexing helper function. It reads values from the given -// channel repeatedly, wrapping them up as either a channelRecv or -// channelClosed structure, and forwards them to the multiplex channel. -func recvValues(multiplex chan<- interface{}, channel interface{}) { - c := reflect.ValueOf(channel) - - for { - v, ok := c.Recv() - if !ok { - multiplex <- channelClosed{channel} - return - } - - multiplex <- channelRecv{channel, v.Interface()} - } -} - -type channelClosed struct { - channel interface{} -} - -type channelRecv struct { - channel interface{} - value interface{} -} - -// readyEvents returns the subset of events that are ready. -func readyEvents(events []*Event) ([]*Event, os.Error) { - ready := make([]*Event, len(events)) - - j := 0 - eventsWaiting := false - for _, event := range events { - if event.occurred { - continue - } - - eventsWaiting = true - if event.isReady() { - ready[j] = event - j++ - } - } - - if j == 0 && eventsWaiting { - names := make([]string, len(events)) - for _, event := range events { - if event.occurred { - continue - } - names[j] = event.name - } - - return nil, SetupError("dependency cycle in events. These events are waiting to run but cannot: " + strings.Join(names, ", ")) - } - - return ready[0:j], nil -} diff --git a/src/cmd/fix/testdata/reflect.template.go.in b/src/cmd/fix/testdata/reflect.template.go.in deleted file mode 100644 index 1f5a8128fd..0000000000 --- a/src/cmd/fix/testdata/reflect.template.go.in +++ /dev/null @@ -1,1043 +0,0 @@ -// 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. - -/* - Data-driven templates for generating textual output such as - HTML. - - Templates are executed by applying them to a data structure. - Annotations in the template refer to elements of the data - structure (typically a field of a struct or a key in a map) - to control execution and derive values to be displayed. - The template walks the structure as it executes and the - "cursor" @ represents the value at the current location - in the structure. - - Data items may be values or pointers; the interface hides the - indirection. - - In the following, 'field' is one of several things, according to the data. - - - The name of a field of a struct (result = data.field), - - The value stored in a map under that key (result = data[field]), or - - The result of invoking a niladic single-valued method with that name - (result = data.field()) - - Major constructs ({} are the default delimiters for template actions; - [] are the notation in this comment for optional elements): - - {# comment } - - A one-line comment. - - {.section field} XXX [ {.or} YYY ] {.end} - - Set @ to the value of the field. It may be an explicit @ - to stay at the same point in the data. If the field is nil - or empty, execute YYY; otherwise execute XXX. - - {.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end} - - Like .section, but field must be an array or slice. XXX - is executed for each element. If the array is nil or empty, - YYY is executed instead. If the {.alternates with} marker - is present, ZZZ is executed between iterations of XXX. - - {field} - {field1 field2 ...} - {field|formatter} - {field1 field2...|formatter} - {field|formatter1|formatter2} - - Insert the value of the fields into the output. Each field is - first looked for in the cursor, as in .section and .repeated. - If it is not found, the search continues in outer sections - until the top level is reached. - - If the field value is a pointer, leading asterisks indicate - that the value to be inserted should be evaluated through the - pointer. For example, if x.p is of type *int, {x.p} will - insert the value of the pointer but {*x.p} will insert the - value of the underlying integer. If the value is nil or not a - pointer, asterisks have no effect. - - If a formatter is specified, it must be named in the formatter - map passed to the template set up routines or in the default - set ("html","str","") and is used to process the data for - output. The formatter function has signature - func(wr io.Writer, formatter string, data ...interface{}) - where wr is the destination for output, data holds the field - values at the instantiation, and formatter is its name at - the invocation site. The default formatter just concatenates - the string representations of the fields. - - Multiple formatters separated by the pipeline character | are - executed sequentially, with each formatter receiving the bytes - emitted by the one to its left. - - The delimiter strings get their default value, "{" and "}", from - JSON-template. They may be set to any non-empty, space-free - string using the SetDelims method. Their value can be printed - in the output using {.meta-left} and {.meta-right}. -*/ -package template - -import ( - "bytes" - "container/vector" - "fmt" - "io" - "io/ioutil" - "os" - "reflect" - "strings" - "unicode" - "utf8" -) - -// Errors returned during parsing and execution. Users may extract the information and reformat -// if they desire. -type Error struct { - Line int - Msg string -} - -func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) } - -// Most of the literals are aces. -var lbrace = []byte{'{'} -var rbrace = []byte{'}'} -var space = []byte{' '} -var tab = []byte{'\t'} - -// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors -const ( - tokAlternates = iota - tokComment - tokEnd - tokLiteral - tokOr - tokRepeated - tokSection - tokText - tokVariable -) - -// FormatterMap is the type describing the mapping from formatter -// names to the functions that implement them. -type FormatterMap map[string]func(io.Writer, string, ...interface{}) - -// Built-in formatters. -var builtins = FormatterMap{ - "html": HTMLFormatter, - "str": StringFormatter, - "": StringFormatter, -} - -// The parsed state of a template is a vector of xxxElement structs. -// Sections have line numbers so errors can be reported better during execution. - -// Plain text. -type textElement struct { - text []byte -} - -// A literal such as .meta-left or .meta-right -type literalElement struct { - text []byte -} - -// A variable invocation to be evaluated -type variableElement struct { - linenum int - word []string // The fields in the invocation. - fmts []string // Names of formatters to apply. len(fmts) > 0 -} - -// A .section block, possibly with a .or -type sectionElement struct { - linenum int // of .section itself - field string // cursor field for this block - start int // first element - or int // first element of .or block - end int // one beyond last element -} - -// A .repeated block, possibly with a .or and a .alternates -type repeatedElement struct { - sectionElement // It has the same structure... - altstart int // ... except for alternates - altend int -} - -// Template is the type that represents a template definition. -// It is unchanged after parsing. -type Template struct { - fmap FormatterMap // formatters for variables - // Used during parsing: - ldelim, rdelim []byte // delimiters; default {} - buf []byte // input text to process - p int // position in buf - linenum int // position in input - // Parsed results: - elems *vector.Vector -} - -// Internal state for executing a Template. As we evaluate the struct, -// the data item descends into the fields associated with sections, etc. -// Parent is used to walk upwards to find variables higher in the tree. -type state struct { - parent *state // parent in hierarchy - data reflect.Value // the driver data for this section etc. - wr io.Writer // where to send output - buf [2]bytes.Buffer // alternating buffers used when chaining formatters -} - -func (parent *state) clone(data reflect.Value) *state { - return &state{parent: parent, data: data, wr: parent.wr} -} - -// New creates a new template with the specified formatter map (which -// may be nil) to define auxiliary functions for formatting variables. -func New(fmap FormatterMap) *Template { - t := new(Template) - t.fmap = fmap - t.ldelim = lbrace - t.rdelim = rbrace - t.elems = new(vector.Vector) - return t -} - -// Report error and stop executing. The line number must be provided explicitly. -func (t *Template) execError(st *state, line int, err string, args ...interface{}) { - panic(&Error{line, fmt.Sprintf(err, args...)}) -} - -// Report error, panic to terminate parsing. -// The line number comes from the template state. -func (t *Template) parseError(err string, args ...interface{}) { - panic(&Error{t.linenum, fmt.Sprintf(err, args...)}) -} - -// Is this an exported - upper case - name? -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// -- Lexical analysis - -// Is c a white space character? -func white(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } - -// Safely, does s[n:n+len(t)] == t? -func equal(s []byte, n int, t []byte) bool { - b := s[n:] - if len(t) > len(b) { // not enough space left for a match. - return false - } - for i, c := range t { - if c != b[i] { - return false - } - } - return true -} - -// nextItem returns the next item from the input buffer. If the returned -// item is empty, we are at EOF. The item will be either a -// delimited string or a non-empty string between delimited -// strings. Tokens stop at (but include, if plain text) a newline. -// Action tokens on a line by themselves drop any space on -// either side, up to and including the newline. -func (t *Template) nextItem() []byte { - startOfLine := t.p == 0 || t.buf[t.p-1] == '\n' - start := t.p - var i int - newline := func() { - t.linenum++ - i++ - } - // Leading white space up to but not including newline - for i = start; i < len(t.buf); i++ { - if t.buf[i] == '\n' || !white(t.buf[i]) { - break - } - } - leadingSpace := i > start - // What's left is nothing, newline, delimited string, or plain text - switch { - case i == len(t.buf): - // EOF; nothing to do - case t.buf[i] == '\n': - newline() - case equal(t.buf, i, t.ldelim): - left := i // Start of left delimiter. - right := -1 // Will be (immediately after) right delimiter. - haveText := false // Delimiters contain text. - i += len(t.ldelim) - // Find the end of the action. - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - break - } - if equal(t.buf, i, t.rdelim) { - i += len(t.rdelim) - right = i - break - } - haveText = true - } - if right < 0 { - t.parseError("unmatched opening delimiter") - return nil - } - // Is this a special action (starts with '.' or '#') and the only thing on the line? - if startOfLine && haveText { - firstChar := t.buf[left+len(t.ldelim)] - if firstChar == '.' || firstChar == '#' { - // It's special and the first thing on the line. Is it the last? - for j := right; j < len(t.buf) && white(t.buf[j]); j++ { - if t.buf[j] == '\n' { - // Yes it is. Drop the surrounding space and return the {.foo} - t.linenum++ - t.p = j + 1 - return t.buf[left:right] - } - } - } - } - // No it's not. If there's leading space, return that. - if leadingSpace { - // not trimming space: return leading white space if there is some. - t.p = left - return t.buf[start:left] - } - // Return the word, leave the trailing space. - start = left - break - default: - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - newline() - break - } - if equal(t.buf, i, t.ldelim) { - break - } - } - } - item := t.buf[start:i] - t.p = i - return item -} - -// Turn a byte array into a white-space-split array of strings. -func words(buf []byte) []string { - s := make([]string, 0, 5) - p := 0 // position in buf - // one word per loop - for i := 0; ; i++ { - // skip white space - for ; p < len(buf) && white(buf[p]); p++ { - } - // grab word - start := p - for ; p < len(buf) && !white(buf[p]); p++ { - } - if start == p { // no text left - break - } - s = append(s, string(buf[start:p])) - } - return s -} - -// Analyze an item and return its token type and, if it's an action item, an array of -// its constituent words. -func (t *Template) analyze(item []byte) (tok int, w []string) { - // item is known to be non-empty - if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter - tok = tokText - return - } - if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter - t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this - return - } - if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents - t.parseError("empty directive") - return - } - // Comment - if item[len(t.ldelim)] == '#' { - tok = tokComment - return - } - // Split into words - w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter - if len(w) == 0 { - t.parseError("empty directive") - return - } - if len(w) > 0 && w[0][0] != '.' { - tok = tokVariable - return - } - switch w[0] { - case ".meta-left", ".meta-right", ".space", ".tab": - tok = tokLiteral - return - case ".or": - tok = tokOr - return - case ".end": - tok = tokEnd - return - case ".section": - if len(w) != 2 { - t.parseError("incorrect fields for .section: %s", item) - return - } - tok = tokSection - return - case ".repeated": - if len(w) != 3 || w[1] != "section" { - t.parseError("incorrect fields for .repeated: %s", item) - return - } - tok = tokRepeated - return - case ".alternates": - if len(w) != 2 || w[1] != "with" { - t.parseError("incorrect fields for .alternates: %s", item) - return - } - tok = tokAlternates - return - } - t.parseError("bad directive: %s", item) - return -} - -// formatter returns the Formatter with the given name in the Template, or nil if none exists. -func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) { - if t.fmap != nil { - if fn := t.fmap[name]; fn != nil { - return fn - } - } - return builtins[name] -} - -// -- Parsing - -// Allocate a new variable-evaluation element. -func (t *Template) newVariable(words []string) *variableElement { - // After the final space-separated argument, formatters may be specified separated - // by pipe symbols, for example: {a b c|d|e} - - // Until we learn otherwise, formatters contains a single name: "", the default formatter. - formatters := []string{""} - lastWord := words[len(words)-1] - bar := strings.IndexRune(lastWord, '|') - if bar >= 0 { - words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|") - } - - // We could remember the function address here and avoid the lookup later, - // but it's more dynamic to let the user change the map contents underfoot. - // We do require the name to be present, though. - - // Is it in user-supplied map? - for _, f := range formatters { - if t.formatter(f) == nil { - t.parseError("unknown formatter: %q", f) - } - } - return &variableElement{t.linenum, words, formatters} -} - -// Grab the next item. If it's simple, just append it to the template. -// Otherwise return its details. -func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { - tok, w = t.analyze(item) - done = true // assume for simplicity - switch tok { - case tokComment: - return - case tokText: - t.elems.Push(&textElement{item}) - return - case tokLiteral: - switch w[0] { - case ".meta-left": - t.elems.Push(&literalElement{t.ldelim}) - case ".meta-right": - t.elems.Push(&literalElement{t.rdelim}) - case ".space": - t.elems.Push(&literalElement{space}) - case ".tab": - t.elems.Push(&literalElement{tab}) - default: - t.parseError("internal error: unknown literal: %s", w[0]) - } - return - case tokVariable: - t.elems.Push(t.newVariable(w)) - return - } - return false, tok, w -} - -// parseRepeated and parseSection are mutually recursive - -func (t *Template) parseRepeated(words []string) *repeatedElement { - r := new(repeatedElement) - t.elems.Push(r) - r.linenum = t.linenum - r.field = words[2] - // Scan section, collecting true and false (.or) blocks. - r.start = t.elems.Len() - r.or = -1 - r.altstart = -1 - r.altend = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .repeated section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if r.or >= 0 { - t.parseError("extra .or in .repeated section") - break Loop - } - r.altend = t.elems.Len() - r.or = t.elems.Len() - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - if r.altstart >= 0 { - t.parseError("extra .alternates in .repeated section") - break Loop - } - if r.or >= 0 { - t.parseError(".alternates inside .or block in .repeated section") - break Loop - } - r.altstart = t.elems.Len() - default: - t.parseError("internal error: unknown repeated section item: %s", item) - break Loop - } - } - if r.altend < 0 { - r.altend = t.elems.Len() - } - r.end = t.elems.Len() - return r -} - -func (t *Template) parseSection(words []string) *sectionElement { - s := new(sectionElement) - t.elems.Push(s) - s.linenum = t.linenum - s.field = words[1] - // Scan section, collecting true and false (.or) blocks. - s.start = t.elems.Len() - s.or = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if s.or >= 0 { - t.parseError("extra .or in .section") - break Loop - } - s.or = t.elems.Len() - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - t.parseError(".alternates not in .repeated") - default: - t.parseError("internal error: unknown section item: %s", item) - } - } - s.end = t.elems.Len() - return s -} - -func (t *Template) parse() { - for { - item := t.nextItem() - if len(item) == 0 { - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokOr, tokEnd, tokAlternates: - t.parseError("unexpected %s", w[0]) - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - default: - t.parseError("internal error: bad directive in parse: %s", item) - } - } -} - -// -- Execution - -// Evaluate interfaces and pointers looking for a value that can look up the name, via a -// struct field, method, or map key, and return the result of the lookup. -func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value { - for v != nil { - typ := v.Type() - if n := v.Type().NumMethod(); n > 0 { - for i := 0; i < n; i++ { - m := typ.Method(i) - mtyp := m.Type - if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 { - if !isExported(name) { - t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) - } - return v.Method(i).Call(nil)[0] - } - } - } - switch av := v.(type) { - case *reflect.PtrValue: - v = av.Elem() - case *reflect.InterfaceValue: - v = av.Elem() - case *reflect.StructValue: - if !isExported(name) { - t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) - } - return av.FieldByName(name) - case *reflect.MapValue: - if v := av.Elem(reflect.NewValue(name)); v != nil { - return v - } - return reflect.MakeZero(typ.(*reflect.MapType).Elem()) - default: - return nil - } - } - return v -} - -// indirectPtr returns the item numLevels levels of indirection below the value. -// It is forgiving: if the value is not a pointer, it returns it rather than giving -// an error. If the pointer is nil, it is returned as is. -func indirectPtr(v reflect.Value, numLevels int) reflect.Value { - for i := numLevels; v != nil && i > 0; i++ { - if p, ok := v.(*reflect.PtrValue); ok { - if p.IsNil() { - return v - } - v = p.Elem() - } else { - break - } - } - return v -} - -// Walk v through pointers and interfaces, extracting the elements within. -func indirect(v reflect.Value) reflect.Value { -loop: - for v != nil { - switch av := v.(type) { - case *reflect.PtrValue: - v = av.Elem() - case *reflect.InterfaceValue: - v = av.Elem() - default: - break loop - } - } - return v -} - -// If the data for this template is a struct, find the named variable. -// Names of the form a.b.c are walked down the data tree. -// The special name "@" (the "cursor") denotes the current data. -// The value coming in (st.data) might need indirecting to reach -// a struct while the return value is not indirected - that is, -// it represents the actual named field. Leading stars indicate -// levels of indirection to be applied to the value. -func (t *Template) findVar(st *state, s string) reflect.Value { - data := st.data - flattenedName := strings.TrimLeft(s, "*") - numStars := len(s) - len(flattenedName) - s = flattenedName - if s == "@" { - return indirectPtr(data, numStars) - } - for _, elem := range strings.Split(s, ".") { - // Look up field; data must be a struct or map. - data = t.lookup(st, data, elem) - if data == nil { - return nil - } - } - return indirectPtr(data, numStars) -} - -// Is there no data to look at? -func empty(v reflect.Value) bool { - v = indirect(v) - if v == nil { - return true - } - switch v := v.(type) { - case *reflect.BoolValue: - return v.Get() == false - case *reflect.StringValue: - return v.Get() == "" - case *reflect.StructValue: - return false - case *reflect.MapValue: - return false - case *reflect.ArrayValue: - return v.Len() == 0 - case *reflect.SliceValue: - return v.Len() == 0 - } - return false -} - -// Look up a variable or method, up through the parent if necessary. -func (t *Template) varValue(name string, st *state) reflect.Value { - field := t.findVar(st, name) - if field == nil { - if st.parent == nil { - t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type()) - } - return t.varValue(name, st.parent) - } - return field -} - -func (t *Template) format(wr io.Writer, fmt string, val []interface{}, v *variableElement, st *state) { - fn := t.formatter(fmt) - if fn == nil { - t.execError(st, v.linenum, "missing formatter %s for variable %s", fmt, v.word[0]) - } - fn(wr, fmt, val...) -} - -// Evaluate a variable, looking up through the parent if necessary. -// If it has a formatter attached ({var|formatter}) run that too. -func (t *Template) writeVariable(v *variableElement, st *state) { - // Turn the words of the invocation into values. - val := make([]interface{}, len(v.word)) - for i, word := range v.word { - val[i] = t.varValue(word, st).Interface() - } - - for i, fmt := range v.fmts[:len(v.fmts)-1] { - b := &st.buf[i&1] - b.Reset() - t.format(b, fmt, val, v, st) - val = val[0:1] - val[0] = b.Bytes() - } - t.format(st.wr, v.fmts[len(v.fmts)-1], val, v, st) -} - -// Execute element i. Return next index to execute. -func (t *Template) executeElement(i int, st *state) int { - switch elem := t.elems.At(i).(type) { - case *textElement: - st.wr.Write(elem.text) - return i + 1 - case *literalElement: - st.wr.Write(elem.text) - return i + 1 - case *variableElement: - t.writeVariable(elem, st) - return i + 1 - case *sectionElement: - t.executeSection(elem, st) - return elem.end - case *repeatedElement: - t.executeRepeated(elem, st) - return elem.end - } - e := t.elems.At(i) - t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e) - return 0 -} - -// Execute the template. -func (t *Template) execute(start, end int, st *state) { - for i := start; i < end; { - i = t.executeElement(i, st) - } -} - -// Execute a .section -func (t *Template) executeSection(s *sectionElement, st *state) { - // Find driver data for this section. It must be in the current struct. - field := t.varValue(s.field, st) - if field == nil { - t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, st.data.Type()) - } - st = st.clone(field) - start, end := s.start, s.or - if !empty(field) { - // Execute the normal block. - if end < 0 { - end = s.end - } - } else { - // Execute the .or block. If it's missing, do nothing. - start, end = s.or, s.end - if start < 0 { - return - } - } - for i := start; i < end; { - i = t.executeElement(i, st) - } -} - -// Return the result of calling the Iter method on v, or nil. -func iter(v reflect.Value) *reflect.ChanValue { - for j := 0; j < v.Type().NumMethod(); j++ { - mth := v.Type().Method(j) - fv := v.Method(j) - ft := fv.Type().(*reflect.FuncType) - // TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue. - if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 { - continue - } - ct, ok := ft.Out(0).(*reflect.ChanType) - if !ok || ct.Dir()&reflect.RecvDir == 0 { - continue - } - return fv.Call(nil)[0].(*reflect.ChanValue) - } - return nil -} - -// Execute a .repeated section -func (t *Template) executeRepeated(r *repeatedElement, st *state) { - // Find driver data for this section. It must be in the current struct. - field := t.varValue(r.field, st) - if field == nil { - t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, st.data.Type()) - } - field = indirect(field) - - start, end := r.start, r.or - if end < 0 { - end = r.end - } - if r.altstart >= 0 { - end = r.altstart - } - first := true - - // Code common to all the loops. - loopBody := func(newst *state) { - // .alternates between elements - if !first && r.altstart >= 0 { - for i := r.altstart; i < r.altend; { - i = t.executeElement(i, newst) - } - } - first = false - for i := start; i < end; { - i = t.executeElement(i, newst) - } - } - - if array, ok := field.(reflect.ArrayOrSliceValue); ok { - for j := 0; j < array.Len(); j++ { - loopBody(st.clone(array.Elem(j))) - } - } else if m, ok := field.(*reflect.MapValue); ok { - for _, key := range m.Keys() { - loopBody(st.clone(m.Elem(key))) - } - } else if ch := iter(field); ch != nil { - for { - e, ok := ch.Recv() - if !ok { - break - } - loopBody(st.clone(e)) - } - } else { - t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)", - r.field, field.Type()) - } - - if first { - // Empty. Execute the .or block, once. If it's missing, do nothing. - start, end := r.or, r.end - if start >= 0 { - newst := st.clone(field) - for i := start; i < end; { - i = t.executeElement(i, newst) - } - } - return - } -} - -// A valid delimiter must contain no white space and be non-empty. -func validDelim(d []byte) bool { - if len(d) == 0 { - return false - } - for _, c := range d { - if white(c) { - return false - } - } - return true -} - -// checkError is a deferred function to turn a panic with type *Error into a plain error return. -// Other panics are unexpected and so are re-enabled. -func checkError(error *os.Error) { - if v := recover(); v != nil { - if e, ok := v.(*Error); ok { - *error = e - } else { - // runtime errors should crash - panic(v) - } - } -} - -// -- Public interface - -// Parse initializes a Template by parsing its definition. The string -// s contains the template text. If any errors occur, Parse returns -// the error. -func (t *Template) Parse(s string) (err os.Error) { - if t.elems == nil { - return &Error{1, "template not allocated with New"} - } - if !validDelim(t.ldelim) || !validDelim(t.rdelim) { - return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)} - } - defer checkError(&err) - t.buf = []byte(s) - t.p = 0 - t.linenum = 1 - t.parse() - return nil -} - -// ParseFile is like Parse but reads the template definition from the -// named file. -func (t *Template) ParseFile(filename string) (err os.Error) { - b, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - return t.Parse(string(b)) -} - -// Execute applies a parsed template to the specified data object, -// generating output to wr. -func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) { - // Extract the driver data. - val := reflect.NewValue(data) - defer checkError(&err) - t.p = 0 - t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr}) - return nil -} - -// SetDelims sets the left and right delimiters for operations in the -// template. They are validated during parsing. They could be -// validated here but it's better to keep the routine simple. The -// delimiters are very rarely invalid and Parse has the necessary -// error-handling interface already. -func (t *Template) SetDelims(left, right string) { - t.ldelim = []byte(left) - t.rdelim = []byte(right) -} - -// Parse creates a Template with default parameters (such as {} for -// metacharacters). The string s contains the template text while -// the formatter map fmap, which may be nil, defines auxiliary functions -// for formatting variables. The template is returned. If any errors -// occur, err will be non-nil. -func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) { - t = New(fmap) - err = t.Parse(s) - if err != nil { - t = nil - } - return -} - -// ParseFile is a wrapper function that creates a Template with default -// parameters (such as {} for metacharacters). The filename identifies -// a file containing the template text, while the formatter map fmap, which -// may be nil, defines auxiliary functions for formatting variables. -// The template is returned. If any errors occur, err will be non-nil. -func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) { - b, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - return Parse(string(b), fmap) -} - -// MustParse is like Parse but panics if the template cannot be parsed. -func MustParse(s string, fmap FormatterMap) *Template { - t, err := Parse(s, fmap) - if err != nil { - panic("template.MustParse error: " + err.String()) - } - return t -} - -// MustParseFile is like ParseFile but panics if the file cannot be read -// or the template cannot be parsed. -func MustParseFile(filename string, fmap FormatterMap) *Template { - b, err := ioutil.ReadFile(filename) - if err != nil { - panic("template.MustParseFile error: " + err.String()) - } - return MustParse(string(b), fmap) -} diff --git a/src/cmd/fix/testdata/reflect.template.go.out b/src/cmd/fix/testdata/reflect.template.go.out deleted file mode 100644 index f2f56ef3c2..0000000000 --- a/src/cmd/fix/testdata/reflect.template.go.out +++ /dev/null @@ -1,1044 +0,0 @@ -// 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. - -/* - Data-driven templates for generating textual output such as - HTML. - - Templates are executed by applying them to a data structure. - Annotations in the template refer to elements of the data - structure (typically a field of a struct or a key in a map) - to control execution and derive values to be displayed. - The template walks the structure as it executes and the - "cursor" @ represents the value at the current location - in the structure. - - Data items may be values or pointers; the interface hides the - indirection. - - In the following, 'field' is one of several things, according to the data. - - - The name of a field of a struct (result = data.field), - - The value stored in a map under that key (result = data[field]), or - - The result of invoking a niladic single-valued method with that name - (result = data.field()) - - Major constructs ({} are the default delimiters for template actions; - [] are the notation in this comment for optional elements): - - {# comment } - - A one-line comment. - - {.section field} XXX [ {.or} YYY ] {.end} - - Set @ to the value of the field. It may be an explicit @ - to stay at the same point in the data. If the field is nil - or empty, execute YYY; otherwise execute XXX. - - {.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end} - - Like .section, but field must be an array or slice. XXX - is executed for each element. If the array is nil or empty, - YYY is executed instead. If the {.alternates with} marker - is present, ZZZ is executed between iterations of XXX. - - {field} - {field1 field2 ...} - {field|formatter} - {field1 field2...|formatter} - {field|formatter1|formatter2} - - Insert the value of the fields into the output. Each field is - first looked for in the cursor, as in .section and .repeated. - If it is not found, the search continues in outer sections - until the top level is reached. - - If the field value is a pointer, leading asterisks indicate - that the value to be inserted should be evaluated through the - pointer. For example, if x.p is of type *int, {x.p} will - insert the value of the pointer but {*x.p} will insert the - value of the underlying integer. If the value is nil or not a - pointer, asterisks have no effect. - - If a formatter is specified, it must be named in the formatter - map passed to the template set up routines or in the default - set ("html","str","") and is used to process the data for - output. The formatter function has signature - func(wr io.Writer, formatter string, data ...interface{}) - where wr is the destination for output, data holds the field - values at the instantiation, and formatter is its name at - the invocation site. The default formatter just concatenates - the string representations of the fields. - - Multiple formatters separated by the pipeline character | are - executed sequentially, with each formatter receiving the bytes - emitted by the one to its left. - - The delimiter strings get their default value, "{" and "}", from - JSON-template. They may be set to any non-empty, space-free - string using the SetDelims method. Their value can be printed - in the output using {.meta-left} and {.meta-right}. -*/ -package template - -import ( - "bytes" - "container/vector" - "fmt" - "io" - "io/ioutil" - "os" - "reflect" - "strings" - "unicode" - "utf8" -) - -// Errors returned during parsing and execution. Users may extract the information and reformat -// if they desire. -type Error struct { - Line int - Msg string -} - -func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) } - -// Most of the literals are aces. -var lbrace = []byte{'{'} -var rbrace = []byte{'}'} -var space = []byte{' '} -var tab = []byte{'\t'} - -// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors -const ( - tokAlternates = iota - tokComment - tokEnd - tokLiteral - tokOr - tokRepeated - tokSection - tokText - tokVariable -) - -// FormatterMap is the type describing the mapping from formatter -// names to the functions that implement them. -type FormatterMap map[string]func(io.Writer, string, ...interface{}) - -// Built-in formatters. -var builtins = FormatterMap{ - "html": HTMLFormatter, - "str": StringFormatter, - "": StringFormatter, -} - -// The parsed state of a template is a vector of xxxElement structs. -// Sections have line numbers so errors can be reported better during execution. - -// Plain text. -type textElement struct { - text []byte -} - -// A literal such as .meta-left or .meta-right -type literalElement struct { - text []byte -} - -// A variable invocation to be evaluated -type variableElement struct { - linenum int - word []string // The fields in the invocation. - fmts []string // Names of formatters to apply. len(fmts) > 0 -} - -// A .section block, possibly with a .or -type sectionElement struct { - linenum int // of .section itself - field string // cursor field for this block - start int // first element - or int // first element of .or block - end int // one beyond last element -} - -// A .repeated block, possibly with a .or and a .alternates -type repeatedElement struct { - sectionElement // It has the same structure... - altstart int // ... except for alternates - altend int -} - -// Template is the type that represents a template definition. -// It is unchanged after parsing. -type Template struct { - fmap FormatterMap // formatters for variables - // Used during parsing: - ldelim, rdelim []byte // delimiters; default {} - buf []byte // input text to process - p int // position in buf - linenum int // position in input - // Parsed results: - elems *vector.Vector -} - -// Internal state for executing a Template. As we evaluate the struct, -// the data item descends into the fields associated with sections, etc. -// Parent is used to walk upwards to find variables higher in the tree. -type state struct { - parent *state // parent in hierarchy - data reflect.Value // the driver data for this section etc. - wr io.Writer // where to send output - buf [2]bytes.Buffer // alternating buffers used when chaining formatters -} - -func (parent *state) clone(data reflect.Value) *state { - return &state{parent: parent, data: data, wr: parent.wr} -} - -// New creates a new template with the specified formatter map (which -// may be nil) to define auxiliary functions for formatting variables. -func New(fmap FormatterMap) *Template { - t := new(Template) - t.fmap = fmap - t.ldelim = lbrace - t.rdelim = rbrace - t.elems = new(vector.Vector) - return t -} - -// Report error and stop executing. The line number must be provided explicitly. -func (t *Template) execError(st *state, line int, err string, args ...interface{}) { - panic(&Error{line, fmt.Sprintf(err, args...)}) -} - -// Report error, panic to terminate parsing. -// The line number comes from the template state. -func (t *Template) parseError(err string, args ...interface{}) { - panic(&Error{t.linenum, fmt.Sprintf(err, args...)}) -} - -// Is this an exported - upper case - name? -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// -- Lexical analysis - -// Is c a white space character? -func white(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } - -// Safely, does s[n:n+len(t)] == t? -func equal(s []byte, n int, t []byte) bool { - b := s[n:] - if len(t) > len(b) { // not enough space left for a match. - return false - } - for i, c := range t { - if c != b[i] { - return false - } - } - return true -} - -// nextItem returns the next item from the input buffer. If the returned -// item is empty, we are at EOF. The item will be either a -// delimited string or a non-empty string between delimited -// strings. Tokens stop at (but include, if plain text) a newline. -// Action tokens on a line by themselves drop any space on -// either side, up to and including the newline. -func (t *Template) nextItem() []byte { - startOfLine := t.p == 0 || t.buf[t.p-1] == '\n' - start := t.p - var i int - newline := func() { - t.linenum++ - i++ - } - // Leading white space up to but not including newline - for i = start; i < len(t.buf); i++ { - if t.buf[i] == '\n' || !white(t.buf[i]) { - break - } - } - leadingSpace := i > start - // What's left is nothing, newline, delimited string, or plain text - switch { - case i == len(t.buf): - // EOF; nothing to do - case t.buf[i] == '\n': - newline() - case equal(t.buf, i, t.ldelim): - left := i // Start of left delimiter. - right := -1 // Will be (immediately after) right delimiter. - haveText := false // Delimiters contain text. - i += len(t.ldelim) - // Find the end of the action. - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - break - } - if equal(t.buf, i, t.rdelim) { - i += len(t.rdelim) - right = i - break - } - haveText = true - } - if right < 0 { - t.parseError("unmatched opening delimiter") - return nil - } - // Is this a special action (starts with '.' or '#') and the only thing on the line? - if startOfLine && haveText { - firstChar := t.buf[left+len(t.ldelim)] - if firstChar == '.' || firstChar == '#' { - // It's special and the first thing on the line. Is it the last? - for j := right; j < len(t.buf) && white(t.buf[j]); j++ { - if t.buf[j] == '\n' { - // Yes it is. Drop the surrounding space and return the {.foo} - t.linenum++ - t.p = j + 1 - return t.buf[left:right] - } - } - } - } - // No it's not. If there's leading space, return that. - if leadingSpace { - // not trimming space: return leading white space if there is some. - t.p = left - return t.buf[start:left] - } - // Return the word, leave the trailing space. - start = left - break - default: - for ; i < len(t.buf); i++ { - if t.buf[i] == '\n' { - newline() - break - } - if equal(t.buf, i, t.ldelim) { - break - } - } - } - item := t.buf[start:i] - t.p = i - return item -} - -// Turn a byte array into a white-space-split array of strings. -func words(buf []byte) []string { - s := make([]string, 0, 5) - p := 0 // position in buf - // one word per loop - for i := 0; ; i++ { - // skip white space - for ; p < len(buf) && white(buf[p]); p++ { - } - // grab word - start := p - for ; p < len(buf) && !white(buf[p]); p++ { - } - if start == p { // no text left - break - } - s = append(s, string(buf[start:p])) - } - return s -} - -// Analyze an item and return its token type and, if it's an action item, an array of -// its constituent words. -func (t *Template) analyze(item []byte) (tok int, w []string) { - // item is known to be non-empty - if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter - tok = tokText - return - } - if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter - t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this - return - } - if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents - t.parseError("empty directive") - return - } - // Comment - if item[len(t.ldelim)] == '#' { - tok = tokComment - return - } - // Split into words - w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter - if len(w) == 0 { - t.parseError("empty directive") - return - } - if len(w) > 0 && w[0][0] != '.' { - tok = tokVariable - return - } - switch w[0] { - case ".meta-left", ".meta-right", ".space", ".tab": - tok = tokLiteral - return - case ".or": - tok = tokOr - return - case ".end": - tok = tokEnd - return - case ".section": - if len(w) != 2 { - t.parseError("incorrect fields for .section: %s", item) - return - } - tok = tokSection - return - case ".repeated": - if len(w) != 3 || w[1] != "section" { - t.parseError("incorrect fields for .repeated: %s", item) - return - } - tok = tokRepeated - return - case ".alternates": - if len(w) != 2 || w[1] != "with" { - t.parseError("incorrect fields for .alternates: %s", item) - return - } - tok = tokAlternates - return - } - t.parseError("bad directive: %s", item) - return -} - -// formatter returns the Formatter with the given name in the Template, or nil if none exists. -func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) { - if t.fmap != nil { - if fn := t.fmap[name]; fn != nil { - return fn - } - } - return builtins[name] -} - -// -- Parsing - -// Allocate a new variable-evaluation element. -func (t *Template) newVariable(words []string) *variableElement { - // After the final space-separated argument, formatters may be specified separated - // by pipe symbols, for example: {a b c|d|e} - - // Until we learn otherwise, formatters contains a single name: "", the default formatter. - formatters := []string{""} - lastWord := words[len(words)-1] - bar := strings.IndexRune(lastWord, '|') - if bar >= 0 { - words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|") - } - - // We could remember the function address here and avoid the lookup later, - // but it's more dynamic to let the user change the map contents underfoot. - // We do require the name to be present, though. - - // Is it in user-supplied map? - for _, f := range formatters { - if t.formatter(f) == nil { - t.parseError("unknown formatter: %q", f) - } - } - return &variableElement{t.linenum, words, formatters} -} - -// Grab the next item. If it's simple, just append it to the template. -// Otherwise return its details. -func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { - tok, w = t.analyze(item) - done = true // assume for simplicity - switch tok { - case tokComment: - return - case tokText: - t.elems.Push(&textElement{item}) - return - case tokLiteral: - switch w[0] { - case ".meta-left": - t.elems.Push(&literalElement{t.ldelim}) - case ".meta-right": - t.elems.Push(&literalElement{t.rdelim}) - case ".space": - t.elems.Push(&literalElement{space}) - case ".tab": - t.elems.Push(&literalElement{tab}) - default: - t.parseError("internal error: unknown literal: %s", w[0]) - } - return - case tokVariable: - t.elems.Push(t.newVariable(w)) - return - } - return false, tok, w -} - -// parseRepeated and parseSection are mutually recursive - -func (t *Template) parseRepeated(words []string) *repeatedElement { - r := new(repeatedElement) - t.elems.Push(r) - r.linenum = t.linenum - r.field = words[2] - // Scan section, collecting true and false (.or) blocks. - r.start = t.elems.Len() - r.or = -1 - r.altstart = -1 - r.altend = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .repeated section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if r.or >= 0 { - t.parseError("extra .or in .repeated section") - break Loop - } - r.altend = t.elems.Len() - r.or = t.elems.Len() - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - if r.altstart >= 0 { - t.parseError("extra .alternates in .repeated section") - break Loop - } - if r.or >= 0 { - t.parseError(".alternates inside .or block in .repeated section") - break Loop - } - r.altstart = t.elems.Len() - default: - t.parseError("internal error: unknown repeated section item: %s", item) - break Loop - } - } - if r.altend < 0 { - r.altend = t.elems.Len() - } - r.end = t.elems.Len() - return r -} - -func (t *Template) parseSection(words []string) *sectionElement { - s := new(sectionElement) - t.elems.Push(s) - s.linenum = t.linenum - s.field = words[1] - // Scan section, collecting true and false (.or) blocks. - s.start = t.elems.Len() - s.or = -1 -Loop: - for { - item := t.nextItem() - if len(item) == 0 { - t.parseError("missing .end for .section") - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokEnd: - break Loop - case tokOr: - if s.or >= 0 { - t.parseError("extra .or in .section") - break Loop - } - s.or = t.elems.Len() - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - case tokAlternates: - t.parseError(".alternates not in .repeated") - default: - t.parseError("internal error: unknown section item: %s", item) - } - } - s.end = t.elems.Len() - return s -} - -func (t *Template) parse() { - for { - item := t.nextItem() - if len(item) == 0 { - break - } - done, tok, w := t.parseSimple(item) - if done { - continue - } - switch tok { - case tokOr, tokEnd, tokAlternates: - t.parseError("unexpected %s", w[0]) - case tokSection: - t.parseSection(w) - case tokRepeated: - t.parseRepeated(w) - default: - t.parseError("internal error: bad directive in parse: %s", item) - } - } -} - -// -- Execution - -// Evaluate interfaces and pointers looking for a value that can look up the name, via a -// struct field, method, or map key, and return the result of the lookup. -func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value { - for v.IsValid() { - typ := v.Type() - if n := v.Type().NumMethod(); n > 0 { - for i := 0; i < n; i++ { - m := typ.Method(i) - mtyp := m.Type - if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 { - if !isExported(name) { - t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) - } - return v.Method(i).Call(nil)[0] - } - } - } - switch av := v; av.Kind() { - case reflect.Ptr: - v = av.Elem() - case reflect.Interface: - v = av.Elem() - case reflect.Struct: - if !isExported(name) { - t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) - } - return av.FieldByName(name) - case reflect.Map: - if v := av.MapIndex(reflect.ValueOf(name)); v.IsValid() { - return v - } - return reflect.Zero(typ.Elem()) - default: - return reflect.Value{} - } - } - return v -} - -// indirectPtr returns the item numLevels levels of indirection below the value. -// It is forgiving: if the value is not a pointer, it returns it rather than giving -// an error. If the pointer is nil, it is returned as is. -func indirectPtr(v reflect.Value, numLevels int) reflect.Value { - for i := numLevels; v.IsValid() && i > 0; i++ { - if p := v; p.Kind() == reflect.Ptr { - if p.IsNil() { - return v - } - v = p.Elem() - } else { - break - } - } - return v -} - -// Walk v through pointers and interfaces, extracting the elements within. -func indirect(v reflect.Value) reflect.Value { -loop: - for v.IsValid() { - switch av := v; av.Kind() { - case reflect.Ptr: - v = av.Elem() - case reflect.Interface: - v = av.Elem() - default: - break loop - } - } - return v -} - -// If the data for this template is a struct, find the named variable. -// Names of the form a.b.c are walked down the data tree. -// The special name "@" (the "cursor") denotes the current data. -// The value coming in (st.data) might need indirecting to reach -// a struct while the return value is not indirected - that is, -// it represents the actual named field. Leading stars indicate -// levels of indirection to be applied to the value. -func (t *Template) findVar(st *state, s string) reflect.Value { - data := st.data - flattenedName := strings.TrimLeft(s, "*") - numStars := len(s) - len(flattenedName) - s = flattenedName - if s == "@" { - return indirectPtr(data, numStars) - } - for _, elem := range strings.Split(s, ".") { - // Look up field; data must be a struct or map. - data = t.lookup(st, data, elem) - if !data.IsValid() { - return reflect.Value{} - } - } - return indirectPtr(data, numStars) -} - -// Is there no data to look at? -func empty(v reflect.Value) bool { - v = indirect(v) - if !v.IsValid() { - return true - } - switch v.Kind() { - case reflect.Bool: - return v.Bool() == false - case reflect.String: - return v.String() == "" - case reflect.Struct: - return false - case reflect.Map: - return false - case reflect.Array: - return v.Len() == 0 - case reflect.Slice: - return v.Len() == 0 - } - return false -} - -// Look up a variable or method, up through the parent if necessary. -func (t *Template) varValue(name string, st *state) reflect.Value { - field := t.findVar(st, name) - if !field.IsValid() { - if st.parent == nil { - t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type()) - } - return t.varValue(name, st.parent) - } - return field -} - -func (t *Template) format(wr io.Writer, fmt string, val []interface{}, v *variableElement, st *state) { - fn := t.formatter(fmt) - if fn == nil { - t.execError(st, v.linenum, "missing formatter %s for variable %s", fmt, v.word[0]) - } - fn(wr, fmt, val...) -} - -// Evaluate a variable, looking up through the parent if necessary. -// If it has a formatter attached ({var|formatter}) run that too. -func (t *Template) writeVariable(v *variableElement, st *state) { - // Turn the words of the invocation into values. - val := make([]interface{}, len(v.word)) - for i, word := range v.word { - val[i] = t.varValue(word, st).Interface() - } - - for i, fmt := range v.fmts[:len(v.fmts)-1] { - b := &st.buf[i&1] - b.Reset() - t.format(b, fmt, val, v, st) - val = val[0:1] - val[0] = b.Bytes() - } - t.format(st.wr, v.fmts[len(v.fmts)-1], val, v, st) -} - -// Execute element i. Return next index to execute. -func (t *Template) executeElement(i int, st *state) int { - switch elem := t.elems.At(i).(type) { - case *textElement: - st.wr.Write(elem.text) - return i + 1 - case *literalElement: - st.wr.Write(elem.text) - return i + 1 - case *variableElement: - t.writeVariable(elem, st) - return i + 1 - case *sectionElement: - t.executeSection(elem, st) - return elem.end - case *repeatedElement: - t.executeRepeated(elem, st) - return elem.end - } - e := t.elems.At(i) - t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.ValueOf(e).Interface(), e) - return 0 -} - -// Execute the template. -func (t *Template) execute(start, end int, st *state) { - for i := start; i < end; { - i = t.executeElement(i, st) - } -} - -// Execute a .section -func (t *Template) executeSection(s *sectionElement, st *state) { - // Find driver data for this section. It must be in the current struct. - field := t.varValue(s.field, st) - if !field.IsValid() { - t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, st.data.Type()) - } - st = st.clone(field) - start, end := s.start, s.or - if !empty(field) { - // Execute the normal block. - if end < 0 { - end = s.end - } - } else { - // Execute the .or block. If it's missing, do nothing. - start, end = s.or, s.end - if start < 0 { - return - } - } - for i := start; i < end; { - i = t.executeElement(i, st) - } -} - -// Return the result of calling the Iter method on v, or nil. -func iter(v reflect.Value) reflect.Value { - for j := 0; j < v.Type().NumMethod(); j++ { - mth := v.Type().Method(j) - fv := v.Method(j) - ft := fv.Type() - // TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue. - if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 { - continue - } - ct := ft.Out(0) - if ct.Kind() != reflect.Chan || - ct.ChanDir()&reflect.RecvDir == 0 { - continue - } - return fv.Call(nil)[0] - } - return reflect.Value{} -} - -// Execute a .repeated section -func (t *Template) executeRepeated(r *repeatedElement, st *state) { - // Find driver data for this section. It must be in the current struct. - field := t.varValue(r.field, st) - if !field.IsValid() { - t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, st.data.Type()) - } - field = indirect(field) - - start, end := r.start, r.or - if end < 0 { - end = r.end - } - if r.altstart >= 0 { - end = r.altstart - } - first := true - - // Code common to all the loops. - loopBody := func(newst *state) { - // .alternates between elements - if !first && r.altstart >= 0 { - for i := r.altstart; i < r.altend; { - i = t.executeElement(i, newst) - } - } - first = false - for i := start; i < end; { - i = t.executeElement(i, newst) - } - } - - if array := field; array.Kind() == reflect.Array || array.Kind() == reflect.Slice { - for j := 0; j < array.Len(); j++ { - loopBody(st.clone(array.Index(j))) - } - } else if m := field; m.Kind() == reflect.Map { - for _, key := range m.MapKeys() { - loopBody(st.clone(m.MapIndex(key))) - } - } else if ch := iter(field); ch.IsValid() { - for { - e, ok := ch.Recv() - if !ok { - break - } - loopBody(st.clone(e)) - } - } else { - t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)", - r.field, field.Type()) - } - - if first { - // Empty. Execute the .or block, once. If it's missing, do nothing. - start, end := r.or, r.end - if start >= 0 { - newst := st.clone(field) - for i := start; i < end; { - i = t.executeElement(i, newst) - } - } - return - } -} - -// A valid delimiter must contain no white space and be non-empty. -func validDelim(d []byte) bool { - if len(d) == 0 { - return false - } - for _, c := range d { - if white(c) { - return false - } - } - return true -} - -// checkError is a deferred function to turn a panic with type *Error into a plain error return. -// Other panics are unexpected and so are re-enabled. -func checkError(error *os.Error) { - if v := recover(); v != nil { - if e, ok := v.(*Error); ok { - *error = e - } else { - // runtime errors should crash - panic(v) - } - } -} - -// -- Public interface - -// Parse initializes a Template by parsing its definition. The string -// s contains the template text. If any errors occur, Parse returns -// the error. -func (t *Template) Parse(s string) (err os.Error) { - if t.elems == nil { - return &Error{1, "template not allocated with New"} - } - if !validDelim(t.ldelim) || !validDelim(t.rdelim) { - return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)} - } - defer checkError(&err) - t.buf = []byte(s) - t.p = 0 - t.linenum = 1 - t.parse() - return nil -} - -// ParseFile is like Parse but reads the template definition from the -// named file. -func (t *Template) ParseFile(filename string) (err os.Error) { - b, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - return t.Parse(string(b)) -} - -// Execute applies a parsed template to the specified data object, -// generating output to wr. -func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) { - // Extract the driver data. - val := reflect.ValueOf(data) - defer checkError(&err) - t.p = 0 - t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr}) - return nil -} - -// SetDelims sets the left and right delimiters for operations in the -// template. They are validated during parsing. They could be -// validated here but it's better to keep the routine simple. The -// delimiters are very rarely invalid and Parse has the necessary -// error-handling interface already. -func (t *Template) SetDelims(left, right string) { - t.ldelim = []byte(left) - t.rdelim = []byte(right) -} - -// Parse creates a Template with default parameters (such as {} for -// metacharacters). The string s contains the template text while -// the formatter map fmap, which may be nil, defines auxiliary functions -// for formatting variables. The template is returned. If any errors -// occur, err will be non-nil. -func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) { - t = New(fmap) - err = t.Parse(s) - if err != nil { - t = nil - } - return -} - -// ParseFile is a wrapper function that creates a Template with default -// parameters (such as {} for metacharacters). The filename identifies -// a file containing the template text, while the formatter map fmap, which -// may be nil, defines auxiliary functions for formatting variables. -// The template is returned. If any errors occur, err will be non-nil. -func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) { - b, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - return Parse(string(b), fmap) -} - -// MustParse is like Parse but panics if the template cannot be parsed. -func MustParse(s string, fmap FormatterMap) *Template { - t, err := Parse(s, fmap) - if err != nil { - panic("template.MustParse error: " + err.String()) - } - return t -} - -// MustParseFile is like ParseFile but panics if the file cannot be read -// or the template cannot be parsed. -func MustParseFile(filename string, fmap FormatterMap) *Template { - b, err := ioutil.ReadFile(filename) - if err != nil { - panic("template.MustParseFile error: " + err.String()) - } - return MustParse(string(b), fmap) -} diff --git a/src/cmd/fix/testdata/reflect.type.go.in b/src/cmd/fix/testdata/reflect.type.go.in deleted file mode 100644 index 34963bef92..0000000000 --- a/src/cmd/fix/testdata/reflect.type.go.in +++ /dev/null @@ -1,790 +0,0 @@ -// 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. - -package gob - -import ( - "fmt" - "os" - "reflect" - "sync" - "unicode" - "utf8" -) - -// userTypeInfo stores the information associated with a type the user has handed -// to the package. It's computed once and stored in a map keyed by reflection -// type. -type userTypeInfo struct { - user reflect.Type // the type the user handed us - base reflect.Type // the base type after all indirections - indir int // number of indirections to reach the base type - isGobEncoder bool // does the type implement GobEncoder? - isGobDecoder bool // does the type implement GobDecoder? - encIndir int8 // number of indirections to reach the receiver type; may be negative - decIndir int8 // number of indirections to reach the receiver type; may be negative -} - -var ( - // Protected by an RWMutex because we read it a lot and write - // it only when we see a new type, typically when compiling. - userTypeLock sync.RWMutex - userTypeCache = make(map[reflect.Type]*userTypeInfo) -) - -// validType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, err will be non-nil. To be used when the error handler -// is not set up. -func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) { - userTypeLock.RLock() - ut = userTypeCache[rt] - userTypeLock.RUnlock() - if ut != nil { - return - } - // Now set the value under the write lock. - userTypeLock.Lock() - defer userTypeLock.Unlock() - if ut = userTypeCache[rt]; ut != nil { - // Lost the race; not a problem. - return - } - ut = new(userTypeInfo) - ut.base = rt - ut.user = rt - // A type that is just a cycle of pointers (such as type T *T) cannot - // be represented in gobs, which need some concrete data. We use a - // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, - // pp 539-540. As we step through indirections, run another type at - // half speed. If they meet up, there's a cycle. - slowpoke := ut.base // walks half as fast as ut.base - for { - pt, ok := ut.base.(*reflect.PtrType) - if !ok { - break - } - ut.base = pt.Elem() - if ut.base == slowpoke { // ut.base lapped slowpoke - // recursive pointer type. - return nil, os.NewError("can't represent recursive pointer type " + ut.base.String()) - } - if ut.indir%2 == 0 { - slowpoke = slowpoke.(*reflect.PtrType).Elem() - } - ut.indir++ - } - ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderCheck) - ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderCheck) - userTypeCache[rt] = ut - return -} - -const ( - gobEncodeMethodName = "GobEncode" - gobDecodeMethodName = "GobDecode" -) - -// implements returns whether the type implements the interface, as encoded -// in the check function. -func implements(typ reflect.Type, check func(typ reflect.Type) bool) bool { - if typ.NumMethod() == 0 { // avoid allocations etc. unless there's some chance - return false - } - return check(typ) -} - -// gobEncoderCheck makes the type assertion a boolean function. -func gobEncoderCheck(typ reflect.Type) bool { - _, ok := reflect.MakeZero(typ).Interface().(GobEncoder) - return ok -} - -// gobDecoderCheck makes the type assertion a boolean function. -func gobDecoderCheck(typ reflect.Type) bool { - _, ok := reflect.MakeZero(typ).Interface().(GobDecoder) - return ok -} - -// implementsInterface reports whether the type implements the -// interface. (The actual check is done through the provided function.) -// It also returns the number of indirections required to get to the -// implementation. -func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (success bool, indir int8) { - if typ == nil { - return - } - rt := typ - // The type might be a pointer and we need to keep - // dereferencing to the base type until we find an implementation. - for { - if implements(rt, check) { - return true, indir - } - if p, ok := rt.(*reflect.PtrType); ok { - indir++ - if indir > 100 { // insane number of indirections - return false, 0 - } - rt = p.Elem() - continue - } - break - } - // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. - if _, ok := typ.(*reflect.PtrType); !ok { - // Not a pointer, but does the pointer work? - if implements(reflect.PtrTo(typ), check) { - return true, -1 - } - } - return false, 0 -} - -// userType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, it calls error. -func userType(rt reflect.Type) *userTypeInfo { - ut, err := validUserType(rt) - if err != nil { - error(err) - } - return ut -} - -// A typeId represents a gob Type as an integer that can be passed on the wire. -// Internally, typeIds are used as keys to a map to recover the underlying type info. -type typeId int32 - -var nextId typeId // incremented for each new type we build -var typeLock sync.Mutex // set while building a type -const firstUserId = 64 // lowest id number granted to user - -type gobType interface { - id() typeId - setId(id typeId) - name() string - string() string // not public; only for debugging - safeString(seen map[typeId]bool) string -} - -var types = make(map[reflect.Type]gobType) -var idToType = make(map[typeId]gobType) -var builtinIdToType map[typeId]gobType // set in init() after builtins are established - -func setTypeId(typ gobType) { - nextId++ - typ.setId(nextId) - idToType[nextId] = typ -} - -func (t typeId) gobType() gobType { - if t == 0 { - return nil - } - return idToType[t] -} - -// string returns the string representation of the type associated with the typeId. -func (t typeId) string() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().string() -} - -// Name returns the name of the type associated with the typeId. -func (t typeId) name() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().name() -} - -// Common elements of all types. -type CommonType struct { - Name string - Id typeId -} - -func (t *CommonType) id() typeId { return t.Id } - -func (t *CommonType) setId(id typeId) { t.Id = id } - -func (t *CommonType) string() string { return t.Name } - -func (t *CommonType) safeString(seen map[typeId]bool) string { - return t.Name -} - -func (t *CommonType) name() string { return t.Name } - -// Create and check predefined types -// The string for tBytes is "bytes" not "[]byte" to signify its specialness. - -var ( - // Primordial types, needed during initialization. - // Always passed as pointers so the interface{} type - // goes through without losing its interfaceness. - tBool = bootstrapType("bool", (*bool)(nil), 1) - tInt = bootstrapType("int", (*int)(nil), 2) - tUint = bootstrapType("uint", (*uint)(nil), 3) - tFloat = bootstrapType("float", (*float64)(nil), 4) - tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) - tString = bootstrapType("string", (*string)(nil), 6) - tComplex = bootstrapType("complex", (*complex128)(nil), 7) - tInterface = bootstrapType("interface", (*interface{})(nil), 8) - // Reserve some Ids for compatible expansion - tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) - tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) - tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11) - tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12) - tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13) - tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14) - tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15) -) - -// Predefined because it's needed by the Decoder -var tWireType = mustGetTypeInfo(reflect.Typeof(wireType{})).id -var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) - -func init() { - // Some magic numbers to make sure there are no surprises. - checkId(16, tWireType) - checkId(17, mustGetTypeInfo(reflect.Typeof(arrayType{})).id) - checkId(18, mustGetTypeInfo(reflect.Typeof(CommonType{})).id) - checkId(19, mustGetTypeInfo(reflect.Typeof(sliceType{})).id) - checkId(20, mustGetTypeInfo(reflect.Typeof(structType{})).id) - checkId(21, mustGetTypeInfo(reflect.Typeof(fieldType{})).id) - checkId(23, mustGetTypeInfo(reflect.Typeof(mapType{})).id) - - builtinIdToType = make(map[typeId]gobType) - for k, v := range idToType { - builtinIdToType[k] = v - } - - // Move the id space upwards to allow for growth in the predefined world - // without breaking existing files. - if nextId > firstUserId { - panic(fmt.Sprintln("nextId too large:", nextId)) - } - nextId = firstUserId - registerBasics() - wireTypeUserInfo = userType(reflect.Typeof((*wireType)(nil))) -} - -// Array type -type arrayType struct { - CommonType - Elem typeId - Len int -} - -func newArrayType(name string) *arrayType { - a := &arrayType{CommonType{Name: name}, 0, 0} - return a -} - -func (a *arrayType) init(elem gobType, len int) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(a) - a.Elem = elem.id() - a.Len = len -} - -func (a *arrayType) safeString(seen map[typeId]bool) string { - if seen[a.Id] { - return a.Name - } - seen[a.Id] = true - return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) -} - -func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } - -// GobEncoder type (something that implements the GobEncoder interface) -type gobEncoderType struct { - CommonType -} - -func newGobEncoderType(name string) *gobEncoderType { - g := &gobEncoderType{CommonType{Name: name}} - setTypeId(g) - return g -} - -func (g *gobEncoderType) safeString(seen map[typeId]bool) string { - return g.Name -} - -func (g *gobEncoderType) string() string { return g.Name } - -// Map type -type mapType struct { - CommonType - Key typeId - Elem typeId -} - -func newMapType(name string) *mapType { - m := &mapType{CommonType{Name: name}, 0, 0} - return m -} - -func (m *mapType) init(key, elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(m) - m.Key = key.id() - m.Elem = elem.id() -} - -func (m *mapType) safeString(seen map[typeId]bool) string { - if seen[m.Id] { - return m.Name - } - seen[m.Id] = true - key := m.Key.gobType().safeString(seen) - elem := m.Elem.gobType().safeString(seen) - return fmt.Sprintf("map[%s]%s", key, elem) -} - -func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } - -// Slice type -type sliceType struct { - CommonType - Elem typeId -} - -func newSliceType(name string) *sliceType { - s := &sliceType{CommonType{Name: name}, 0} - return s -} - -func (s *sliceType) init(elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(s) - s.Elem = elem.id() -} - -func (s *sliceType) safeString(seen map[typeId]bool) string { - if seen[s.Id] { - return s.Name - } - seen[s.Id] = true - return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) -} - -func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } - -// Struct type -type fieldType struct { - Name string - Id typeId -} - -type structType struct { - CommonType - Field []*fieldType -} - -func (s *structType) safeString(seen map[typeId]bool) string { - if s == nil { - return "<nil>" - } - if _, ok := seen[s.Id]; ok { - return s.Name - } - seen[s.Id] = true - str := s.Name + " = struct { " - for _, f := range s.Field { - str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) - } - str += "}" - return str -} - -func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } - -func newStructType(name string) *structType { - s := &structType{CommonType{Name: name}, nil} - // For historical reasons we set the id here rather than init. - // See the comment in newTypeObject for details. - setTypeId(s) - return s -} - -// newTypeObject allocates a gobType for the reflection type rt. -// Unless ut represents a GobEncoder, rt should be the base type -// of ut. -// This is only called from the encoding side. The decoding side -// works through typeIds and userTypeInfos alone. -func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) { - // Does this type implement GobEncoder? - if ut.isGobEncoder { - return newGobEncoderType(name), nil - } - var err os.Error - var type0, type1 gobType - defer func() { - if err != nil { - types[rt] = nil, false - } - }() - // Install the top-level type before the subtypes (e.g. struct before - // fields) so recursive types can be constructed safely. - switch t := rt.(type) { - // All basic types are easy: they are predefined. - case *reflect.BoolType: - return tBool.gobType(), nil - - case *reflect.IntType: - return tInt.gobType(), nil - - case *reflect.UintType: - return tUint.gobType(), nil - - case *reflect.FloatType: - return tFloat.gobType(), nil - - case *reflect.ComplexType: - return tComplex.gobType(), nil - - case *reflect.StringType: - return tString.gobType(), nil - - case *reflect.InterfaceType: - return tInterface.gobType(), nil - - case *reflect.ArrayType: - at := newArrayType(name) - types[rt] = at - type0, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - // Historical aside: - // For arrays, maps, and slices, we set the type id after the elements - // are constructed. This is to retain the order of type id allocation after - // a fix made to handle recursive types, which changed the order in - // which types are built. Delaying the setting in this way preserves - // type ids while allowing recursive types to be described. Structs, - // done below, were already handling recursion correctly so they - // assign the top-level id before those of the field. - at.init(type0, t.Len()) - return at, nil - - case *reflect.MapType: - mt := newMapType(name) - types[rt] = mt - type0, err = getBaseType("", t.Key()) - if err != nil { - return nil, err - } - type1, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - mt.init(type0, type1) - return mt, nil - - case *reflect.SliceType: - // []byte == []uint8 is a special case - if t.Elem().Kind() == reflect.Uint8 { - return tBytes.gobType(), nil - } - st := newSliceType(name) - types[rt] = st - type0, err = getBaseType(t.Elem().Name(), t.Elem()) - if err != nil { - return nil, err - } - st.init(type0) - return st, nil - - case *reflect.StructType: - st := newStructType(name) - types[rt] = st - idToType[st.id()] = st - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if !isExported(f.Name) { - continue - } - typ := userType(f.Type).base - tname := typ.Name() - if tname == "" { - t := userType(f.Type).base - tname = t.String() - } - gt, err := getBaseType(tname, f.Type) - if err != nil { - return nil, err - } - st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) - } - return st, nil - - default: - return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String()) - } - return nil, nil -} - -// isExported reports whether this is an exported - upper case - name. -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// getBaseType returns the Gob type describing the given reflect.Type's base type. -// typeLock must be held. -func getBaseType(name string, rt reflect.Type) (gobType, os.Error) { - ut := userType(rt) - return getType(name, ut, ut.base) -} - -// getType returns the Gob type describing the given reflect.Type. -// Should be called only when handling GobEncoders/Decoders, -// which may be pointers. All other types are handled through the -// base type, never a pointer. -// typeLock must be held. -func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) { - typ, present := types[rt] - if present { - return typ, nil - } - typ, err := newTypeObject(name, ut, rt) - if err == nil { - types[rt] = typ - } - return typ, err -} - -func checkId(want, got typeId) { - if want != got { - fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) - panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) - } -} - -// used for building the basic types; called only from init(). the incoming -// interface always refers to a pointer. -func bootstrapType(name string, e interface{}, expect typeId) typeId { - rt := reflect.Typeof(e).(*reflect.PtrType).Elem() - _, present := types[rt] - if present { - panic("bootstrap type already present: " + name + ", " + rt.String()) - } - typ := &CommonType{Name: name} - types[rt] = typ - setTypeId(typ) - checkId(expect, nextId) - userType(rt) // might as well cache it now - return nextId -} - -// Representation of the information we send and receive about this type. -// Each value we send is preceded by its type definition: an encoded int. -// However, the very first time we send the value, we first send the pair -// (-id, wireType). -// For bootstrapping purposes, we assume that the recipient knows how -// to decode a wireType; it is exactly the wireType struct here, interpreted -// using the gob rules for sending a structure, except that we assume the -// ids for wireType and structType etc. are known. The relevant pieces -// are built in encode.go's init() function. -// To maintain binary compatibility, if you extend this type, always put -// the new fields last. -type wireType struct { - ArrayT *arrayType - SliceT *sliceType - StructT *structType - MapT *mapType - GobEncoderT *gobEncoderType -} - -func (w *wireType) string() string { - const unknown = "unknown type" - if w == nil { - return unknown - } - switch { - case w.ArrayT != nil: - return w.ArrayT.Name - case w.SliceT != nil: - return w.SliceT.Name - case w.StructT != nil: - return w.StructT.Name - case w.MapT != nil: - return w.MapT.Name - case w.GobEncoderT != nil: - return w.GobEncoderT.Name - } - return unknown -} - -type typeInfo struct { - id typeId - encoder *encEngine - wire *wireType -} - -var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock - -// typeLock must be held. -func getTypeInfo(ut *userTypeInfo) (*typeInfo, os.Error) { - rt := ut.base - if ut.isGobEncoder { - // We want the user type, not the base type. - rt = ut.user - } - info, ok := typeInfoMap[rt] - if ok { - return info, nil - } - info = new(typeInfo) - gt, err := getBaseType(rt.Name(), rt) - if err != nil { - return nil, err - } - info.id = gt.id() - - if ut.isGobEncoder { - userType, err := getType(rt.Name(), ut, rt) - if err != nil { - return nil, err - } - info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)} - typeInfoMap[ut.user] = info - return info, nil - } - - t := info.id.gobType() - switch typ := rt.(type) { - case *reflect.ArrayType: - info.wire = &wireType{ArrayT: t.(*arrayType)} - case *reflect.MapType: - info.wire = &wireType{MapT: t.(*mapType)} - case *reflect.SliceType: - // []byte == []uint8 is a special case handled separately - if typ.Elem().Kind() != reflect.Uint8 { - info.wire = &wireType{SliceT: t.(*sliceType)} - } - case *reflect.StructType: - info.wire = &wireType{StructT: t.(*structType)} - } - typeInfoMap[rt] = info - return info, nil -} - -// Called only when a panic is acceptable and unexpected. -func mustGetTypeInfo(rt reflect.Type) *typeInfo { - t, err := getTypeInfo(userType(rt)) - if err != nil { - panic("getTypeInfo: " + err.String()) - } - return t -} - -// GobEncoder is the interface describing data that provides its own -// representation for encoding values for transmission to a GobDecoder. -// A type that implements GobEncoder and GobDecoder has complete -// control over the representation of its data and may therefore -// contain things such as private fields, channels, and functions, -// which are not usually transmissable in gob streams. -// -// Note: Since gobs can be stored permanently, It is good design -// to guarantee the encoding used by a GobEncoder is stable as the -// software evolves. For instance, it might make sense for GobEncode -// to include a version number in the encoding. -type GobEncoder interface { - // GobEncode returns a byte slice representing the encoding of the - // receiver for transmission to a GobDecoder, usually of the same - // concrete type. - GobEncode() ([]byte, os.Error) -} - -// GobDecoder is the interface describing data that provides its own -// routine for decoding transmitted values sent by a GobEncoder. -type GobDecoder interface { - // GobDecode overwrites the receiver, which must be a pointer, - // with the value represented by the byte slice, which was written - // by GobEncode, usually for the same concrete type. - GobDecode([]byte) os.Error -} - -var ( - nameToConcreteType = make(map[string]reflect.Type) - concreteTypeToName = make(map[reflect.Type]string) -) - -// RegisterName is like Register but uses the provided name rather than the -// type's default. -func RegisterName(name string, value interface{}) { - if name == "" { - // reserved for nil - panic("attempt to register empty name") - } - base := userType(reflect.Typeof(value)).base - // Check for incompatible duplicates. - if t, ok := nameToConcreteType[name]; ok && t != base { - panic("gob: registering duplicate types for " + name) - } - if n, ok := concreteTypeToName[base]; ok && n != name { - panic("gob: registering duplicate names for " + base.String()) - } - // Store the name and type provided by the user.... - nameToConcreteType[name] = reflect.Typeof(value) - // but the flattened type in the type table, since that's what decode needs. - concreteTypeToName[base] = name -} - -// Register records a type, identified by a value for that type, under its -// internal type name. That name will identify the concrete type of a value -// sent or received as an interface variable. Only types that will be -// transferred as implementations of interface values need to be registered. -// Expecting to be used only during initialization, it panics if the mapping -// between types and names is not a bijection. -func Register(value interface{}) { - // Default to printed representation for unnamed types - rt := reflect.Typeof(value) - name := rt.String() - - // But for named types (or pointers to them), qualify with import path. - // Dereference one pointer looking for a named type. - star := "" - if rt.Name() == "" { - if pt, ok := rt.(*reflect.PtrType); ok { - star = "*" - rt = pt - } - } - if rt.Name() != "" { - if rt.PkgPath() == "" { - name = star + rt.Name() - } else { - name = star + rt.PkgPath() + "." + rt.Name() - } - } - - RegisterName(name, value) -} - -func registerBasics() { - Register(int(0)) - Register(int8(0)) - Register(int16(0)) - Register(int32(0)) - Register(int64(0)) - Register(uint(0)) - Register(uint8(0)) - Register(uint16(0)) - Register(uint32(0)) - Register(uint64(0)) - Register(float32(0)) - Register(float64(0)) - Register(complex64(0i)) - Register(complex128(0i)) - Register(false) - Register("") - Register([]byte(nil)) -} diff --git a/src/cmd/fix/testdata/reflect.type.go.out b/src/cmd/fix/testdata/reflect.type.go.out deleted file mode 100644 index d729ea471a..0000000000 --- a/src/cmd/fix/testdata/reflect.type.go.out +++ /dev/null @@ -1,790 +0,0 @@ -// 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. - -package gob - -import ( - "fmt" - "os" - "reflect" - "sync" - "unicode" - "utf8" -) - -// userTypeInfo stores the information associated with a type the user has handed -// to the package. It's computed once and stored in a map keyed by reflection -// type. -type userTypeInfo struct { - user reflect.Type // the type the user handed us - base reflect.Type // the base type after all indirections - indir int // number of indirections to reach the base type - isGobEncoder bool // does the type implement GobEncoder? - isGobDecoder bool // does the type implement GobDecoder? - encIndir int8 // number of indirections to reach the receiver type; may be negative - decIndir int8 // number of indirections to reach the receiver type; may be negative -} - -var ( - // Protected by an RWMutex because we read it a lot and write - // it only when we see a new type, typically when compiling. - userTypeLock sync.RWMutex - userTypeCache = make(map[reflect.Type]*userTypeInfo) -) - -// validType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, err will be non-nil. To be used when the error handler -// is not set up. -func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) { - userTypeLock.RLock() - ut = userTypeCache[rt] - userTypeLock.RUnlock() - if ut != nil { - return - } - // Now set the value under the write lock. - userTypeLock.Lock() - defer userTypeLock.Unlock() - if ut = userTypeCache[rt]; ut != nil { - // Lost the race; not a problem. - return - } - ut = new(userTypeInfo) - ut.base = rt - ut.user = rt - // A type that is just a cycle of pointers (such as type T *T) cannot - // be represented in gobs, which need some concrete data. We use a - // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, - // pp 539-540. As we step through indirections, run another type at - // half speed. If they meet up, there's a cycle. - slowpoke := ut.base // walks half as fast as ut.base - for { - pt := ut.base - if pt.Kind() != reflect.Ptr { - break - } - ut.base = pt.Elem() - if ut.base == slowpoke { // ut.base lapped slowpoke - // recursive pointer type. - return nil, os.NewError("can't represent recursive pointer type " + ut.base.String()) - } - if ut.indir%2 == 0 { - slowpoke = slowpoke.Elem() - } - ut.indir++ - } - ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderCheck) - ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderCheck) - userTypeCache[rt] = ut - return -} - -const ( - gobEncodeMethodName = "GobEncode" - gobDecodeMethodName = "GobDecode" -) - -// implements returns whether the type implements the interface, as encoded -// in the check function. -func implements(typ reflect.Type, check func(typ reflect.Type) bool) bool { - if typ.NumMethod() == 0 { // avoid allocations etc. unless there's some chance - return false - } - return check(typ) -} - -// gobEncoderCheck makes the type assertion a boolean function. -func gobEncoderCheck(typ reflect.Type) bool { - _, ok := reflect.Zero(typ).Interface().(GobEncoder) - return ok -} - -// gobDecoderCheck makes the type assertion a boolean function. -func gobDecoderCheck(typ reflect.Type) bool { - _, ok := reflect.Zero(typ).Interface().(GobDecoder) - return ok -} - -// implementsInterface reports whether the type implements the -// interface. (The actual check is done through the provided function.) -// It also returns the number of indirections required to get to the -// implementation. -func implementsInterface(typ reflect.Type, check func(typ reflect.Type) bool) (success bool, indir int8) { - if typ == nil { - return - } - rt := typ - // The type might be a pointer and we need to keep - // dereferencing to the base type until we find an implementation. - for { - if implements(rt, check) { - return true, indir - } - if p := rt; p.Kind() == reflect.Ptr { - indir++ - if indir > 100 { // insane number of indirections - return false, 0 - } - rt = p.Elem() - continue - } - break - } - // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. - if typ.Kind() != reflect.Ptr { - // Not a pointer, but does the pointer work? - if implements(reflect.PtrTo(typ), check) { - return true, -1 - } - } - return false, 0 -} - -// userType returns, and saves, the information associated with user-provided type rt. -// If the user type is not valid, it calls error. -func userType(rt reflect.Type) *userTypeInfo { - ut, err := validUserType(rt) - if err != nil { - error(err) - } - return ut -} - -// A typeId represents a gob Type as an integer that can be passed on the wire. -// Internally, typeIds are used as keys to a map to recover the underlying type info. -type typeId int32 - -var nextId typeId // incremented for each new type we build -var typeLock sync.Mutex // set while building a type -const firstUserId = 64 // lowest id number granted to user - -type gobType interface { - id() typeId - setId(id typeId) - name() string - string() string // not public; only for debugging - safeString(seen map[typeId]bool) string -} - -var types = make(map[reflect.Type]gobType) -var idToType = make(map[typeId]gobType) -var builtinIdToType map[typeId]gobType // set in init() after builtins are established - -func setTypeId(typ gobType) { - nextId++ - typ.setId(nextId) - idToType[nextId] = typ -} - -func (t typeId) gobType() gobType { - if t == 0 { - return nil - } - return idToType[t] -} - -// string returns the string representation of the type associated with the typeId. -func (t typeId) string() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().string() -} - -// Name returns the name of the type associated with the typeId. -func (t typeId) name() string { - if t.gobType() == nil { - return "<nil>" - } - return t.gobType().name() -} - -// Common elements of all types. -type CommonType struct { - Name string - Id typeId -} - -func (t *CommonType) id() typeId { return t.Id } - -func (t *CommonType) setId(id typeId) { t.Id = id } - -func (t *CommonType) string() string { return t.Name } - -func (t *CommonType) safeString(seen map[typeId]bool) string { - return t.Name -} - -func (t *CommonType) name() string { return t.Name } - -// Create and check predefined types -// The string for tBytes is "bytes" not "[]byte" to signify its specialness. - -var ( - // Primordial types, needed during initialization. - // Always passed as pointers so the interface{} type - // goes through without losing its interfaceness. - tBool = bootstrapType("bool", (*bool)(nil), 1) - tInt = bootstrapType("int", (*int)(nil), 2) - tUint = bootstrapType("uint", (*uint)(nil), 3) - tFloat = bootstrapType("float", (*float64)(nil), 4) - tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) - tString = bootstrapType("string", (*string)(nil), 6) - tComplex = bootstrapType("complex", (*complex128)(nil), 7) - tInterface = bootstrapType("interface", (*interface{})(nil), 8) - // Reserve some Ids for compatible expansion - tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) - tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) - tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11) - tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12) - tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13) - tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14) - tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15) -) - -// Predefined because it's needed by the Decoder -var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id -var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) - -func init() { - // Some magic numbers to make sure there are no surprises. - checkId(16, tWireType) - checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id) - checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id) - checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id) - checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id) - checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id) - checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id) - - builtinIdToType = make(map[typeId]gobType) - for k, v := range idToType { - builtinIdToType[k] = v - } - - // Move the id space upwards to allow for growth in the predefined world - // without breaking existing files. - if nextId > firstUserId { - panic(fmt.Sprintln("nextId too large:", nextId)) - } - nextId = firstUserId - registerBasics() - wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil))) -} - -// Array type -type arrayType struct { - CommonType - Elem typeId - Len int -} - -func newArrayType(name string) *arrayType { - a := &arrayType{CommonType{Name: name}, 0, 0} - return a -} - -func (a *arrayType) init(elem gobType, len int) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(a) - a.Elem = elem.id() - a.Len = len -} - -func (a *arrayType) safeString(seen map[typeId]bool) string { - if seen[a.Id] { - return a.Name - } - seen[a.Id] = true - return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) -} - -func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } - -// GobEncoder type (something that implements the GobEncoder interface) -type gobEncoderType struct { - CommonType -} - -func newGobEncoderType(name string) *gobEncoderType { - g := &gobEncoderType{CommonType{Name: name}} - setTypeId(g) - return g -} - -func (g *gobEncoderType) safeString(seen map[typeId]bool) string { - return g.Name -} - -func (g *gobEncoderType) string() string { return g.Name } - -// Map type -type mapType struct { - CommonType - Key typeId - Elem typeId -} - -func newMapType(name string) *mapType { - m := &mapType{CommonType{Name: name}, 0, 0} - return m -} - -func (m *mapType) init(key, elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(m) - m.Key = key.id() - m.Elem = elem.id() -} - -func (m *mapType) safeString(seen map[typeId]bool) string { - if seen[m.Id] { - return m.Name - } - seen[m.Id] = true - key := m.Key.gobType().safeString(seen) - elem := m.Elem.gobType().safeString(seen) - return fmt.Sprintf("map[%s]%s", key, elem) -} - -func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } - -// Slice type -type sliceType struct { - CommonType - Elem typeId -} - -func newSliceType(name string) *sliceType { - s := &sliceType{CommonType{Name: name}, 0} - return s -} - -func (s *sliceType) init(elem gobType) { - // Set our type id before evaluating the element's, in case it's our own. - setTypeId(s) - s.Elem = elem.id() -} - -func (s *sliceType) safeString(seen map[typeId]bool) string { - if seen[s.Id] { - return s.Name - } - seen[s.Id] = true - return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) -} - -func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } - -// Struct type -type fieldType struct { - Name string - Id typeId -} - -type structType struct { - CommonType - Field []*fieldType -} - -func (s *structType) safeString(seen map[typeId]bool) string { - if s == nil { - return "<nil>" - } - if _, ok := seen[s.Id]; ok { - return s.Name - } - seen[s.Id] = true - str := s.Name + " = struct { " - for _, f := range s.Field { - str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) - } - str += "}" - return str -} - -func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } - -func newStructType(name string) *structType { - s := &structType{CommonType{Name: name}, nil} - // For historical reasons we set the id here rather than init. - // See the comment in newTypeObject for details. - setTypeId(s) - return s -} - -// newTypeObject allocates a gobType for the reflection type rt. -// Unless ut represents a GobEncoder, rt should be the base type -// of ut. -// This is only called from the encoding side. The decoding side -// works through typeIds and userTypeInfos alone. -func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) { - // Does this type implement GobEncoder? - if ut.isGobEncoder { - return newGobEncoderType(name), nil - } - var err os.Error - var type0, type1 gobType - defer func() { - if err != nil { - types[rt] = nil, false - } - }() - // Install the top-level type before the subtypes (e.g. struct before - // fields) so recursive types can be constructed safely. - switch t := rt; t.Kind() { - // All basic types are easy: they are predefined. - case reflect.Bool: - return tBool.gobType(), nil - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return tInt.gobType(), nil - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return tUint.gobType(), nil - - case reflect.Float32, reflect.Float64: - return tFloat.gobType(), nil - - case reflect.Complex64, reflect.Complex128: - return tComplex.gobType(), nil - - case reflect.String: - return tString.gobType(), nil - - case reflect.Interface: - return tInterface.gobType(), nil - - case reflect.Array: - at := newArrayType(name) - types[rt] = at - type0, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - // Historical aside: - // For arrays, maps, and slices, we set the type id after the elements - // are constructed. This is to retain the order of type id allocation after - // a fix made to handle recursive types, which changed the order in - // which types are built. Delaying the setting in this way preserves - // type ids while allowing recursive types to be described. Structs, - // done below, were already handling recursion correctly so they - // assign the top-level id before those of the field. - at.init(type0, t.Len()) - return at, nil - - case reflect.Map: - mt := newMapType(name) - types[rt] = mt - type0, err = getBaseType("", t.Key()) - if err != nil { - return nil, err - } - type1, err = getBaseType("", t.Elem()) - if err != nil { - return nil, err - } - mt.init(type0, type1) - return mt, nil - - case reflect.Slice: - // []byte == []uint8 is a special case - if t.Elem().Kind() == reflect.Uint8 { - return tBytes.gobType(), nil - } - st := newSliceType(name) - types[rt] = st - type0, err = getBaseType(t.Elem().Name(), t.Elem()) - if err != nil { - return nil, err - } - st.init(type0) - return st, nil - - case reflect.Struct: - st := newStructType(name) - types[rt] = st - idToType[st.id()] = st - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - if !isExported(f.Name) { - continue - } - typ := userType(f.Type).base - tname := typ.Name() - if tname == "" { - t := userType(f.Type).base - tname = t.String() - } - gt, err := getBaseType(tname, f.Type) - if err != nil { - return nil, err - } - st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) - } - return st, nil - - default: - return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String()) - } - return nil, nil -} - -// isExported reports whether this is an exported - upper case - name. -func isExported(name string) bool { - rune, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(rune) -} - -// getBaseType returns the Gob type describing the given reflect.Type's base type. -// typeLock must be held. -func getBaseType(name string, rt reflect.Type) (gobType, os.Error) { - ut := userType(rt) - return getType(name, ut, ut.base) -} - -// getType returns the Gob type describing the given reflect.Type. -// Should be called only when handling GobEncoders/Decoders, -// which may be pointers. All other types are handled through the -// base type, never a pointer. -// typeLock must be held. -func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) { - typ, present := types[rt] - if present { - return typ, nil - } - typ, err := newTypeObject(name, ut, rt) - if err == nil { - types[rt] = typ - } - return typ, err -} - -func checkId(want, got typeId) { - if want != got { - fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) - panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) - } -} - -// used for building the basic types; called only from init(). the incoming -// interface always refers to a pointer. -func bootstrapType(name string, e interface{}, expect typeId) typeId { - rt := reflect.TypeOf(e).Elem() - _, present := types[rt] - if present { - panic("bootstrap type already present: " + name + ", " + rt.String()) - } - typ := &CommonType{Name: name} - types[rt] = typ - setTypeId(typ) - checkId(expect, nextId) - userType(rt) // might as well cache it now - return nextId -} - -// Representation of the information we send and receive about this type. -// Each value we send is preceded by its type definition: an encoded int. -// However, the very first time we send the value, we first send the pair -// (-id, wireType). -// For bootstrapping purposes, we assume that the recipient knows how -// to decode a wireType; it is exactly the wireType struct here, interpreted -// using the gob rules for sending a structure, except that we assume the -// ids for wireType and structType etc. are known. The relevant pieces -// are built in encode.go's init() function. -// To maintain binary compatibility, if you extend this type, always put -// the new fields last. -type wireType struct { - ArrayT *arrayType - SliceT *sliceType - StructT *structType - MapT *mapType - GobEncoderT *gobEncoderType -} - -func (w *wireType) string() string { - const unknown = "unknown type" - if w == nil { - return unknown - } - switch { - case w.ArrayT != nil: - return w.ArrayT.Name - case w.SliceT != nil: - return w.SliceT.Name - case w.StructT != nil: - return w.StructT.Name - case w.MapT != nil: - return w.MapT.Name - case w.GobEncoderT != nil: - return w.GobEncoderT.Name - } - return unknown -} - -type typeInfo struct { - id typeId - encoder *encEngine - wire *wireType -} - -var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock - -// typeLock must be held. -func getTypeInfo(ut *userTypeInfo) (*typeInfo, os.Error) { - rt := ut.base - if ut.isGobEncoder { - // We want the user type, not the base type. - rt = ut.user - } - info, ok := typeInfoMap[rt] - if ok { - return info, nil - } - info = new(typeInfo) - gt, err := getBaseType(rt.Name(), rt) - if err != nil { - return nil, err - } - info.id = gt.id() - - if ut.isGobEncoder { - userType, err := getType(rt.Name(), ut, rt) - if err != nil { - return nil, err - } - info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)} - typeInfoMap[ut.user] = info - return info, nil - } - - t := info.id.gobType() - switch typ := rt; typ.Kind() { - case reflect.Array: - info.wire = &wireType{ArrayT: t.(*arrayType)} - case reflect.Map: - info.wire = &wireType{MapT: t.(*mapType)} - case reflect.Slice: - // []byte == []uint8 is a special case handled separately - if typ.Elem().Kind() != reflect.Uint8 { - info.wire = &wireType{SliceT: t.(*sliceType)} - } - case reflect.Struct: - info.wire = &wireType{StructT: t.(*structType)} - } - typeInfoMap[rt] = info - return info, nil -} - -// Called only when a panic is acceptable and unexpected. -func mustGetTypeInfo(rt reflect.Type) *typeInfo { - t, err := getTypeInfo(userType(rt)) - if err != nil { - panic("getTypeInfo: " + err.String()) - } - return t -} - -// GobEncoder is the interface describing data that provides its own -// representation for encoding values for transmission to a GobDecoder. -// A type that implements GobEncoder and GobDecoder has complete -// control over the representation of its data and may therefore -// contain things such as private fields, channels, and functions, -// which are not usually transmissable in gob streams. -// -// Note: Since gobs can be stored permanently, It is good design -// to guarantee the encoding used by a GobEncoder is stable as the -// software evolves. For instance, it might make sense for GobEncode -// to include a version number in the encoding. -type GobEncoder interface { - // GobEncode returns a byte slice representing the encoding of the - // receiver for transmission to a GobDecoder, usually of the same - // concrete type. - GobEncode() ([]byte, os.Error) -} - -// GobDecoder is the interface describing data that provides its own -// routine for decoding transmitted values sent by a GobEncoder. -type GobDecoder interface { - // GobDecode overwrites the receiver, which must be a pointer, - // with the value represented by the byte slice, which was written - // by GobEncode, usually for the same concrete type. - GobDecode([]byte) os.Error -} - -var ( - nameToConcreteType = make(map[string]reflect.Type) - concreteTypeToName = make(map[reflect.Type]string) -) - -// RegisterName is like Register but uses the provided name rather than the -// type's default. -func RegisterName(name string, value interface{}) { - if name == "" { - // reserved for nil - panic("attempt to register empty name") - } - base := userType(reflect.TypeOf(value)).base - // Check for incompatible duplicates. - if t, ok := nameToConcreteType[name]; ok && t != base { - panic("gob: registering duplicate types for " + name) - } - if n, ok := concreteTypeToName[base]; ok && n != name { - panic("gob: registering duplicate names for " + base.String()) - } - // Store the name and type provided by the user.... - nameToConcreteType[name] = reflect.TypeOf(value) - // but the flattened type in the type table, since that's what decode needs. - concreteTypeToName[base] = name -} - -// Register records a type, identified by a value for that type, under its -// internal type name. That name will identify the concrete type of a value -// sent or received as an interface variable. Only types that will be -// transferred as implementations of interface values need to be registered. -// Expecting to be used only during initialization, it panics if the mapping -// between types and names is not a bijection. -func Register(value interface{}) { - // Default to printed representation for unnamed types - rt := reflect.TypeOf(value) - name := rt.String() - - // But for named types (or pointers to them), qualify with import path. - // Dereference one pointer looking for a named type. - star := "" - if rt.Name() == "" { - if pt := rt; pt.Kind() == reflect.Ptr { - star = "*" - rt = pt - } - } - if rt.Name() != "" { - if rt.PkgPath() == "" { - name = star + rt.Name() - } else { - name = star + rt.PkgPath() + "." + rt.Name() - } - } - - RegisterName(name, value) -} - -func registerBasics() { - Register(int(0)) - Register(int8(0)) - Register(int16(0)) - Register(int32(0)) - Register(int64(0)) - Register(uint(0)) - Register(uint8(0)) - Register(uint16(0)) - Register(uint32(0)) - Register(uint64(0)) - Register(float32(0)) - Register(float64(0)) - Register(complex64(0i)) - Register(complex128(0i)) - Register(false) - Register("") - Register([]byte(nil)) -} |