mirror of
https://github.com/dsoprea/go-exif.git
synced 2025-05-31 11:41:57 +00:00
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.
This commit is contained in:
parent
1bdfa9b10e
commit
173d686dd9
@ -13,17 +13,16 @@ import (
|
|||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v2/common"
|
"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 {
|
type visitorWrapper struct {
|
||||||
f innerVisitorCall
|
f innerVisitorCall
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vw *visitorWrapper) Visit(fqIfdPath string, ifdIndex int, tagId uint16, tagType exifcommon.TagTypePrimitive, valueContext *exifcommon.ValueContext) (err error) {
|
func (vw *visitorWrapper) Visit(fqIfdPath string, ifdIndex int, ite *IfdTagEntry) (err error) {
|
||||||
return vw.f(fqIfdPath, ifdIndex, tagId, tagType, valueContext)
|
return vw.f(fqIfdPath, ifdIndex, ite)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVisit(t *testing.T) {
|
func TestVisit(t *testing.T) {
|
||||||
@ -71,7 +70,7 @@ func TestVisit(t *testing.T) {
|
|||||||
|
|
||||||
tags := make([]string, 0)
|
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() {
|
defer func() {
|
||||||
if state := recover(); state != nil {
|
if state := recover(); state != nil {
|
||||||
err = log.Wrap(state.(error))
|
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)
|
ifdPath, err := im.StripPathPhraseIndices(fqIfdPath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -92,26 +94,10 @@ func TestVisit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valueString := ""
|
valueString, err := ite.FormatFirst()
|
||||||
if tagType == exifcommon.TypeUndefined {
|
log.PanicIf(err)
|
||||||
value, err := exifundefined.Decode(valueContext)
|
|
||||||
if err != nil {
|
|
||||||
if err == exifcommon.ErrUnhandledUnknownTypedTag {
|
|
||||||
valueString = "!UNDEFINED!"
|
|
||||||
} else {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
valueString = fmt.Sprintf("%v", value)
|
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)
|
||||||
} 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)
|
|
||||||
tags = append(tags, description)
|
tags = append(tags, description)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -1112,38 +1112,8 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
|
|||||||
} else {
|
} else {
|
||||||
// Non-IFD tag.
|
// Non-IFD tag.
|
||||||
|
|
||||||
valueContext := ite.GetValueContext()
|
rawBytes, err := ite.RawBytes()
|
||||||
|
log.PanicIf(err)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
value := NewIfdBuilderTagValueFromBytes(rawBytes)
|
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)
|
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 {
|
recoveredValueBytes, err := recoveredIte.RawBytes()
|
||||||
valueContext := originalIte.GetValueContext()
|
log.PanicIf(err)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Compare(recoveredValueBytes, originalValueBytes) != 0 {
|
if bytes.Compare(recoveredValueBytes, originalValueBytes) != 0 {
|
||||||
fmt.Printf("ACTUAL: %s\n", originalIte)
|
fmt.Printf("ACTUAL: %s\n", originalIte)
|
||||||
@ -1811,9 +1781,7 @@ func ExampleIfdBuilder_SetStandardWithName() {
|
|||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
for _, ite := range results {
|
for _, ite := range results {
|
||||||
valueContext := ite.GetValueContext()
|
valueRaw, err := ite.Value()
|
||||||
|
|
||||||
valueRaw, err := valueContext.Values()
|
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
stringValue := valueRaw.(string)
|
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
|
// This was reimplemented as an interface to allow for simpler change management
|
||||||
// in the future.
|
// in the future.
|
||||||
type RawTagWalk interface {
|
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
|
// 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 {
|
if visitor != nil {
|
||||||
valueContext := ite.GetValueContext()
|
err := visitor.Visit(fqIfdPath, ifdIndex, ite)
|
||||||
|
|
||||||
err := visitor.Visit(fqIfdPath, ifdIndex, ite.TagId(), ite.TagType(), valueContext)
|
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,9 +495,8 @@ func ExampleIfd_FindTagWithName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ite := results[0]
|
ite := results[0]
|
||||||
valueContext := ite.GetValueContext()
|
|
||||||
|
|
||||||
valueRaw, err := valueContext.Values()
|
valueRaw, err := ite.Value()
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
value := valueRaw.(string)
|
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.
|
// RawBytes renders a specific list of bytes from the value in this tag.
|
||||||
func (ite *IfdTagEntry) RawBytes() (rawBytes []byte, err error) {
|
func (ite *IfdTagEntry) RawBytes() (rawBytes []byte, err error) {
|
||||||
valueContext := ite.GetValueContext()
|
valueContext := ite.getValueContext()
|
||||||
|
|
||||||
if ite.TagType() == exifcommon.TypeUndefined {
|
if ite.TagType() == exifcommon.TypeUndefined {
|
||||||
value, err := exifundefined.Decode(valueContext)
|
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 {
|
if ite.tagType == exifcommon.TypeUndefined {
|
||||||
var err error
|
var err error
|
||||||
@ -163,6 +163,52 @@ func (ite *IfdTagEntry) Value() (value interface{}, err error) {
|
|||||||
return value, nil
|
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) {
|
func (ite *IfdTagEntry) setIsUnhandledUnknown(isUnhandledUnknown bool) {
|
||||||
ite.isUnhandledUnknown = isUnhandledUnknown
|
ite.isUnhandledUnknown = isUnhandledUnknown
|
||||||
}
|
}
|
||||||
@ -174,19 +220,22 @@ func (ite *IfdTagEntry) SetChildIfd(childFqIfdPath, childIfdPath, childIfdName s
|
|||||||
ite.childIfdName = childIfdName
|
ite.childIfdName = childIfdName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChildIfdName returns the name of the child IFD
|
||||||
func (ite *IfdTagEntry) ChildIfdName() string {
|
func (ite *IfdTagEntry) ChildIfdName() string {
|
||||||
return ite.childIfdName
|
return ite.childIfdName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChildIfdPath returns the path of the child IFD.
|
||||||
func (ite *IfdTagEntry) ChildIfdPath() string {
|
func (ite *IfdTagEntry) ChildIfdPath() string {
|
||||||
return ite.childIfdPath
|
return ite.childIfdPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChildFqIfdPath returns the complete path of the child IFD.
|
||||||
func (ite *IfdTagEntry) ChildFqIfdPath() string {
|
func (ite *IfdTagEntry) ChildFqIfdPath() string {
|
||||||
return ite.childFqIfdPath
|
return ite.childFqIfdPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ite *IfdTagEntry) GetValueContext() *exifcommon.ValueContext {
|
func (ite *IfdTagEntry) getValueContext() *exifcommon.ValueContext {
|
||||||
return exifcommon.NewValueContext(
|
return exifcommon.NewValueContext(
|
||||||
ite.ifdPath,
|
ite.ifdPath,
|
||||||
ite.tagId,
|
ite.tagId,
|
||||||
|
@ -126,9 +126,7 @@ func GetFlatExifData(exifData []byte) (exifTags []ExifTag, err error) {
|
|||||||
tagName = it.Name
|
tagName = it.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
valueContext := ite.GetValueContext()
|
valueBytes, err := ite.RawBytes()
|
||||||
|
|
||||||
valueBytes, err := valueContext.ReadRawEncoded()
|
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
value, err := ite.Value()
|
value, err := ite.Value()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user