-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
153 lines (128 loc) · 4.09 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package sbm
import (
"bytes"
"errors"
"fmt"
"math"
"strconv"
"strings"
)
// Errors.
const (
ErrFormat = "format is unrecognized"
ErrHeaderSyntax = "header syntax error"
ErrfHeaderUnexpected = "unexpected header: '%v'"
ErrOverflow = "overflow"
ErrIntegrity = "integrity failure"
)
// parseHeaderFormat parses the format header.
func (sbm *Sbm) parseHeaderFormat(rawHeader []byte) (err error) {
if !bytes.Equal(rawHeader, []byte(Header_FormatName)) {
return errors.New(ErrFormat)
}
return nil
}
// parseHeaderVersion parses the version header.
func parseHeaderVersion(rawHeader []byte) (headerData HeaderDataVersion, err error) {
// Trim.
var rawHeaderTrimmed []byte
rawHeaderTrimmed, err = trimHeader(rawHeader)
if err != nil {
return headerData, err
}
// Split.
headerPartsCountExpected := 2
headerParts := strings.Split(string(rawHeaderTrimmed), HeaderPartsSeparator)
if len(headerParts) != headerPartsCountExpected {
return headerData, errors.New(ErrHeaderSyntax)
}
// Check the header name.
if headerParts[0] != HeaderPrefix_Version {
return headerData, fmt.Errorf(ErrfHeaderUnexpected, headerParts[0])
}
// Parse the version number.
var versionNumberTmp uint64
versionNumberTmp, err = strconv.ParseUint(headerParts[1], 10, 64)
if err != nil {
return headerData, err
}
if versionNumberTmp > math.MaxUint8 {
return headerData, errors.New(ErrOverflow)
}
// Save the version number.
headerData.version = byte(versionNumberTmp)
return headerData, nil
}
// parseHeaderSize parses the size header.
func parseHeaderSize(rawHeader []byte, headerNameExpected string) (headerData HeaderDataSize, err error) {
// Trim.
var rawHeaderTrimmed []byte
rawHeaderTrimmed, err = trimHeader(rawHeader)
if err != nil {
return headerData, err
}
// Split.
headerPartsCountExpected := 5
headerParts := strings.Split(string(rawHeaderTrimmed), HeaderPartsSeparator)
if len(headerParts) != headerPartsCountExpected {
return headerData, errors.New(ErrHeaderSyntax)
}
// Check the header name.
if headerParts[0] != headerNameExpected {
return headerData, fmt.Errorf(ErrfHeaderUnexpected, headerParts[0])
}
// Parse the fixed size.
var sizeTmp uint64
sizeTmp, err = strconv.ParseUint(headerParts[1], 10, 64)
if err != nil {
return headerData, err
}
sizeFixed := uint(sizeTmp)
// Parse the random left size.
headerPartSizeLeft := headerParts[2]
if !strings.HasPrefix(headerPartSizeLeft, HeaderPartsBracketLeft) {
return headerData, errors.New(ErrHeaderSyntax)
}
headerPartSizeLeft = strings.TrimLeft(headerPartSizeLeft, HeaderPartsBracketLeft)
sizeTmp, err = strconv.ParseUint(headerPartSizeLeft, 10, 64)
if err != nil {
return headerData, err
}
sizeRandomLeft := uint(sizeTmp)
// Plus sign.
if headerParts[3] != HeaderPartsPlus {
return headerData, errors.New(ErrHeaderSyntax)
}
// Parse the random right size.
headerPartSizeRight := headerParts[4]
if !strings.HasSuffix(headerPartSizeRight, HeaderPartsBracketRight) {
return headerData, errors.New(ErrHeaderSyntax)
}
headerPartSizeRight = strings.TrimRight(headerPartSizeRight, HeaderPartsBracketRight)
sizeTmp, err = strconv.ParseUint(headerPartSizeRight, 10, 64)
if err != nil {
return headerData, err
}
sizeRandomRight := uint(sizeTmp)
// Verify the integrity of the size.
if sizeFixed != (sizeRandomLeft + sizeRandomRight) {
return headerData, errors.New(ErrIntegrity)
}
// Save the data.
headerData.sizeFixed = sizeFixed
headerData.sizeRandomLeft = sizeRandomLeft
headerData.sizeRandomRight = sizeRandomRight
return headerData, nil
}
// parseHeaderWidth parses the width header.
func parseHeaderWidth(rawHeader []byte) (headerData HeaderDataSize, err error) {
return parseHeaderSize(rawHeader, HeaderPrefix_Width)
}
// parseHeaderHeight parses the height header.
func parseHeaderHeight(rawHeader []byte) (headerData HeaderDataSize, err error) {
return parseHeaderSize(rawHeader, HeaderPrefix_Height)
}
// parseHeaderArea parses the area header.
func parseHeaderArea(rawHeader []byte) (headerData HeaderDataSize, err error) {
return parseHeaderSize(rawHeader, HeaderPrefix_Area)
}