value_context.go: We now store the IFD-path and tag-ID on the value-context

This allows us to add an API for accessing an undefined-value/structure
directly on ValueContext.

- ifd_tag_entry.go: Fixed several methods on `IfdTagEntry` to be by-
  reference. It was a latent bug that they weren't.

- value_context.go: Added `newValueContextFromTag` to streamline
  the changes above.
pull/28/head
Dustin Oprea 2019-12-31 06:09:35 -05:00
parent e6b94637a3
commit 71b242c269
3 changed files with 50 additions and 44 deletions

View File

@ -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)
}

View File

@ -43,34 +43,31 @@ type IfdTagEntry struct {
isUnhandledUnknown bool
}
func (ite IfdTagEntry) String() string {
func (ite *IfdTagEntry) String() string {
return fmt.Sprintf("IfdTagEntry<TAG-IFD-PATH=[%s] TAG-ID=(0x%04x) TAG-TYPE=[%s] UNIT-COUNT=(%d)>", 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)
}

View File

@ -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