parser.go (6299B)
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 // Parser knows how to parse all well-defined, encoded EXIF types. 22 type Parser struct { 23 } 24 25 // ParseBytesknows how to parse a byte-type value. 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 // TODO(dustin): Add test 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 // ParseAscii returns a string and auto-strips the trailing NUL character that 47 // should be at the end of the encoding. 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 // TODO(dustin): Add test 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 // Binary 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 // Auto-strip the NUL from the end. It serves no purpose outside of 82 // encoding semantics. 83 84 return string(data[:count-1]), nil 85 } 86 87 // ParseAsciiNoNul returns a string without any consideration for a trailing NUL 88 // character. 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 // TODO(dustin): Add test 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 // ParseShorts knows how to parse an encoded list of shorts. 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 // TODO(dustin): Add test 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 // ParseLongs knows how to encode an encoded list of unsigned longs. 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 // TODO(dustin): Add test 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 // ParseFloats knows how to encode an encoded list of floats. 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 // ParseDoubles knows how to encode an encoded list of doubles. 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 // ParseRationals knows how to parse an encoded list of unsigned rationals. 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 // TODO(dustin): Add test 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 // ParseSignedLongs knows how to parse an encoded list of signed longs. 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 // TODO(dustin): Add test 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 // ParseSignedRationals knows how to parse an encoded list of signed 252 // rationals. 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 // TODO(dustin): Add test 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 }