diff --git a/ifd_enumerate.go b/ifd_enumerate.go index c56c906..b088971 100644 --- a/ifd_enumerate.go +++ b/ifd_enumerate.go @@ -210,6 +210,18 @@ func (ie *IfdEnumerate) parseTag(fqIfdPath string, tagPosition int, ite *IfdTagE return tag, nil } +func (ie *IfdEnumerate) GetValueContext(ite *IfdTagEntry) *ValueContext { + + // TODO(dustin): Add test + + addressableData := ie.exifData[ExifAddressableAreaStart:] + + return newValueContextFromTag( + ite, + addressableData, + ie.byteOrder) +} + func (ie *IfdEnumerate) resolveTagValue(ite *IfdTagEntry) (valueBytes []byte, isUnhandledUnknown bool, err error) { defer func() { if state := recover(); state != nil { @@ -225,15 +237,7 @@ func (ie *IfdEnumerate) resolveTagValue(ite *IfdTagEntry) (valueBytes []byte, is // (obviously). However, here, in order to produce the list of bytes, we // need to coerce whatever `UndefinedValue()` returns. if ite.TagType == TypeUndefined { - valueContext := - newValueContext( - ite.UnitCount, - ite.ValueOffset, - ite.RawValueOffset, - addressableData, - ite.TagType, - ie.byteOrder, - ) + valueContext := ie.GetValueContext(ite) value, err := UndefinedValue(ite.IfdPath, ite.TagId, valueContext, ie.byteOrder) if err != nil { @@ -372,16 +376,9 @@ func (ie *IfdEnumerate) ParseIfd(fqIfdPath string, ifdIndex int, ite *IfdTagEnum if visitorWrapper != nil { tt := NewTagType(tag.TagType, ie.byteOrder) - vc := - newValueContext( - tag.UnitCount, - tag.ValueOffset, - tag.RawValueOffset, - ie.exifData[ExifAddressableAreaStart:], - tag.TagType, - ie.byteOrder) + valueContext := ie.GetValueContext(tag) - err := visitorWrapper.Visit(fqIfdPath, ifdIndex, tag.TagId, tt, vc) + err := visitorWrapper.Visit(fqIfdPath, ifdIndex, tag.TagId, tt, valueContext) log.PanicIf(err) } diff --git a/ifd_tag_entry.go b/ifd_tag_entry.go index 7519b4a..89902c1 100644 --- a/ifd_tag_entry.go +++ b/ifd_tag_entry.go @@ -43,34 +43,31 @@ type IfdTagEntry struct { isUnhandledUnknown bool } -func (ite IfdTagEntry) String() string { +func (ite *IfdTagEntry) String() string { return fmt.Sprintf("IfdTagEntry", ite.IfdPath, ite.TagId, TypeNames[ite.TagType], ite.UnitCount) } // ValueString renders a string from whatever the value in this tag is. -func (ite IfdTagEntry) ValueString(addressableData []byte, byteOrder binary.ByteOrder) (value string, err error) { +func (ite *IfdTagEntry) ValueString(addressableData []byte, byteOrder binary.ByteOrder) (value string, err error) { defer func() { if state := recover(); state != nil { err = log.Wrap(state.(error)) } }() - vc := - newValueContext( - ite.UnitCount, - ite.ValueOffset, - ite.RawValueOffset, + valueContext := + newValueContextFromTag( + ite, addressableData, - ite.TagType, byteOrder) if ite.TagType == TypeUndefined { - valueRaw, err := UndefinedValue(ite.IfdPath, ite.TagId, vc, byteOrder) + valueRaw, err := UndefinedValue(ite.IfdPath, ite.TagId, valueContext, byteOrder) log.PanicIf(err) value = fmt.Sprintf("%v", valueRaw) } else { - value, err = vc.Format() + value, err = valueContext.Format() log.PanicIf(err) } @@ -78,7 +75,7 @@ func (ite IfdTagEntry) ValueString(addressableData []byte, byteOrder binary.Byte } // ValueBytes renders a specific list of bytes from the value in this tag. -func (ite IfdTagEntry) ValueBytes(addressableData []byte, byteOrder binary.ByteOrder) (value []byte, err error) { +func (ite *IfdTagEntry) ValueBytes(addressableData []byte, byteOrder binary.ByteOrder) (value []byte, err error) { defer func() { if state := recover(); state != nil { err = log.Wrap(state.(error)) @@ -92,12 +89,9 @@ func (ite IfdTagEntry) ValueBytes(addressableData []byte, byteOrder binary.ByteO // need to coerce whatever `UndefinedValue()` returns. if ite.TagType == TypeUndefined { valueContext := - newValueContext( - ite.UnitCount, - ite.ValueOffset, - ite.RawValueOffset, + newValueContextFromTag( + ite, addressableData, - ite.TagType, byteOrder) value, err := UndefinedValue(ite.IfdPath, ite.TagId, valueContext, byteOrder) @@ -145,29 +139,26 @@ func (ite IfdTagEntry) ValueBytes(addressableData []byte, byteOrder binary.ByteO } // Value returns the specific, parsed, typed value from the tag. -func (ite IfdTagEntry) Value(addressableData []byte, byteOrder binary.ByteOrder) (value interface{}, err error) { +func (ite *IfdTagEntry) Value(addressableData []byte, byteOrder binary.ByteOrder) (value interface{}, err error) { defer func() { if state := recover(); state != nil { err = log.Wrap(state.(error)) } }() - vc := - newValueContext( - ite.UnitCount, - ite.ValueOffset, - ite.RawValueOffset, + valueContext := + newValueContextFromTag( + ite, addressableData, - ite.TagType, byteOrder) if ite.TagType == TypeUndefined { - value, err = UndefinedValue(ite.IfdPath, ite.TagId, vc, byteOrder) + value, err = UndefinedValue(ite.IfdPath, ite.TagId, valueContext, byteOrder) log.PanicIf(err) } else { tt := NewTagType(ite.TagType, byteOrder) - value, err = tt.Resolve(vc) + value, err = tt.Resolve(valueContext) log.PanicIf(err) } diff --git a/value_context.go b/value_context.go index 4c187dc..3d3f044 100644 --- a/value_context.go +++ b/value_context.go @@ -28,9 +28,12 @@ type ValueContext struct { // undefinedValueUnitCount is the effective unit-count to use if this is an // "undefined" value. undefinedValueUnitCount uint32 + + ifdPath string + tagId uint16 } -func newValueContext(unitCount, valueOffset uint32, rawValueOffset, addressableData []byte, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext { +func newValueContext(ifdPath string, tagId uint16, unitCount, valueOffset uint32, rawValueOffset, addressableData []byte, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext { return &ValueContext{ unitCount: unitCount, valueOffset: valueOffset, @@ -39,9 +42,24 @@ func newValueContext(unitCount, valueOffset uint32, rawValueOffset, addressableD tagType: tagType, byteOrder: byteOrder, + + ifdPath: ifdPath, + tagId: tagId, } } +func newValueContextFromTag(ite *IfdTagEntry, addressableData []byte, byteOrder binary.ByteOrder) *ValueContext { + return newValueContext( + ite.IfdPath, + ite.TagId, + ite.UnitCount, + ite.ValueOffset, + ite.RawValueOffset, + addressableData, + ite.TagType, + byteOrder) +} + func (vc *ValueContext) SetUnknownValueParameters(tagType TagTypePrimitive, unitCount uint32) { vc.undefinedValueTagType = tagType vc.undefinedValueUnitCount = unitCount