1 package exifcommon
2
3 import (
4 "bytes"
5 "errors"
6 "math"
7
8 "encoding/binary"
9
10 "github.com/dsoprea/go-logging"
11 )
12
13 var (
14 parserLogger = log.NewLogger("exifcommon.parser")
15 )
16
17 var (
18 ErrParseFail = errors.New("parse failure")
19 )
20
21
22 type Parser struct {
23 }
24
25
26 func (p *Parser) ParseBytes(data []byte, unitCount uint32) (value []uint8, err error) {
27 defer func() {
28 if state := recover(); state != nil {
29 err = log.Wrap(state.(error))
30 }
31 }()
32
33
34
35 count := int(unitCount)
36
37 if len(data) < (TypeByte.Size() * count) {
38 log.Panic(ErrNotEnoughData)
39 }
40
41 value = []uint8(data[:count])
42
43 return value, nil
44 }
45
46
47
48 func (p *Parser) ParseAscii(data []byte, unitCount uint32) (value string, err error) {
49 defer func() {
50 if state := recover(); state != nil {
51 err = log.Wrap(state.(error))
52 }
53 }()
54
55
56
57 count := int(unitCount)
58
59 if len(data) < (TypeAscii.Size() * count) {
60 log.Panic(ErrNotEnoughData)
61 }
62
63 if len(data) == 0 || data[count-1] != 0 {
64 s := string(data[:count])
65 parserLogger.Warningf(nil, "ASCII not terminated with NUL as expected: [%v]", s)
66
67 for i, c := range s {
68 if c > 127 {
69
70
71 t := s[:i]
72 parserLogger.Warningf(nil, "ASCII also had binary characters. Truncating: [%v]->[%s]", s, t)
73
74 return t, nil
75 }
76 }
77
78 return s, nil
79 }
80
81
82
83
84 return string(data[:count-1]), nil
85 }
86
87
88
89 func (p *Parser) ParseAsciiNoNul(data []byte, unitCount uint32) (value string, err error) {
90 defer func() {
91 if state := recover(); state != nil {
92 err = log.Wrap(state.(error))
93 }
94 }()
95
96
97
98 count := int(unitCount)
99
100 if len(data) < (TypeAscii.Size() * count) {
101 log.Panic(ErrNotEnoughData)
102 }
103
104 return string(data[:count]), nil
105 }
106
107
108 func (p *Parser) ParseShorts(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint16, err error) {
109 defer func() {
110 if state := recover(); state != nil {
111 err = log.Wrap(state.(error))
112 }
113 }()
114
115
116
117 count := int(unitCount)
118
119 if len(data) < (TypeShort.Size() * count) {
120 log.Panic(ErrNotEnoughData)
121 }
122
123 value = make([]uint16, count)
124 for i := 0; i < count; i++ {
125 value[i] = byteOrder.Uint16(data[i*2:])
126 }
127
128 return value, nil
129 }
130
131
132 func (p *Parser) ParseLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint32, err error) {
133 defer func() {
134 if state := recover(); state != nil {
135 err = log.Wrap(state.(error))
136 }
137 }()
138
139
140
141 count := int(unitCount)
142
143 if len(data) < (TypeLong.Size() * count) {
144 log.Panic(ErrNotEnoughData)
145 }
146
147 value = make([]uint32, count)
148 for i := 0; i < count; i++ {
149 value[i] = byteOrder.Uint32(data[i*4:])
150 }
151
152 return value, nil
153 }
154
155
156 func (p *Parser) ParseFloats(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []float32, err error) {
157 defer func() {
158 if state := recover(); state != nil {
159 err = log.Wrap(state.(error))
160 }
161 }()
162
163 count := int(unitCount)
164
165 if len(data) != (TypeFloat.Size() * count) {
166 log.Panic(ErrNotEnoughData)
167 }
168
169 value = make([]float32, count)
170 for i := 0; i < count; i++ {
171 value[i] = math.Float32frombits(byteOrder.Uint32(data[i*4 : (i+1)*4]))
172 }
173
174 return value, nil
175 }
176
177
178 func (p *Parser) ParseDoubles(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []float64, err error) {
179 defer func() {
180 if state := recover(); state != nil {
181 err = log.Wrap(state.(error))
182 }
183 }()
184
185 count := int(unitCount)
186
187 if len(data) != (TypeDouble.Size() * count) {
188 log.Panic(ErrNotEnoughData)
189 }
190
191 value = make([]float64, count)
192 for i := 0; i < count; i++ {
193 value[i] = math.Float64frombits(byteOrder.Uint64(data[i*8 : (i+1)*8]))
194 }
195
196 return value, nil
197 }
198
199
200 func (p *Parser) ParseRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []Rational, err error) {
201 defer func() {
202 if state := recover(); state != nil {
203 err = log.Wrap(state.(error))
204 }
205 }()
206
207
208
209 count := int(unitCount)
210
211 if len(data) < (TypeRational.Size() * count) {
212 log.Panic(ErrNotEnoughData)
213 }
214
215 value = make([]Rational, count)
216 for i := 0; i < count; i++ {
217 value[i].Numerator = byteOrder.Uint32(data[i*8:])
218 value[i].Denominator = byteOrder.Uint32(data[i*8+4:])
219 }
220
221 return value, nil
222 }
223
224
225 func (p *Parser) ParseSignedLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []int32, err error) {
226 defer func() {
227 if state := recover(); state != nil {
228 err = log.Wrap(state.(error))
229 }
230 }()
231
232
233
234 count := int(unitCount)
235
236 if len(data) < (TypeSignedLong.Size() * count) {
237 log.Panic(ErrNotEnoughData)
238 }
239
240 b := bytes.NewBuffer(data)
241
242 value = make([]int32, count)
243 for i := 0; i < count; i++ {
244 err := binary.Read(b, byteOrder, &value[i])
245 log.PanicIf(err)
246 }
247
248 return value, nil
249 }
250
251
252
253 func (p *Parser) ParseSignedRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []SignedRational, err error) {
254 defer func() {
255 if state := recover(); state != nil {
256 err = log.Wrap(state.(error))
257 }
258 }()
259
260
261
262 count := int(unitCount)
263
264 if len(data) < (TypeSignedRational.Size() * count) {
265 log.Panic(ErrNotEnoughData)
266 }
267
268 b := bytes.NewBuffer(data)
269
270 value = make([]SignedRational, count)
271 for i := 0; i < count; i++ {
272 err = binary.Read(b, byteOrder, &value[i].Numerator)
273 log.PanicIf(err)
274
275 err = binary.Read(b, byteOrder, &value[i].Denominator)
276 log.PanicIf(err)
277 }
278
279 return value, nil
280 }
281
View as plain text