mirror of https://github.com/dsoprea/go-exif.git
Visit interface now just gets the ITE struct
That, rather than just a couple of values from it. Primarily because we want to not have callers involve themselves with the value context unless they want to. - ifd_tag_entry.go: ITEs now provide `Format()` and `FormatFirst()` methods. - We dumped several spots of code that could just reuse functions to format, decode, or get raw bytes rather than dealing with undefined vs not undefined logic themselves. - This is now possible due to prior change. - ifd_tag_entry.go: No longer exports GetValueContext(). Users shouldn't usually have to touch it, now. - Added some commenting. This commit almost represents everything we have been trying to achieve, now made possible by the last several commits.for/master
parent
1bdfa9b10e
commit
173d686dd9
|
@ -13,17 +13,16 @@ import (
|
|||
"github.com/dsoprea/go-logging"
|
||||
|
||||
"github.com/dsoprea/go-exif/v2/common"
|
||||
"github.com/dsoprea/go-exif/v2/undefined"
|
||||
)
|
||||
|
||||
type innerVisitorCall func(fqIfdPath string, ifdIndex int, tagId uint16, tagType exifcommon.TagTypePrimitive, valueContext *exifcommon.ValueContext) (err error)
|
||||
type innerVisitorCall func(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error)
|
||||
|
||||
type visitorWrapper struct {
|
||||
f innerVisitorCall
|
||||
}
|
||||
|
||||
func (vw *visitorWrapper) Visit(fqIfdPath string, ifdIndex int, tagId uint16, tagType exifcommon.TagTypePrimitive, valueContext *exifcommon.ValueContext) (err error) {
|
||||
return vw.f(fqIfdPath, ifdIndex, tagId, tagType, valueContext)
|
||||
func (vw *visitorWrapper) Visit(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error) {
|
||||
return vw.f(fqIfdPath, ifdIndex, ite)
|
||||
}
|
||||
|
||||
func TestVisit(t *testing.T) {
|
||||
|
@ -71,7 +70,7 @@ func TestVisit(t *testing.T) {
|
|||
|
||||
tags := make([]string, 0)
|
||||
|
||||
visitor := func(fqIfdPath string, ifdIndex int, tagId uint16, tagType exifcommon.TagTypePrimitive, valueContext *exifcommon.ValueContext) (err error) {
|
||||
visitor := func(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
|
@ -79,6 +78,9 @@ func TestVisit(t *testing.T) {
|
|||
}
|
||||
}()
|
||||
|
||||
tagId := ite.TagId()
|
||||
tagType := ite.TagType()
|
||||
|
||||
ifdPath, err := im.StripPathPhraseIndices(fqIfdPath)
|
||||
log.PanicIf(err)
|
||||
|
||||
|
@ -92,26 +94,10 @@ func TestVisit(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
valueString := ""
|
||||
if tagType == exifcommon.TypeUndefined {
|
||||
value, err := exifundefined.Decode(valueContext)
|
||||
if err != nil {
|
||||
if err == exifcommon.ErrUnhandledUnknownTypedTag {
|
||||
valueString = "!UNDEFINED!"
|
||||
} else {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
valueString, err := ite.FormatFirst()
|
||||
log.PanicIf(err)
|
||||
|
||||
valueString = fmt.Sprintf("%v", value)
|
||||
} else {
|
||||
var err error
|
||||
|
||||
valueString, err = valueContext.FormatFirst()
|
||||
log.PanicIf(err)
|
||||
}
|
||||
|
||||
description := fmt.Sprintf("IFD-PATH=[%s] ID=(0x%04x) NAME=[%s] COUNT=(%d) TYPE=[%s] VALUE=[%s]", ifdPath, tagId, it.Name, valueContext.UnitCount(), tagType.String(), valueString)
|
||||
description := fmt.Sprintf("IFD-PATH=[%s] ID=(0x%04x) NAME=[%s] COUNT=(%d) TYPE=[%s] VALUE=[%s]", ifdPath, tagId, it.Name, ite.UnitCount(), tagType.String(), valueString)
|
||||
tags = append(tags, description)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1112,38 +1112,8 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
|
|||
} else {
|
||||
// Non-IFD tag.
|
||||
|
||||
valueContext := ite.GetValueContext()
|
||||
|
||||
var rawBytes []byte
|
||||
|
||||
if ite.TagType() == exifcommon.TypeUndefined {
|
||||
// It's an undefined-type value. Try to process (or skip if
|
||||
// we don't know how to), and encode back to bytes. This is the
|
||||
// cleanest way of using what we already have to both determine
|
||||
// if we support this tag and producing the bytes for it.
|
||||
|
||||
value, err := exifundefined.Decode(valueContext)
|
||||
if err != nil {
|
||||
if err == exifcommon.ErrUnhandledUnknownTypedTag {
|
||||
// It's an undefined-type tag that we don't handle. If
|
||||
// we don't know how to handle it, we can't know how
|
||||
// many bytes it is and we must skip it.
|
||||
continue
|
||||
}
|
||||
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
rawBytes, _, err = exifundefined.Encode(value, ib.byteOrder)
|
||||
log.PanicIf(err)
|
||||
} else {
|
||||
// It's a value with a standard type.
|
||||
|
||||
var err error
|
||||
|
||||
rawBytes, err = valueContext.ReadRawEncoded()
|
||||
log.PanicIf(err)
|
||||
}
|
||||
rawBytes, err := ite.RawBytes()
|
||||
log.PanicIf(err)
|
||||
|
||||
value := NewIfdBuilderTagValueFromBytes(rawBytes)
|
||||
|
||||
|
|
|
@ -1488,41 +1488,11 @@ func TestIfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
|
|||
t.Fatalf("Tag-type not as expected: %d != %d ITE=%s", recoveredIte.TagType(), originalIte.TagType(), recoveredIte)
|
||||
}
|
||||
|
||||
var originalValueBytes []byte
|
||||
originalValueBytes, err := originalIte.RawBytes()
|
||||
log.PanicIf(err)
|
||||
|
||||
if originalIte.TagType() == exifcommon.TypeUndefined {
|
||||
valueContext := originalIte.GetValueContext()
|
||||
|
||||
var err error
|
||||
|
||||
value, err := exifundefined.Decode(valueContext)
|
||||
log.PanicIf(err)
|
||||
|
||||
originalValueBytes, _, err = exifundefined.Encode(value, originalIndex.RootIfd.ByteOrder)
|
||||
} else {
|
||||
var err error
|
||||
|
||||
originalValueBytes, err = originalIte.RawBytes()
|
||||
log.PanicIf(err)
|
||||
}
|
||||
|
||||
var recoveredValueBytes []byte
|
||||
|
||||
if recoveredIte.TagType() == exifcommon.TypeUndefined {
|
||||
valueContext := recoveredIte.GetValueContext()
|
||||
|
||||
var err error
|
||||
|
||||
value, err := exifundefined.Decode(valueContext)
|
||||
log.PanicIf(err)
|
||||
|
||||
recoveredValueBytes, _, err = exifundefined.Encode(value, recoveredIndex.RootIfd.ByteOrder)
|
||||
} else {
|
||||
var err error
|
||||
|
||||
recoveredValueBytes, err = recoveredIte.RawBytes()
|
||||
log.PanicIf(err)
|
||||
}
|
||||
recoveredValueBytes, err := recoveredIte.RawBytes()
|
||||
log.PanicIf(err)
|
||||
|
||||
if bytes.Compare(recoveredValueBytes, originalValueBytes) != 0 {
|
||||
fmt.Printf("ACTUAL: %s\n", originalIte)
|
||||
|
@ -1811,9 +1781,7 @@ func ExampleIfdBuilder_SetStandardWithName() {
|
|||
log.PanicIf(err)
|
||||
|
||||
for _, ite := range results {
|
||||
valueContext := ite.GetValueContext()
|
||||
|
||||
valueRaw, err := valueContext.Values()
|
||||
valueRaw, err := ite.Value()
|
||||
log.PanicIf(err)
|
||||
|
||||
stringValue := valueRaw.(string)
|
||||
|
|
|
@ -213,7 +213,7 @@ func (ie *IfdEnumerate) parseTag(fqIfdPath string, tagPosition int, enumerator *
|
|||
// This was reimplemented as an interface to allow for simpler change management
|
||||
// in the future.
|
||||
type RawTagWalk interface {
|
||||
Visit(fqIfdPath string, ifdIndex int, tagId uint16, tagType exifcommon.TagTypePrimitive, valueContext *exifcommon.ValueContext) (err error)
|
||||
Visit(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error)
|
||||
}
|
||||
|
||||
// ParseIfd decodes the IFD block that we're currently sitting on the first
|
||||
|
@ -257,9 +257,7 @@ func (ie *IfdEnumerate) ParseIfd(fqIfdPath string, ifdIndex int, enumerator *Ifd
|
|||
}
|
||||
|
||||
if visitor != nil {
|
||||
valueContext := ite.GetValueContext()
|
||||
|
||||
err := visitor.Visit(fqIfdPath, ifdIndex, ite.TagId(), ite.TagType(), valueContext)
|
||||
err := visitor.Visit(fqIfdPath, ifdIndex, ite)
|
||||
log.PanicIf(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -495,9 +495,8 @@ func ExampleIfd_FindTagWithName() {
|
|||
}
|
||||
|
||||
ite := results[0]
|
||||
valueContext := ite.GetValueContext()
|
||||
|
||||
valueRaw, err := valueContext.Values()
|
||||
valueRaw, err := ite.Value()
|
||||
log.PanicIf(err)
|
||||
|
||||
value := valueRaw.(string)
|
||||
|
|
|
@ -105,7 +105,7 @@ func (ite *IfdTagEntry) valueOffset_() uint32 {
|
|||
|
||||
// RawBytes renders a specific list of bytes from the value in this tag.
|
||||
func (ite *IfdTagEntry) RawBytes() (rawBytes []byte, err error) {
|
||||
valueContext := ite.GetValueContext()
|
||||
valueContext := ite.getValueContext()
|
||||
|
||||
if ite.TagType() == exifcommon.TypeUndefined {
|
||||
value, err := exifundefined.Decode(valueContext)
|
||||
|
@ -140,7 +140,7 @@ func (ite *IfdTagEntry) Value() (value interface{}, err error) {
|
|||
}
|
||||
}()
|
||||
|
||||
valueContext := ite.GetValueContext()
|
||||
valueContext := ite.getValueContext()
|
||||
|
||||
if ite.tagType == exifcommon.TypeUndefined {
|
||||
var err error
|
||||
|
@ -163,6 +163,52 @@ func (ite *IfdTagEntry) Value() (value interface{}, err error) {
|
|||
return value, nil
|
||||
}
|
||||
|
||||
// Format returns the tag's value as a string.
|
||||
func (ite *IfdTagEntry) Format() (phrase string, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
value, err := ite.Value()
|
||||
if err != nil {
|
||||
if err == exifcommon.ErrUnhandledUnknownTypedTag {
|
||||
return exifundefined.UnparseableUnknownTagValuePlaceholder, nil
|
||||
}
|
||||
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
phrase, err = exifcommon.FormatFromType(value, false)
|
||||
log.PanicIf(err)
|
||||
|
||||
return phrase, nil
|
||||
}
|
||||
|
||||
// FormatFirst returns the same as Format() but only the first item.
|
||||
func (ite *IfdTagEntry) FormatFirst() (phrase string, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
value, err := ite.Value()
|
||||
if err != nil {
|
||||
if err == exifcommon.ErrUnhandledUnknownTypedTag {
|
||||
return exifundefined.UnparseableUnknownTagValuePlaceholder, nil
|
||||
}
|
||||
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
phrase, err = exifcommon.FormatFromType(value, true)
|
||||
log.PanicIf(err)
|
||||
|
||||
return phrase, nil
|
||||
}
|
||||
|
||||
func (ite *IfdTagEntry) setIsUnhandledUnknown(isUnhandledUnknown bool) {
|
||||
ite.isUnhandledUnknown = isUnhandledUnknown
|
||||
}
|
||||
|
@ -174,19 +220,22 @@ func (ite *IfdTagEntry) SetChildIfd(childFqIfdPath, childIfdPath, childIfdName s
|
|||
ite.childIfdName = childIfdName
|
||||
}
|
||||
|
||||
// ChildIfdName returns the name of the child IFD
|
||||
func (ite *IfdTagEntry) ChildIfdName() string {
|
||||
return ite.childIfdName
|
||||
}
|
||||
|
||||
// ChildIfdPath returns the path of the child IFD.
|
||||
func (ite *IfdTagEntry) ChildIfdPath() string {
|
||||
return ite.childIfdPath
|
||||
}
|
||||
|
||||
// ChildFqIfdPath returns the complete path of the child IFD.
|
||||
func (ite *IfdTagEntry) ChildFqIfdPath() string {
|
||||
return ite.childFqIfdPath
|
||||
}
|
||||
|
||||
func (ite *IfdTagEntry) GetValueContext() *exifcommon.ValueContext {
|
||||
func (ite *IfdTagEntry) getValueContext() *exifcommon.ValueContext {
|
||||
return exifcommon.NewValueContext(
|
||||
ite.ifdPath,
|
||||
ite.tagId,
|
||||
|
|
|
@ -126,9 +126,7 @@ func GetFlatExifData(exifData []byte) (exifTags []ExifTag, err error) {
|
|||
tagName = it.Name
|
||||
}
|
||||
|
||||
valueContext := ite.GetValueContext()
|
||||
|
||||
valueBytes, err := valueContext.ReadRawEncoded()
|
||||
valueBytes, err := ite.RawBytes()
|
||||
log.PanicIf(err)
|
||||
|
||||
value, err := ite.Value()
|
||||
|
|
Loading…
Reference in New Issue