OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / asn1 / marshal.go
index a3e1145..d7eb63b 100644 (file)
@@ -5,6 +5,7 @@
 package asn1
 
 import (
+       "big"
        "bytes"
        "fmt"
        "io"
@@ -125,6 +126,43 @@ func int64Length(i int64) (numBytes int) {
        return
 }
 
+func marshalBigInt(out *forkableWriter, n *big.Int) (err os.Error) {
+       if n.Sign() < 0 {
+               // A negative number has to be converted to two's-complement
+               // form. So we'll subtract 1 and invert. If the
+               // most-significant-bit isn't set then we'll need to pad the
+               // beginning with 0xff in order to keep the number negative.
+               nMinus1 := new(big.Int).Neg(n)
+               nMinus1.Sub(nMinus1, bigOne)
+               bytes := nMinus1.Bytes()
+               for i := range bytes {
+                       bytes[i] ^= 0xff
+               }
+               if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+                       err = out.WriteByte(0xff)
+                       if err != nil {
+                               return
+                       }
+               }
+               _, err = out.Write(bytes)
+       } else if n.Sign() == 0 {
+               // Zero is written as a single 0 zero rather than no bytes.
+               err = out.WriteByte(0x00)
+       } else {
+               bytes := n.Bytes()
+               if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+                       // We'll have to pad this with 0x00 in order to stop it
+                       // looking like a negative number.
+                       err = out.WriteByte(0)
+                       if err != nil {
+                               return
+                       }
+               }
+               _, err = out.Write(bytes)
+       }
+       return
+}
+
 func marshalLength(out *forkableWriter, i int) (err os.Error) {
        n := lengthLength(i)
 
@@ -334,6 +372,8 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                return marshalBitString(out, value.Interface().(BitString))
        case objectIdentifierType:
                return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
+       case bigIntType:
+               return marshalBigInt(out, value.Interface().(*big.Int))
        }
 
        switch v := value; v.Kind() {
@@ -351,7 +391,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                startingField := 0
 
                // If the first element of the structure is a non-empty
-               // RawContents, then we don't bother serialising the rest.
+               // RawContents, then we don't bother serializing the rest.
                if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
                        s := v.Field(0)
                        if s.Len() > 0 {
@@ -361,7 +401,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                                }
                                /* The RawContents will contain the tag and
                                 * length fields but we'll also be writing
-                                * those outselves, so we strip them out of
+                                * those ourselves, so we strip them out of
                                 * bytes */
                                _, err = out.Write(stripTagAndLength(bytes))
                                return
@@ -373,7 +413,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                for i := startingField; i < t.NumField(); i++ {
                        var pre *forkableWriter
                        pre, out = out.fork()
-                       err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag))
+                       err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
                        if err != nil {
                                return
                        }
@@ -418,6 +458,10 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
                return marshalField(out, v.Elem(), params)
        }
 
+       if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
+               return
+       }
+
        if v.Type() == rawValueType {
                rv := v.Interface().(RawValue)
                err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
@@ -428,10 +472,6 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
                return
        }
 
-       if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
-               return
-       }
-
        tag, isCompound, ok := getUniversalType(v.Type())
        if !ok {
                err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}