OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [encoding/] [asn1/] [marshal.go] - Blame information for rev 774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package asn1
6
 
7
import (
8
        "bytes"
9
        "fmt"
10
        "io"
11
        "math/big"
12
        "reflect"
13
        "time"
14
)
15
 
16
// A forkableWriter is an in-memory buffer that can be
17
// 'forked' to create new forkableWriters that bracket the
18
// original.  After
19
//    pre, post := w.fork();
20
// the overall sequence of bytes represented is logically w+pre+post.
21
type forkableWriter struct {
22
        *bytes.Buffer
23
        pre, post *forkableWriter
24
}
25
 
26
func newForkableWriter() *forkableWriter {
27
        return &forkableWriter{new(bytes.Buffer), nil, nil}
28
}
29
 
30
func (f *forkableWriter) fork() (pre, post *forkableWriter) {
31
        if f.pre != nil || f.post != nil {
32
                panic("have already forked")
33
        }
34
        f.pre = newForkableWriter()
35
        f.post = newForkableWriter()
36
        return f.pre, f.post
37
}
38
 
39
func (f *forkableWriter) Len() (l int) {
40
        l += f.Buffer.Len()
41
        if f.pre != nil {
42
                l += f.pre.Len()
43
        }
44
        if f.post != nil {
45
                l += f.post.Len()
46
        }
47
        return
48
}
49
 
50
func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
51
        n, err = out.Write(f.Bytes())
52
        if err != nil {
53
                return
54
        }
55
 
56
        var nn int
57
 
58
        if f.pre != nil {
59
                nn, err = f.pre.writeTo(out)
60
                n += nn
61
                if err != nil {
62
                        return
63
                }
64
        }
65
 
66
        if f.post != nil {
67
                nn, err = f.post.writeTo(out)
68
                n += nn
69
        }
70
        return
71
}
72
 
73
func marshalBase128Int(out *forkableWriter, n int64) (err error) {
74
        if n == 0 {
75
                err = out.WriteByte(0)
76
                return
77
        }
78
 
79
        l := 0
80
        for i := n; i > 0; i >>= 7 {
81
                l++
82
        }
83
 
84
        for i := l - 1; i >= 0; i-- {
85
                o := byte(n >> uint(i*7))
86
                o &= 0x7f
87
                if i != 0 {
88
                        o |= 0x80
89
                }
90
                err = out.WriteByte(o)
91
                if err != nil {
92
                        return
93
                }
94
        }
95
 
96
        return nil
97
}
98
 
99
func marshalInt64(out *forkableWriter, i int64) (err error) {
100
        n := int64Length(i)
101
 
102
        for ; n > 0; n-- {
103
                err = out.WriteByte(byte(i >> uint((n-1)*8)))
104
                if err != nil {
105
                        return
106
                }
107
        }
108
 
109
        return nil
110
}
111
 
112
func int64Length(i int64) (numBytes int) {
113
        numBytes = 1
114
 
115
        for i > 127 {
116
                numBytes++
117
                i >>= 8
118
        }
119
 
120
        for i < -128 {
121
                numBytes++
122
                i >>= 8
123
        }
124
 
125
        return
126
}
127
 
128
func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
129
        if n.Sign() < 0 {
130
                // A negative number has to be converted to two's-complement
131
                // form. So we'll subtract 1 and invert. If the
132
                // most-significant-bit isn't set then we'll need to pad the
133
                // beginning with 0xff in order to keep the number negative.
134
                nMinus1 := new(big.Int).Neg(n)
135
                nMinus1.Sub(nMinus1, bigOne)
136
                bytes := nMinus1.Bytes()
137
                for i := range bytes {
138
                        bytes[i] ^= 0xff
139
                }
140
                if len(bytes) == 0 || bytes[0]&0x80 == 0 {
141
                        err = out.WriteByte(0xff)
142
                        if err != nil {
143
                                return
144
                        }
145
                }
146
                _, err = out.Write(bytes)
147
        } else if n.Sign() == 0 {
148
                // Zero is written as a single 0 zero rather than no bytes.
149
                err = out.WriteByte(0x00)
150
        } else {
151
                bytes := n.Bytes()
152
                if len(bytes) > 0 && bytes[0]&0x80 != 0 {
153
                        // We'll have to pad this with 0x00 in order to stop it
154
                        // looking like a negative number.
155
                        err = out.WriteByte(0)
156
                        if err != nil {
157
                                return
158
                        }
159
                }
160
                _, err = out.Write(bytes)
161
        }
162
        return
163
}
164
 
165
func marshalLength(out *forkableWriter, i int) (err error) {
166
        n := lengthLength(i)
167
 
168
        for ; n > 0; n-- {
169
                err = out.WriteByte(byte(i >> uint((n-1)*8)))
170
                if err != nil {
171
                        return
172
                }
173
        }
174
 
175
        return nil
176
}
177
 
178
func lengthLength(i int) (numBytes int) {
179
        numBytes = 1
180
        for i > 255 {
181
                numBytes++
182
                i >>= 8
183
        }
184
        return
185
}
186
 
