...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package assuan
18
19
20
21 import (
22 "bytes"
23 "errors"
24 "strconv"
25 )
26
27 type csExp struct {
28 Value []byte
29 Items []*csExp
30 }
31
32 var InvalidCsExp = errors.New("invalid cs-exp")
33
34 func parseCsExp(blob []byte) (*csExp, error) {
35 root := new(csExp)
36 stack := []*csExp{root}
37 top := root
38 csloop:
39 for {
40 switch {
41 case len(blob) == 0:
42 if len(stack) > 1 {
43 return nil, InvalidCsExp
44 }
45 break csloop
46 case blob[0] == '(':
47 item := new(csExp)
48 stack = append(stack, item)
49 top.Items = append(top.Items, item)
50 top = item
51 blob = blob[1:]
52 case blob[0] == ')':
53 if len(stack) < 2 {
54 return nil, InvalidCsExp
55 }
56 stack = stack[:len(stack)-1]
57 top = stack[len(stack)-1]
58 blob = blob[1:]
59 default:
60 n := bytes.IndexByte(blob, ':')
61 if n < 1 {
62 return nil, InvalidCsExp
63 }
64 length, err := strconv.ParseUint(string(blob[:n]), 10, 64)
65 if err != nil || length > uint64(len(blob)-n-1) {
66 return nil, InvalidCsExp
67 }
68 blob = blob[n+1:]
69 data := blob[:length]
70 blob = blob[length:]
71 top.Items = append(top.Items, &csExp{Value: data})
72 }
73 }
74 return root, nil
75 }
76
View as plain text