mirror of
https://github.com/dsoprea/go-exif.git
synced 2025-04-28 05:33:05 +00:00
Use encapsulated data/reader rather than bytes
Given a stream of data, it is possible to determine the beginning of EXIF data but not the end. Therefore, either an image-aware implementation must know how to parse an image and extract the EXIF data or a brute-force search implementation (one of which is provided by this project) must find the start anchor and then return all bytes from that to the end of the file. We have been made aware of some use-cases where a brute-force search might be unavoidable due to trust or stability issues with the image structure. This leads to large allocations. This can be avoided by accomodating support that will allow for both a byte-slice or an `io.ReadSeeker`. Since the EXIF structure is typically not read- intensive (a couple of kilobytes if no thumbnail is present), this should have a minimal performance impact. Closes #42
This commit is contained in:
parent
56058635d0
commit
312218d7b1
@ -2,6 +2,7 @@ package exifcommon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ type ValueContext struct {
|
|||||||
unitCount uint32
|
unitCount uint32
|
||||||
valueOffset uint32
|
valueOffset uint32
|
||||||
rawValueOffset []byte
|
rawValueOffset []byte
|
||||||
addressableData []byte
|
rs io.ReadSeeker
|
||||||
|
|
||||||
tagType TagTypePrimitive
|
tagType TagTypePrimitive
|
||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
@ -40,12 +41,12 @@ type ValueContext struct {
|
|||||||
// TODO(dustin): We can update newValueContext() to derive `valueOffset` itself (from `rawValueOffset`).
|
// TODO(dustin): We can update newValueContext() to derive `valueOffset` itself (from `rawValueOffset`).
|
||||||
|
|
||||||
// NewValueContext returns a new ValueContext struct.
|
// NewValueContext returns a new ValueContext struct.
|
||||||
func NewValueContext(ifdPath string, tagId uint16, unitCount, valueOffset uint32, rawValueOffset, addressableData []byte, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext {
|
func NewValueContext(ifdPath string, tagId uint16, unitCount, valueOffset uint32, rawValueOffset []byte, rs io.ReadSeeker, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext {
|
||||||
return &ValueContext{
|
return &ValueContext{
|
||||||
unitCount: unitCount,
|
unitCount: unitCount,
|
||||||
valueOffset: valueOffset,
|
valueOffset: valueOffset,
|
||||||
rawValueOffset: rawValueOffset,
|
rawValueOffset: rawValueOffset,
|
||||||
addressableData: addressableData,
|
rs: rs,
|
||||||
|
|
||||||
tagType: tagType,
|
tagType: tagType,
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
@ -82,8 +83,11 @@ func (vc *ValueContext) RawValueOffset() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddressableData returns the block of data that we can dereference into.
|
// AddressableData returns the block of data that we can dereference into.
|
||||||
func (vc *ValueContext) AddressableData() []byte {
|
func (vc *ValueContext) AddressableData() io.ReadSeeker {
|
||||||
return vc.addressableData
|
|
||||||
|
// RELEASE)dustin): Rename from AddressableData() to ReadSeeker()
|
||||||
|
|
||||||
|
return vc.rs
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByteOrder returns the byte-order of numbers.
|
// ByteOrder returns the byte-order of numbers.
|
||||||
@ -152,7 +156,15 @@ func (vc *ValueContext) readRawEncoded() (rawBytes []byte, err error) {
|
|||||||
return vc.rawValueOffset[:byteLength], nil
|
return vc.rawValueOffset[:byteLength], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return vc.addressableData[vc.valueOffset : vc.valueOffset+vc.unitCount*unitSizeRaw], nil
|
_, err = vc.rs.Seek(int64(vc.valueOffset), io.SeekStart)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
rawBytes = make([]byte, vc.unitCount*unitSizeRaw)
|
||||||
|
|
||||||
|
_, err = io.ReadFull(vc.rs, rawBytes)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
return rawBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFarOffset returns the offset if the value is not embedded [within the
|
// GetFarOffset returns the offset if the value is not embedded [within the
|
||||||
|
@ -5,13 +5,26 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewValueContext(t *testing.T) {
|
func TestNewValueContext(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeLong, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.ifdPath != "aa/bb" {
|
if vc.ifdPath != "aa/bb" {
|
||||||
t.Fatalf("ifdPath not correct: [%s]", vc.ifdPath)
|
t.Fatalf("ifdPath not correct: [%s]", vc.ifdPath)
|
||||||
@ -23,13 +36,18 @@ func TestNewValueContext(t *testing.T) {
|
|||||||
t.Fatalf("valueOffset not correct: (%d)", vc.valueOffset)
|
t.Fatalf("valueOffset not correct: (%d)", vc.valueOffset)
|
||||||
} else if bytes.Equal(vc.rawValueOffset, rawValueOffset) != true {
|
} else if bytes.Equal(vc.rawValueOffset, rawValueOffset) != true {
|
||||||
t.Fatalf("rawValueOffset not correct: %v", vc.rawValueOffset)
|
t.Fatalf("rawValueOffset not correct: %v", vc.rawValueOffset)
|
||||||
} else if bytes.Equal(vc.addressableData, addressableData) != true {
|
|
||||||
t.Fatalf("addressableData not correct: %v", vc.addressableData)
|
|
||||||
} else if vc.tagType != TypeLong {
|
} else if vc.tagType != TypeLong {
|
||||||
t.Fatalf("tagType not correct: (%d)", vc.tagType)
|
t.Fatalf("tagType not correct: (%d)", vc.tagType)
|
||||||
} else if vc.byteOrder != TestDefaultByteOrder {
|
} else if vc.byteOrder != TestDefaultByteOrder {
|
||||||
t.Fatalf("byteOrder not correct: %v", vc.byteOrder)
|
t.Fatalf("byteOrder not correct: %v", vc.byteOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recoveredBytes, err := ioutil.ReadAll(vc.AddressableData())
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
if bytes.Equal(recoveredBytes, addressableData) != true {
|
||||||
|
t.Fatalf("AddressableData() not correct: %v", recoveredBytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValueContext_SetUndefinedValueType__ErrorWhenNotUndefined(t *testing.T) {
|
func TestValueContext_SetUndefinedValueType__ErrorWhenNotUndefined(t *testing.T) {
|
||||||
@ -47,16 +65,38 @@ func TestValueContext_SetUndefinedValueType__ErrorWhenNotUndefined(t *testing.T)
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeLong, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
vc.SetUndefinedValueType(TypeLong)
|
vc.SetUndefinedValueType(TypeLong)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValueContext_SetUndefinedValueType__Ok(t *testing.T) {
|
func TestValueContext_SetUndefinedValueType__Ok(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
vc.SetUndefinedValueType(TypeLong)
|
vc.SetUndefinedValueType(TypeLong)
|
||||||
|
|
||||||
@ -71,8 +111,19 @@ func TestValueContext_SetUndefinedValueType__Ok(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_effectiveValueType(t *testing.T) {
|
func TestValueContext_effectiveValueType(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
vc.SetUndefinedValueType(TypeLong)
|
vc.SetUndefinedValueType(TypeLong)
|
||||||
|
|
||||||
@ -87,8 +138,19 @@ func TestValueContext_effectiveValueType(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_UnitCount(t *testing.T) {
|
func TestValueContext_UnitCount(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.UnitCount() != 11 {
|
if vc.UnitCount() != 11 {
|
||||||
t.Fatalf("UnitCount() not correct: (%d)", vc.UnitCount())
|
t.Fatalf("UnitCount() not correct: (%d)", vc.UnitCount())
|
||||||
@ -97,8 +159,19 @@ func TestValueContext_UnitCount(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_ValueOffset(t *testing.T) {
|
func TestValueContext_ValueOffset(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.ValueOffset() != 22 {
|
if vc.ValueOffset() != 22 {
|
||||||
t.Fatalf("ValueOffset() not correct: (%d)", vc.ValueOffset())
|
t.Fatalf("ValueOffset() not correct: (%d)", vc.ValueOffset())
|
||||||
@ -107,8 +180,19 @@ func TestValueContext_ValueOffset(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_RawValueOffset(t *testing.T) {
|
func TestValueContext_RawValueOffset(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if bytes.Equal(vc.RawValueOffset(), rawValueOffset) != true {
|
if bytes.Equal(vc.RawValueOffset(), rawValueOffset) != true {
|
||||||
t.Fatalf("RawValueOffset() not correct: %v", vc.RawValueOffset())
|
t.Fatalf("RawValueOffset() not correct: %v", vc.RawValueOffset())
|
||||||
@ -117,18 +201,43 @@ func TestValueContext_RawValueOffset(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_AddressableData(t *testing.T) {
|
func TestValueContext_AddressableData(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
|
||||||
|
|
||||||
if bytes.Equal(vc.AddressableData(), addressableData) != true {
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
t.Fatalf("AddressableData() not correct: %v", vc.AddressableData())
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
|
recoveredBytes, err := ioutil.ReadAll(vc.AddressableData())
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
if bytes.Equal(recoveredBytes, addressableData) != true {
|
||||||
|
t.Fatalf("AddressableData() not correct: %v", recoveredBytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValueContext_ByteOrder(t *testing.T) {
|
func TestValueContext_ByteOrder(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.ByteOrder() != TestDefaultByteOrder {
|
if vc.ByteOrder() != TestDefaultByteOrder {
|
||||||
t.Fatalf("ByteOrder() not correct: %v", vc.ByteOrder())
|
t.Fatalf("ByteOrder() not correct: %v", vc.ByteOrder())
|
||||||
@ -137,8 +246,19 @@ func TestValueContext_ByteOrder(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_IfdPath(t *testing.T) {
|
func TestValueContext_IfdPath(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.IfdPath() != "aa/bb" {
|
if vc.IfdPath() != "aa/bb" {
|
||||||
t.Fatalf("IfdPath() not correct: [%s]", vc.IfdPath())
|
t.Fatalf("IfdPath() not correct: [%s]", vc.IfdPath())
|
||||||
@ -147,8 +267,19 @@ func TestValueContext_IfdPath(t *testing.T) {
|
|||||||
|
|
||||||
func TestValueContext_TagId(t *testing.T) {
|
func TestValueContext_TagId(t *testing.T) {
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, 11, 22, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
11,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.TagId() != 0x1234 {
|
if vc.TagId() != 0x1234 {
|
||||||
t.Fatalf("TagId() not correct: (%d)", vc.TagId())
|
t.Fatalf("TagId() not correct: (%d)", vc.TagId())
|
||||||
@ -158,8 +289,19 @@ func TestValueContext_TagId(t *testing.T) {
|
|||||||
func TestValueContext_isEmbedded__True(t *testing.T) {
|
func TestValueContext_isEmbedded__True(t *testing.T) {
|
||||||
unitCount := uint32(4)
|
unitCount := uint32(4)
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, 22, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.isEmbedded() != true {
|
if vc.isEmbedded() != true {
|
||||||
t.Fatalf("isEmbedded() not correct: %v", vc.isEmbedded())
|
t.Fatalf("isEmbedded() not correct: %v", vc.isEmbedded())
|
||||||
@ -169,8 +311,19 @@ func TestValueContext_isEmbedded__True(t *testing.T) {
|
|||||||
func TestValueContext_isEmbedded__False(t *testing.T) {
|
func TestValueContext_isEmbedded__False(t *testing.T) {
|
||||||
unitCount := uint32(5)
|
unitCount := uint32(5)
|
||||||
rawValueOffset := []byte{0, 0, 0, 22}
|
rawValueOffset := []byte{0, 0, 0, 22}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, 22, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
22,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
if vc.isEmbedded() != false {
|
if vc.isEmbedded() != false {
|
||||||
t.Fatalf("isEmbedded() not correct: %v", vc.isEmbedded())
|
t.Fatalf("isEmbedded() not correct: %v", vc.isEmbedded())
|
||||||
@ -186,7 +339,17 @@ func TestValueContext_readRawEncoded__IsEmbedded(t *testing.T) {
|
|||||||
valueOffset := uint32(0)
|
valueOffset := uint32(0)
|
||||||
|
|
||||||
addressableData := []byte{}
|
addressableData := []byte{}
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
recovered, err := vc.readRawEncoded()
|
recovered, err := vc.readRawEncoded()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -205,10 +368,20 @@ func TestValueContext_readRawEncoded__IsRelative(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{5, 6, 7, 8, 9}
|
data := []byte{5, 6, 7, 8, 9}
|
||||||
|
|
||||||
addressableData := []byte{1, 2, 3, 4}
|
addressableData := []byte{1, 2, 3, 4}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
recovered, err := vc.readRawEncoded()
|
recovered, err := vc.readRawEncoded()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -225,10 +398,20 @@ func TestValueContext_Format__Byte(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -245,10 +428,20 @@ func TestValueContext_Format__Ascii(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAscii, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeAscii,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -265,10 +458,20 @@ func TestValueContext_Format__AsciiNoNul(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAsciiNoNul, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeAsciiNoNul,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -285,10 +488,20 @@ func TestValueContext_Format__Short(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeShort, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeShort,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -305,10 +518,20 @@ func TestValueContext_Format__Long(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeLong, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -331,8 +554,17 @@ func TestValueContext_Format__Rational(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeRational, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeRational,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -349,10 +581,20 @@ func TestValueContext_Format__SignedLong(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedLong, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeSignedLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -375,8 +617,17 @@ func TestValueContext_Format__SignedRational(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedRational, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeSignedRational,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -406,10 +657,20 @@ func TestValueContext_Format__Undefined__NoEffectiveType(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Format()
|
value, err := vc.Format()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -426,10 +687,20 @@ func TestValueContext_Format__Undefined__HasEffectiveType(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeUndefined, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeUndefined,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
vc.SetUndefinedValueType(TypeAscii)
|
vc.SetUndefinedValueType(TypeAscii)
|
||||||
|
|
||||||
@ -448,10 +719,20 @@ func TestValueContext_FormatFirst__Bytes(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.FormatFirst()
|
value, err := vc.FormatFirst()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -468,10 +749,20 @@ func TestValueContext_FormatFirst__String(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAscii, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeAscii,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.FormatFirst()
|
value, err := vc.FormatFirst()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -488,10 +779,20 @@ func TestValueContext_FormatFirst__List(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeShort, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeShort,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.FormatFirst()
|
value, err := vc.FormatFirst()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -510,8 +811,17 @@ func TestValueContext_ReadBytes(t *testing.T) {
|
|||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeByte,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadBytes()
|
value, err := vc.ReadBytes()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -528,10 +838,20 @@ func TestValueContext_ReadAscii(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAscii, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeAscii,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadAscii()
|
value, err := vc.ReadAscii()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -550,8 +870,17 @@ func TestValueContext_ReadAsciiNoNul(t *testing.T) {
|
|||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAsciiNoNul, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeAsciiNoNul,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadAsciiNoNul()
|
value, err := vc.ReadAsciiNoNul()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -568,10 +897,20 @@ func TestValueContext_ReadShorts(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeShort, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeShort,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadShorts()
|
value, err := vc.ReadShorts()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -588,10 +927,20 @@ func TestValueContext_ReadLongs(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeLong, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadLongs()
|
value, err := vc.ReadLongs()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -614,8 +963,17 @@ func TestValueContext_ReadRationals(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeRational, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeRational,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadRationals()
|
value, err := vc.ReadRationals()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -637,10 +995,20 @@ func TestValueContext_ReadSignedLongs(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedLong, TestDefaultByteOrder)
|
vc := NewValueContext(
|
||||||
|
"aa/bb",
|
||||||
|
0x1234,
|
||||||
|
unitCount,
|
||||||
|
valueOffset,
|
||||||
|
rawValueOffset,
|
||||||
|
sb,
|
||||||
|
TypeSignedLong,
|
||||||
|
TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadSignedLongs()
|
value, err := vc.ReadSignedLongs()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -663,8 +1031,9 @@ func TestValueContext_ReadSignedRationals(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedRational, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeSignedRational, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.ReadSignedRationals()
|
value, err := vc.ReadSignedRationals()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -686,10 +1055,12 @@ func TestValueContext_Values__Byte(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeByte, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeByte, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -706,10 +1077,12 @@ func TestValueContext_Values__Ascii(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAscii, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeAscii, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -726,10 +1099,12 @@ func TestValueContext_Values__AsciiNoNul(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
data := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeAsciiNoNul, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeAsciiNoNul, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -746,10 +1121,12 @@ func TestValueContext_Values__Short(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
data := []byte{0, 1, 0, 2, 0, 3, 0, 4}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeShort, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeShort, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -766,10 +1143,12 @@ func TestValueContext_Values__Long(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeLong, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeLong, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -792,8 +1171,9 @@ func TestValueContext_Values__Rational(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeRational, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeRational, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -815,10 +1195,12 @@ func TestValueContext_Values__SignedLong(t *testing.T) {
|
|||||||
valueOffset := uint32(4)
|
valueOffset := uint32(4)
|
||||||
|
|
||||||
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
data := []byte{0, 0, 0, 1, 0, 0, 0, 2}
|
||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedLong, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeSignedLong, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -841,8 +1223,9 @@ func TestValueContext_Values__SignedRational(t *testing.T) {
|
|||||||
|
|
||||||
addressableData := []byte{0, 0, 0, 0}
|
addressableData := []byte{0, 0, 0, 0}
|
||||||
addressableData = append(addressableData, data...)
|
addressableData = append(addressableData, data...)
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, addressableData, TypeSignedRational, TestDefaultByteOrder)
|
vc := NewValueContext("aa/bb", 0x1234, unitCount, valueOffset, rawValueOffset, sb, TypeSignedRational, TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := vc.Values()
|
value, err := vc.Values()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
50
v3/data_layer.go
Normal file
50
v3/data_layer.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package exif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExifBlobSeeker interface {
|
||||||
|
GetReadSeeker(initialOffset int64) (rs io.ReadSeeker, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExifReadSeeker knows how to retrieve data from the EXIF blob relative to the
|
||||||
|
// beginning of the blob (so, absolute position (0) is the first byte of the
|
||||||
|
// EXIF data).
|
||||||
|
type ExifReadSeeker struct {
|
||||||
|
rs io.ReadSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExifReadSeeker(rs io.ReadSeeker) *ExifReadSeeker {
|
||||||
|
return &ExifReadSeeker{
|
||||||
|
rs: rs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExifReadSeekerWithBytes(exifData []byte) *ExifReadSeeker {
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(exifData)
|
||||||
|
edbs := NewExifReadSeeker(sb)
|
||||||
|
|
||||||
|
return edbs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fork creates a new ReadSeeker instead that wraps a BouncebackReader to
|
||||||
|
// maintain its own position in the stream.
|
||||||
|
func (edbs *ExifReadSeeker) GetReadSeeker(initialOffset int64) (rs io.ReadSeeker, err error) {
|
||||||
|
defer func() {
|
||||||
|
if state := recover(); state != nil {
|
||||||
|
err = log.Wrap(state.(error))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
br, err := rifs.NewBouncebackReader(edbs.rs)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
_, err = br.Seek(initialOffset, io.SeekStart)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
return br, nil
|
||||||
|
}
|
@ -202,7 +202,8 @@ func Visit(rootIfdIdentity *exifcommon.IfdIdentity, ifdMapping *exifcommon.IfdMa
|
|||||||
eh, err = ParseExifHeader(exifData)
|
eh, err = ParseExifHeader(exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ie := NewIfdEnumerate(ifdMapping, tagIndex, exifData, eh.ByteOrder)
|
ebs := NewExifReadSeekerWithBytes(exifData)
|
||||||
|
ie := NewIfdEnumerate(ifdMapping, tagIndex, ebs, eh.ByteOrder)
|
||||||
|
|
||||||
_, err = ie.Scan(rootIfdIdentity, eh.FirstIfdOffset, visitor)
|
_, err = ie.Scan(rootIfdIdentity, eh.FirstIfdOffset, visitor)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -223,7 +224,8 @@ func Collect(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, exifData []b
|
|||||||
eh, err = ParseExifHeader(exifData)
|
eh, err = ParseExifHeader(exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ie := NewIfdEnumerate(ifdMapping, tagIndex, exifData, eh.ByteOrder)
|
ebs := NewExifReadSeekerWithBytes(exifData)
|
||||||
|
ie := NewIfdEnumerate(ifdMapping, tagIndex, ebs, eh.ByteOrder)
|
||||||
|
|
||||||
index, err = ie.Collect(eh.FirstIfdOffset)
|
index, err = ie.Collect(eh.FirstIfdOffset)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
@ -43,6 +43,8 @@ func TestVisit(t *testing.T) {
|
|||||||
// Search for the beginning of the EXIF information. The EXIF is near the
|
// Search for the beginning of the EXIF information. The EXIF is near the
|
||||||
// very beginning of our/most JPEGs, so this has a very low cost.
|
// very beginning of our/most JPEGs, so this has a very low cost.
|
||||||
|
|
||||||
|
// TODO(dustin): Just use SearchAndExtractExifWithReader() here.
|
||||||
|
|
||||||
foundAt := -1
|
foundAt := -1
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
if _, err := ParseExifHeader(data[i:]); err == nil {
|
if _, err := ParseExifHeader(data[i:]); err == nil {
|
||||||
@ -416,5 +418,6 @@ func ExampleBuildExifHeader() {
|
|||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
fmt.Printf("%v\n", eh)
|
fmt.Printf("%v\n", eh)
|
||||||
|
|
||||||
// Output: ExifHeader<BYTE-ORDER=[BigEndian] FIRST-IFD-OFFSET=(0x11223344)>
|
// Output: ExifHeader<BYTE-ORDER=[BigEndian] FIRST-IFD-OFFSET=(0x11223344)>
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ go 1.13
|
|||||||
|
|
||||||
// Development only
|
// Development only
|
||||||
// replace github.com/dsoprea/go-logging => ../../go-logging
|
// replace github.com/dsoprea/go-logging => ../../go-logging
|
||||||
|
replace github.com/dsoprea/go-utility => ../../go-utility
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d
|
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d
|
||||||
|
github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176
|
||||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d
|
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d
|
||||||
github.com/jessevdk/go-flags v1.4.0
|
github.com/jessevdk/go-flags v1.4.0
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 // indirect
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 // indirect
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
|
||||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
|
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
|
||||||
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200502191043-ec333ec7635f h1:XM9MVftaUNA4CcjV97+4bSy7u9Ns04DEYbZkswUrRtc=
|
github.com/dsoprea/go-logging v0.0.0-20200502191043-ec333ec7635f h1:XM9MVftaUNA4CcjV97+4bSy7u9Ns04DEYbZkswUrRtc=
|
||||||
@ -6,6 +7,8 @@ github.com/dsoprea/go-logging v0.0.0-20200502201358-170ff607885f h1:FonKAuW3PmNt
|
|||||||
github.com/dsoprea/go-logging v0.0.0-20200502201358-170ff607885f/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
github.com/dsoprea/go-logging v0.0.0-20200502201358-170ff607885f/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d h1:F/7L5wr/fP/SKeO5HuMlNEX9Ipyx2MbH2rV9G4zJRpk=
|
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d h1:F/7L5wr/fP/SKeO5HuMlNEX9Ipyx2MbH2rV9G4zJRpk=
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
|
||||||
|
github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176 h1:CfXezFYb2STGOd1+n1HshvE191zVx+QX3A1nML5xxME=
|
||||||
|
github.com/dsoprea/go-utility v0.0.0-20200512094054-1abbbc781176/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
|
||||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4=
|
github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4=
|
||||||
@ -19,6 +22,7 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY=
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -75,22 +76,22 @@ var (
|
|||||||
// are fairly simple to enumerate.
|
// are fairly simple to enumerate.
|
||||||
type byteParser struct {
|
type byteParser struct {
|
||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
addressableData []byte
|
rs io.ReadSeeker
|
||||||
ifdOffset uint32
|
ifdOffset uint32
|
||||||
currentOffset uint32
|
currentOffset uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newByteParser(addressableData []byte, byteOrder binary.ByteOrder, ifdOffset uint32) (bp *byteParser, err error) {
|
// newByteParser returns a new byteParser struct.
|
||||||
if ifdOffset >= uint32(len(addressableData)) {
|
//
|
||||||
return nil, ErrOffsetInvalid
|
// initialOffset is for arithmetic-based tracking of where we should be at in
|
||||||
}
|
// the stream.
|
||||||
|
func newByteParser(rs io.ReadSeeker, byteOrder binary.ByteOrder, initialOffset uint32) (bp *byteParser, err error) {
|
||||||
// TODO(dustin): Add test
|
// TODO(dustin): Add test
|
||||||
|
|
||||||
bp = &byteParser{
|
bp = &byteParser{
|
||||||
addressableData: addressableData,
|
rs: rs,
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
currentOffset: ifdOffset,
|
currentOffset: initialOffset,
|
||||||
}
|
}
|
||||||
|
|
||||||
return bp, nil
|
return bp, nil
|
||||||
@ -110,11 +111,11 @@ func (bp *byteParser) getUint16() (value uint16, raw []byte, err error) {
|
|||||||
|
|
||||||
needBytes := 2
|
needBytes := 2
|
||||||
|
|
||||||
if bp.currentOffset+needBytes >= len(bp.addressableData) {
|
raw = make([]byte, needBytes)
|
||||||
return 0, nil, io.EOF
|
|
||||||
}
|
_, err = io.ReadFull(bp.rs, raw)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
raw = addressableData[bp.currentOffset : bp.currentOffset+needBytes]
|
|
||||||
value = bp.byteOrder.Uint16(raw)
|
value = bp.byteOrder.Uint16(raw)
|
||||||
|
|
||||||
bp.currentOffset += uint32(needBytes)
|
bp.currentOffset += uint32(needBytes)
|
||||||
@ -136,12 +137,12 @@ func (bp *byteParser) getUint32() (value uint32, raw []byte, err error) {
|
|||||||
|
|
||||||
needBytes := 4
|
needBytes := 4
|
||||||
|
|
||||||
if bp.currentOffset+needBytes >= len(bp.addressableData) {
|
raw = make([]byte, needBytes)
|
||||||
return 0, nil, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
raw = addressableData[bp.currentOffset : bp.currentOffset+needBytes]
|
_, err = io.ReadFull(bp.rs, raw)
|
||||||
value = bp.byteOrder.Uint16(raw)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
value = bp.byteOrder.Uint32(raw)
|
||||||
|
|
||||||
bp.currentOffset += uint32(needBytes)
|
bp.currentOffset += uint32(needBytes)
|
||||||
|
|
||||||
@ -157,7 +158,7 @@ func (bp *byteParser) CurrentOffset() uint32 {
|
|||||||
// IfdEnumerate is the main enumeration type. It knows how to parse the IFD
|
// IfdEnumerate is the main enumeration type. It knows how to parse the IFD
|
||||||
// containers in the EXIF blob.
|
// containers in the EXIF blob.
|
||||||
type IfdEnumerate struct {
|
type IfdEnumerate struct {
|
||||||
exifData []byte
|
ebs ExifBlobSeeker
|
||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
tagIndex *TagIndex
|
tagIndex *TagIndex
|
||||||
ifdMapping *exifcommon.IfdMapping
|
ifdMapping *exifcommon.IfdMapping
|
||||||
@ -165,9 +166,9 @@ type IfdEnumerate struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewIfdEnumerate returns a new instance of IfdEnumerate.
|
// NewIfdEnumerate returns a new instance of IfdEnumerate.
|
||||||
func NewIfdEnumerate(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, exifData []byte, byteOrder binary.ByteOrder) *IfdEnumerate {
|
func NewIfdEnumerate(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, ebs ExifBlobSeeker, byteOrder binary.ByteOrder) *IfdEnumerate {
|
||||||
return &IfdEnumerate{
|
return &IfdEnumerate{
|
||||||
exifData: exifData,
|
ebs: ebs,
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
ifdMapping: ifdMapping,
|
ifdMapping: ifdMapping,
|
||||||
tagIndex: tagIndex,
|
tagIndex: tagIndex,
|
||||||
@ -181,11 +182,16 @@ func (ie *IfdEnumerate) getByteParser(ifdOffset uint32) (bp *byteParser, err err
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
initialOffset := ExifAddressableAreaStart + ifdOffset
|
||||||
|
|
||||||
|
rs, err := ie.ebs.GetReadSeeker(int64(initialOffset))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
bp, err =
|
bp, err =
|
||||||
newByteParser(
|
newByteParser(
|
||||||
ie.exifData[ExifAddressableAreaStart:],
|
rs,
|
||||||
ie.byteOrder,
|
ie.byteOrder,
|
||||||
ifdOffset)
|
initialOffset)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrOffsetInvalid {
|
if err == ErrOffsetInvalid {
|
||||||
@ -228,6 +234,9 @@ func (ie *IfdEnumerate) parseTag(ii *exifcommon.IfdIdentity, tagPosition int, bp
|
|||||||
log.Panic(ErrTagTypeNotValid)
|
log.Panic(ErrTagTypeNotValid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs, err := ie.ebs.GetReadSeeker(0)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
ite = newIfdTagEntry(
|
ite = newIfdTagEntry(
|
||||||
ii,
|
ii,
|
||||||
tagId,
|
tagId,
|
||||||
@ -236,7 +245,7 @@ func (ie *IfdEnumerate) parseTag(ii *exifcommon.IfdIdentity, tagPosition int, bp
|
|||||||
unitCount,
|
unitCount,
|
||||||
valueOffset,
|
valueOffset,
|
||||||
rawValueOffset,
|
rawValueOffset,
|
||||||
ie.exifData[ExifAddressableAreaStart:],
|
rs,
|
||||||
ie.byteOrder)
|
ie.byteOrder)
|
||||||
|
|
||||||
ifdPath := ii.UnindexedString()
|
ifdPath := ii.UnindexedString()
|
||||||
@ -266,8 +275,8 @@ func (ie *IfdEnumerate) parseTag(ii *exifcommon.IfdIdentity, tagPosition int, bp
|
|||||||
// TagVisitorFn is called for each tag when enumerating through the EXIF.
|
// TagVisitorFn is called for each tag when enumerating through the EXIF.
|
||||||
type TagVisitorFn func(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error)
|
type TagVisitorFn func(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error)
|
||||||
|
|
||||||
// postparseTag do some tag-level processing here following the parse of each.
|
// tagPostParse do some tag-level processing here following the parse of each.
|
||||||
func (ie *IfdEnumerate) postparseTag(ite *IfdTagEntry, med *MiscellaneousExifData) (err error) {
|
func (ie *IfdEnumerate) tagPostParse(ite *IfdTagEntry, med *MiscellaneousExifData) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if state := recover(); state != nil {
|
if state := recover(); state != nil {
|
||||||
err = log.Wrap(state.(error))
|
err = log.Wrap(state.(error))
|
||||||
@ -401,7 +410,7 @@ func (ie *IfdEnumerate) parseIfd(ii *exifcommon.IfdIdentity, bp *byteParser, vis
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ie.postparseTag(ite, med)
|
err = ie.tagPostParse(ite, med)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err == ErrTagNotFound {
|
if err == ErrTagNotFound {
|
||||||
continue
|
continue
|
||||||
@ -1382,9 +1391,16 @@ func ParseOneIfd(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, ii *exif
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ie := NewIfdEnumerate(ifdMapping, tagIndex, make([]byte, 0), byteOrder)
|
// TODO(dustin): Add test
|
||||||
|
|
||||||
bp, err := newByteParser(ifdBlock, byteOrder, 0)
|
// RELEASE(dustin): Stop exporting this. Just supports tests.
|
||||||
|
|
||||||
|
ebs := NewExifReadSeekerWithBytes(ifdBlock)
|
||||||
|
|
||||||
|
rs, err := ebs.GetReadSeeker(0)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bp, err := newByteParser(rs, byteOrder, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrOffsetInvalid {
|
if err == ErrOffsetInvalid {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
@ -1393,6 +1409,9 @@ func ParseOneIfd(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, ii *exif
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dummyEbs := NewExifReadSeekerWithBytes([]byte{})
|
||||||
|
ie := NewIfdEnumerate(ifdMapping, tagIndex, dummyEbs, byteOrder)
|
||||||
|
|
||||||
nextIfdOffset, entries, _, err = ie.parseIfd(ii, bp, visitor, true, nil)
|
nextIfdOffset, entries, _, err = ie.parseIfd(ii, bp, visitor, true, nil)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -1407,9 +1426,16 @@ func ParseOneTag(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, ii *exif
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ie := NewIfdEnumerate(ifdMapping, tagIndex, make([]byte, 0), byteOrder)
|
// TODO(dustin): Add test
|
||||||
|
|
||||||
bp, err := newByteParser(tagBlock, byteOrder, 0)
|
// RELEASE(dustin): Stop exporting this. Just supports tests.
|
||||||
|
|
||||||
|
ebs := NewExifReadSeekerWithBytes(tagBlock)
|
||||||
|
|
||||||
|
rs, err := ebs.GetReadSeeker(0)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bp, err := newByteParser(rs, byteOrder, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrOffsetInvalid {
|
if err == ErrOffsetInvalid {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1418,10 +1444,13 @@ func ParseOneTag(ifdMapping *exifcommon.IfdMapping, tagIndex *TagIndex, ii *exif
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dummyEbs := NewExifReadSeekerWithBytes([]byte{})
|
||||||
|
ie := NewIfdEnumerate(ifdMapping, tagIndex, dummyEbs, byteOrder)
|
||||||
|
|
||||||
ite, err = ie.parseTag(ii, 0, bp)
|
ite, err = ie.parseTag(ii, 0, bp)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ie.postparseTag(ite, nil)
|
err = ie.tagPostParse(ite, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrTagNotFound {
|
if err == ErrTagNotFound {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2,6 +2,7 @@ package exif
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
@ -42,13 +43,13 @@ type IfdTagEntry struct {
|
|||||||
|
|
||||||
isUnhandledUnknown bool
|
isUnhandledUnknown bool
|
||||||
|
|
||||||
addressableData []byte
|
rs io.ReadSeeker
|
||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
|
|
||||||
tagName string
|
tagName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIfdTagEntry(ii *exifcommon.IfdIdentity, tagId uint16, tagIndex int, tagType exifcommon.TagTypePrimitive, unitCount uint32, valueOffset uint32, rawValueOffset []byte, addressableData []byte, byteOrder binary.ByteOrder) *IfdTagEntry {
|
func newIfdTagEntry(ii *exifcommon.IfdIdentity, tagId uint16, tagIndex int, tagType exifcommon.TagTypePrimitive, unitCount uint32, valueOffset uint32, rawValueOffset []byte, rs io.ReadSeeker, byteOrder binary.ByteOrder) *IfdTagEntry {
|
||||||
return &IfdTagEntry{
|
return &IfdTagEntry{
|
||||||
ifdIdentity: ii,
|
ifdIdentity: ii,
|
||||||
tagId: tagId,
|
tagId: tagId,
|
||||||
@ -57,7 +58,7 @@ func newIfdTagEntry(ii *exifcommon.IfdIdentity, tagId uint16, tagIndex int, tagT
|
|||||||
unitCount: unitCount,
|
unitCount: unitCount,
|
||||||
valueOffset: valueOffset,
|
valueOffset: valueOffset,
|
||||||
rawValueOffset: rawValueOffset,
|
rawValueOffset: rawValueOffset,
|
||||||
addressableData: addressableData,
|
rs: rs,
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,7 +292,7 @@ func (ite *IfdTagEntry) getValueContext() *exifcommon.ValueContext {
|
|||||||
ite.unitCount,
|
ite.unitCount,
|
||||||
ite.valueOffset,
|
ite.valueOffset,
|
||||||
ite.rawValueOffset,
|
ite.rawValueOffset,
|
||||||
ite.addressableData,
|
ite.rs,
|
||||||
ite.tagType,
|
ite.tagType,
|
||||||
ite.byteOrder)
|
ite.byteOrder)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -13,6 +14,7 @@ func TestIfdTagEntry_RawBytes_Allocated(t *testing.T) {
|
|||||||
data := []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
|
data := []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
|
||||||
|
|
||||||
addressableBytes := data
|
addressableBytes := data
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableBytes)
|
||||||
|
|
||||||
ite := newIfdTagEntry(
|
ite := newIfdTagEntry(
|
||||||
exifcommon.IfdStandardIfdIdentity,
|
exifcommon.IfdStandardIfdIdentity,
|
||||||
@ -22,7 +24,7 @@ func TestIfdTagEntry_RawBytes_Allocated(t *testing.T) {
|
|||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableBytes,
|
sb,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
value, err := ite.GetRawBytes()
|
value, err := ite.GetRawBytes()
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -59,6 +60,7 @@ func TestCodec8828Oecf_Decode(t *testing.T) {
|
|||||||
0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x16}
|
0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x16}
|
||||||
|
|
||||||
addressableData := encoded
|
addressableData := encoded
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableData)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
@ -66,7 +68,7 @@ func TestCodec8828Oecf_Decode(t *testing.T) {
|
|||||||
uint32(len(encoded)),
|
uint32(len(encoded)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableData,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -51,13 +52,15 @@ func TestCodec927CMakerNote_Decode(t *testing.T) {
|
|||||||
MakerNoteBytes: b,
|
MakerNoteBytes: b,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(b)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
uint32(len(b)),
|
uint32(len(b)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
b,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -65,6 +66,7 @@ func TestCodec9286UserComment_Decode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addressableBytes := encoded
|
addressableBytes := encoded
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableBytes)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
@ -72,7 +74,7 @@ func TestCodec9286UserComment_Decode(t *testing.T) {
|
|||||||
uint32(len(encoded)),
|
uint32(len(encoded)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableBytes,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -48,6 +49,7 @@ func TestCodecA000FlashpixVersion_Decode(t *testing.T) {
|
|||||||
encoded := []byte(versionPhrase)
|
encoded := []byte(versionPhrase)
|
||||||
|
|
||||||
addressableBytes := encoded
|
addressableBytes := encoded
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableBytes)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
@ -55,7 +57,7 @@ func TestCodecA000FlashpixVersion_Decode(t *testing.T) {
|
|||||||
uint32(len(encoded)),
|
uint32(len(encoded)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableBytes,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
@ -82,6 +83,7 @@ func TestCodecA20CSpatialFrequencyResponse_Decode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addressableBytes := encoded
|
addressableBytes := encoded
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableBytes)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
@ -89,7 +91,7 @@ func TestCodecA20CSpatialFrequencyResponse_Decode(t *testing.T) {
|
|||||||
uint32(len(encoded)),
|
uint32(len(encoded)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableBytes,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -5,8 +5,10 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
"github.com/dsoprea/go-utility/filesystem"
|
||||||
|
|
||||||
|
"github.com/dsoprea/go-exif/v2/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTagA302CfaPattern_String(t *testing.T) {
|
func TestTagA302CfaPattern_String(t *testing.T) {
|
||||||
@ -63,7 +65,8 @@ func TestCodecA302CfaPattern_Decode(t *testing.T) {
|
|||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||||
}
|
}
|
||||||
|
|
||||||
addressableData := encoded
|
addressableBytes := encoded
|
||||||
|
sb := rifs.NewSeekableBufferWithBytes(addressableBytes)
|
||||||
|
|
||||||
valueContext := exifcommon.NewValueContext(
|
valueContext := exifcommon.NewValueContext(
|
||||||
"",
|
"",
|
||||||
@ -71,7 +74,7 @@ func TestCodecA302CfaPattern_Decode(t *testing.T) {
|
|||||||
uint32(len(encoded)),
|
uint32(len(encoded)),
|
||||||
0,
|
0,
|
||||||
nil,
|
nil,
|
||||||
addressableData,
|
sb,
|
||||||
exifcommon.TypeUndefined,
|
exifcommon.TypeUndefined,
|
||||||
exifcommon.TestDefaultByteOrder)
|
exifcommon.TestDefaultByteOrder)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package exif
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -151,7 +152,8 @@ func GetFlatExifData(exifData []byte) (exifTags []ExifTag, err error) {
|
|||||||
im := NewIfdMappingWithStandard()
|
im := NewIfdMappingWithStandard()
|
||||||
ti := NewTagIndex()
|
ti := NewTagIndex()
|
||||||
|
|
||||||
ie := NewIfdEnumerate(im, ti, exifData, eh.ByteOrder)
|
ebs := NewExifReadSeekerWithBytes(exifData)
|
||||||
|
ie := NewIfdEnumerate(im, ti, ebs, eh.ByteOrder)
|
||||||
|
|
||||||
exifTags = make([]ExifTag, 0)
|
exifTags = make([]ExifTag, 0)
|
||||||
|
|
||||||
@ -232,3 +234,11 @@ func GpsDegreesEquals(gi1, gi2 GpsDegrees) bool {
|
|||||||
func IsTime(v interface{}) bool {
|
func IsTime(v interface{}) bool {
|
||||||
return reflect.TypeOf(v) == timeType
|
return reflect.TypeOf(v) == timeType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dustin): !! For debugging
|
||||||
|
func mustGetCurrentOffset(s io.Seeker) int64 {
|
||||||
|
offset, err := s.Seek(0, io.SeekCurrent)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user