187
func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
188
        b := uint8(t.class) << 6
189
        if t.isCompound {
190
                b |= 0x20
191
        }
192
        if t.tag >= 31 {
193
                b |= 0x1f
194
                err = out.WriteByte(b)
195
                if err != nil {
196
                        return
197
                }
198
                err = marshalBase128Int(out, int64(t.tag))
199
                if err != nil {
200
                        return
201
                }
202
        } else {
203
                b |= uint8(t.tag)
204
                err = out.WriteByte(b)
205
                if err != nil {
206
                        return
207
                }
208
        }
209
 
210
        if t.length >= 128 {
211
                l := lengthLength(t.length)
212
                err = out.WriteByte(0x80 | byte(l))
213
                if err != nil {
214
                        return
215
                }
216
                err = marshalLength(out, t.length)
217
                if err != nil {
218
                        return
219
                }
220
        } else {
221
                err = out.WriteByte(byte(t.length))
222
                if err != nil {
223
                        return
224
                }
225
        }
226
 
227
        return nil
228
}
229
 
230
func marshalBitString(out *forkableWriter, b BitString) (err error) {
231
        paddingBits := byte((8 - b.BitLength%8) % 8)
232
        err = out.WriteByte(paddingBits)
233
        if err != nil {
234
                return
235
        }
236
        _, err = out.Write(b.Bytes)
237
        return
238
}
239
 
240
func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
241
        if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
242
                return StructuralError{"invalid object identifier"}
243
        }
244
 
245
        err = out.WriteByte(byte(oid[0]*40 + oid[1]))
246
        if err != nil {
247
                return
248
        }
249
        for i := 2; i < len(oid); i++ {
250
                err = marshalBase128Int(out, int64(oid[i]))
251
                if err != nil {
252
                        return
253
                }
254
        }
255
 
256
        return
257
}
258
 
259
func marshalPrintableString(out *forkableWriter, s string) (err error) {
260
        b := []byte(s)
261
        for _, c := range b {
262
                if !isPrintable(c) {
263
                        return StructuralError{"PrintableString contains invalid character"}
264
                }
265
        }
266
 
267
        _, err = out.Write(b)
268
        return
269
}
270
 
271
func marshalIA5String(out *forkableWriter, s string) (err error) {
272
        b := []byte(s)
273
        for _, c := range b {
274
                if c > 127 {
275
                        return StructuralError{"IA5String contains invalid character"}
276
                }
277
        }
278
 
279
        _, err = out.Write(b)
280
        return
281
}
282
 
283
func marshalTwoDigits(out *forkableWriter, v int) (err error) {
284
        err = out.WriteByte(byte('0' + (v/10)%10))
285
        if err != nil {
286
                return
287
        }
288
        return out.WriteByte(byte('0' + v%10))
289
}
290
 
291
func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
292
        utc := t.UTC()
293
        year, month, day := utc.Date()
294
 
295
        switch {
296
        case 1950 <= year && year < 2000:
297
                err = marshalTwoDigits(out, int(year-1900))
298
        case 2000 <= year && year < 2050:
299
                err = marshalTwoDigits(out, int(year-2000))
300
        default:
301
                return StructuralError{"Cannot represent time as UTCTime"}
302
        }
303
        if err != nil {
304
                return
305
        }
306
 
307
        err = marshalTwoDigits(out, int(month))
308
        if err != nil {
309
                return
310
        }
311
 
312
        err = marshalTwoDigits(out, day)
313
        if err != nil {
314
                return
315
        }
316
 
317
        hour, min, sec := utc.Clock()
318
 
319
        err = marshalTwoDigits(out, hour)
320
        if err != nil {
321
                return
322
        }
323
 
324
        err = marshalTwoDigits(out, min)
325
        if err != nil {
326
                return
327
        }
328
 
329
        err = marshalTwoDigits(out, sec)
330
        if err != nil {
331
                return
332
        }
333
 
334
        _, offset := t.Zone()
335
 
336
        switch {
337
        case offset/60 == 0:
338
                err = out.WriteByte('Z')
339
                return
340
        case offset > 0:
341
                err = out.WriteByte('+')
342
        case offset < 0:
343
                err = out.WriteByte('-')
344
        }
345
 
346
        if err != nil {
347
                return
348
        }
349
 
350
        offsetMinutes := offset / 60
351
        if offsetMinutes < 0 {
352
                offsetMinutes = -offsetMinutes
353
        }
354
 
355
        err = marshalTwoDigits(out, offsetMinutes/60)
356
        if err != nil {
357
                return
358
        }
359
 
360
        err = marshalTwoDigits(out, offsetMinutes%60)
361
        return
362
}
363
 
364
func stripTagAndLength(in []byte) []byte {
365
        _, offset, err := parseTagAndLength(in, 0)
366
        if err != nil {
367
                return in
368
        }
369
        return in[offset:]
370
}
371
 
372
func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
373
        switch value.Type() {
374
        case timeType:
375
                return marshalUTCTime(out, value.Interface().(time.Time))
376
        case bitStringType:
377
                return marshalBitString(out, value.Interface().(BitString))
378
        case objectIdentifierType:
379
                return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
380
        case bigIntType:
381
                return marshalBigInt(out, value.Interface().(*big.Int))
382
        }
383
 
384
        switch v := value; v.Kind() {
385
        case reflect.Bool:
386
                if v.Bool() {
387
                        return out.WriteByte(255)
388
                } else {
389
                        return out.WriteByte(0)
390
                }
391
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
392
                return marshalInt64(out, int64(v.Int()))
393
        case reflect.Struct:
394
                t := v.Type()
395
 
396
                startingField := 0
397
 
398
                // If the first element of the structure is a non-empty
399
                // RawContents, then we don't bother serializing the rest.
400
                if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
401
                        s := v.Field(0)
402
                        if s.Len() > 0 {
403
                                bytes := make([]byte, s.Len())
404
                                for i := 0; i < s.Len(); i++ {
405
                                        bytes[i] = uint8(s.Index(i).Uint())
406
                                }
407
                                /* The RawContents will contain the tag and
408
                                 * length fields but we'll also be writing
409
                                 * those ourselves, so we strip them out of
410
                                 * bytes */
411
                                _, err = out.Write(stripTagAndLength(bytes))
412
                                return
413
                        } else {
414
                                startingField = 1
415
                        }
416
                }
417
 
418
                for i := startingField; i < t.NumField(); i++ {
419
                        var pre *forkableWriter
420
                        pre, out = out.fork()
421
                        err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
422
                        if err != nil {
423
                                return
424
                        }
425
                }
426
                return
427
        case reflect.Slice:
428
                sliceType := v.Type()
429
                if sliceType.Elem().Kind() == reflect.Uint8 {
430
                        bytes := make([]byte, v.Len())
431
                        for i := 0; i < v.Len(); i++ {
432
                                bytes[i] = uint8(v.Index(i).Uint())
433
                        }
434
                        _, err = out.Write(bytes)
435
                        return
436
                }
437
 
438
                var params fieldParameters
439
                for i := 0; i < v.Len(); i++ {
440
                        var pre *forkableWriter
441
                        pre, out = out.fork()
442
                        err = marshalField(pre, v.Index(i), params)
443
                        if err != nil {
444
                                return
445
                        }
446
                }
447
                return
448
        case reflect.String:
449
                if params.stringType == tagIA5String {
450
                        return marshalIA5String(out, v.String())
451
                } else {
452
                        return marshalPrintableString(out, v.String())
453
                }
454
                return
455
        }
456
 
457
        return StructuralError{"unknown Go type"}
458
}
459
 
460
func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
461
        // If the field is an interface{} then recurse into it.
462
        if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
463
                return marshalField(out, v.Elem(), params)
464
        }
465
 
466
        if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
467
                return
468
        }
469
 
470
        if v.Type() == rawValueType {
471
                rv := v.Interface().(RawValue)
472
                if len(rv.FullBytes) != 0 {
473
                        _, err = out.Write(rv.FullBytes)
474
                } else {
475
                        err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
476
                        if err != nil {
477
                                return
478
                        }
479
                        _, err = out.Write(rv.Bytes)
480
                }
481
                return
482
        }
483
 
484
        tag, isCompound, ok := getUniversalType(v.Type())
485
        if !ok {
486
                err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
487
                return
488
        }
489
        class := classUniversal
490
 
491
        if params.stringType != 0 {
492
                if tag != tagPrintableString {
493
                        return StructuralError{"Explicit string type given to non-string member"}
494
                }
495
                tag = params.stringType
496
        }
497
 
498
        if params.set {
499
                if tag != tagSequence {
500
                        return StructuralError{"Non sequence tagged as set"}
501
                }
502
                tag = tagSet
503
        }
504
 
505
        tags, body := out.fork()
506
 
507
        err = marshalBody(body, v, params)
508
        if err != nil {
509
                return
510
        }
511
 
512
        bodyLen := body.Len()
513
 
514
        var explicitTag *forkableWriter
515
        if params.explicit {
516
                explicitTag, tags = tags.fork()
517
        }
518
 
519
        if !params.explicit && params.tag != nil {
520
                // implicit tag.
521
                tag = *params.tag
522
                class = classContextSpecific
523
        }
524
 
525
        err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
526
        if err != nil {
527
                return
528
        }
529
 
530
        if params.explicit {
531
                err = marshalTagAndLength(explicitTag, tagAndLength{
532
                        class:      classContextSpecific,
533
                        tag:        *params.tag,
534
                        length:     bodyLen + tags.Len(),
535
                        isCompound: true,
536
                })
537
        }
538
 
539
        return nil
540
}
541
 
542
// Marshal returns the ASN.1 encoding of val.
543
func Marshal(val interface{}) ([]byte, error) {
544
        var out bytes.Buffer
545
        v := reflect.ValueOf(val)
546
        f := newForkableWriter()
547
        err := marshalField(f, v, fieldParameters{})
548
        if err != nil {
549
                return nil, err
550
        }
551
        _, err = f.writeTo(&out)
552
        return out.Bytes(), nil
553
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.