summaryrefslogtreecommitdiff
path: root/vendor/github.com/dsoprea/go-exif/v3/common
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dsoprea/go-exif/v3/common')
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/ifd.go651
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/parser.go280
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/testing_common.go88
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/type.go482
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/utility.go148
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/value_context.go464
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/value_encoder.go273
7 files changed, 0 insertions, 2386 deletions
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/ifd.go b/vendor/github.com/dsoprea/go-exif/v3/common/ifd.go
deleted file mode 100644
index 01886e966..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/ifd.go
+++ /dev/null
@@ -1,651 +0,0 @@
-package exifcommon
-
-import (
- "errors"
- "fmt"
- "strings"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- ifdLogger = log.NewLogger("exifcommon.ifd")
-)
-
-var (
- ErrChildIfdNotMapped = errors.New("no child-IFD for that tag-ID under parent")
-)
-
-// MappedIfd is one node in the IFD-mapping.
-type MappedIfd struct {
- ParentTagId uint16
- Placement []uint16
- Path []string
-
- Name string
- TagId uint16
- Children map[uint16]*MappedIfd
-}
-
-// String returns a descriptive string.
-func (mi *MappedIfd) String() string {
- pathPhrase := mi.PathPhrase()
- return fmt.Sprintf("MappedIfd<(0x%04X) [%s] PATH=[%s]>", mi.TagId, mi.Name, pathPhrase)
-}
-
-// PathPhrase returns a non-fully-qualified IFD path.
-func (mi *MappedIfd) PathPhrase() string {
- return strings.Join(mi.Path, "/")
-}
-
-// TODO(dustin): Refactor this to use IfdIdentity structs.
-
-// IfdMapping describes all of the IFDs that we currently recognize.
-type IfdMapping struct {
- rootNode *MappedIfd
-}
-
-// NewIfdMapping returns a new IfdMapping struct.
-func NewIfdMapping() (ifdMapping *IfdMapping) {
- rootNode := &MappedIfd{
- Path: make([]string, 0),
- Children: make(map[uint16]*MappedIfd),
- }
-
- return &IfdMapping{
- rootNode: rootNode,
- }
-}
-
-// NewIfdMappingWithStandard retruns a new IfdMapping struct preloaded with the
-// standard IFDs.
-func NewIfdMappingWithStandard() (ifdMapping *IfdMapping, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- im := NewIfdMapping()
-
- err = LoadStandardIfds(im)
- log.PanicIf(err)
-
- return im, nil
-}
-
-// Get returns the node given the path slice.
-func (im *IfdMapping) Get(parentPlacement []uint16) (childIfd *MappedIfd, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ptr := im.rootNode
- for _, tagId := range parentPlacement {
- if descendantPtr, found := ptr.Children[tagId]; found == false {
- log.Panicf("ifd child with tag-ID (%04x) not registered: [%s]", tagId, ptr.PathPhrase())
- } else {
- ptr = descendantPtr
- }
- }
-
- return ptr, nil
-}
-
-// GetWithPath returns the node given the path string.
-func (im *IfdMapping) GetWithPath(pathPhrase string) (mi *MappedIfd, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- if pathPhrase == "" {
- log.Panicf("path-phrase is empty")
- }
-
- path := strings.Split(pathPhrase, "/")
- ptr := im.rootNode
-
- for _, name := range path {
- var hit *MappedIfd
- for _, mi := range ptr.Children {
- if mi.Name == name {
- hit = mi
- break
- }
- }
-
- if hit == nil {
- log.Panicf("ifd child with name [%s] not registered: [%s]", name, ptr.PathPhrase())
- }
-
- ptr = hit
- }
-
- return ptr, nil
-}
-
-// GetChild is a convenience function to get the child path for a given parent
-// placement and child tag-ID.
-func (im *IfdMapping) GetChild(parentPathPhrase string, tagId uint16) (mi *MappedIfd, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- mi, err = im.GetWithPath(parentPathPhrase)
- log.PanicIf(err)
-
- for _, childMi := range mi.Children {
- if childMi.TagId == tagId {
- return childMi, nil
- }
- }
-
- // Whether or not an IFD is defined in data, such an IFD is not registered
- // and would be unknown.
- log.Panic(ErrChildIfdNotMapped)
- return nil, nil
-}
-
-// IfdTagIdAndIndex represents a specific part of the IFD path.
-//
-// This is a legacy type.
-type IfdTagIdAndIndex struct {
- Name string
- TagId uint16
- Index int
-}
-
-// String returns a descriptive string.
-func (itii IfdTagIdAndIndex) String() string {
- return fmt.Sprintf("IfdTagIdAndIndex<NAME=[%s] ID=(%04x) INDEX=(%d)>", itii.Name, itii.TagId, itii.Index)
-}
-
-// ResolvePath takes a list of names, which can also be suffixed with indices
-// (to identify the second, third, etc.. sibling IFD) and returns a list of
-// tag-IDs and those indices.
-//
-// Example:
-//
-// - IFD/Exif/Iop
-// - IFD0/Exif/Iop
-//
-// This is the only call that supports adding the numeric indices.
-func (im *IfdMapping) ResolvePath(pathPhrase string) (lineage []IfdTagIdAndIndex, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- pathPhrase = strings.TrimSpace(pathPhrase)
-
- if pathPhrase == "" {
- log.Panicf("can not resolve empty path-phrase")
- }
-
- path := strings.Split(pathPhrase, "/")
- lineage = make([]IfdTagIdAndIndex, len(path))
-
- ptr := im.rootNode
- empty := IfdTagIdAndIndex{}
- for i, name := range path {
- indexByte := name[len(name)-1]
- index := 0
- if indexByte >= '0' && indexByte <= '9' {
- index = int(indexByte - '0')
- name = name[:len(name)-1]
- }
-
- itii := IfdTagIdAndIndex{}
- for _, mi := range ptr.Children {
- if mi.Name != name {
- continue
- }
-
- itii.Name = name
- itii.TagId = mi.TagId
- itii.Index = index
-
- ptr = mi
-
- break
- }
-
- if itii == empty {
- log.Panicf("ifd child with name [%s] not registered: [%s]", name, pathPhrase)
- }
-
- lineage[i] = itii
- }
-
- return lineage, nil
-}
-
-// FqPathPhraseFromLineage returns the fully-qualified IFD path from the slice.
-func (im *IfdMapping) FqPathPhraseFromLineage(lineage []IfdTagIdAndIndex) (fqPathPhrase string) {
- fqPathParts := make([]string, len(lineage))
- for i, itii := range lineage {
- if itii.Index > 0 {
- fqPathParts[i] = fmt.Sprintf("%s%d", itii.Name, itii.Index)
- } else {
- fqPathParts[i] = itii.Name
- }
- }
-
- return strings.Join(fqPathParts, "/")
-}
-
-// PathPhraseFromLineage returns the non-fully-qualified IFD path from the
-// slice.
-func (im *IfdMapping) PathPhraseFromLineage(lineage []IfdTagIdAndIndex) (pathPhrase string) {
- pathParts := make([]string, len(lineage))
- for i, itii := range lineage {
- pathParts[i] = itii.Name
- }
-
- return strings.Join(pathParts, "/")
-}
-
-// StripPathPhraseIndices returns a non-fully-qualified path-phrase (no
-// indices).
-func (im *IfdMapping) StripPathPhraseIndices(pathPhrase string) (strippedPathPhrase string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- lineage, err := im.ResolvePath(pathPhrase)
- log.PanicIf(err)
-
- strippedPathPhrase = im.PathPhraseFromLineage(lineage)
- return strippedPathPhrase, nil
-}
-
-// Add puts the given IFD at the given position of the tree. The position of the
-// tree is referred to as the placement and is represented by a set of tag-IDs,
-// where the leftmost is the root tag and the tags going to the right are
-// progressive descendants.
-func (im *IfdMapping) Add(parentPlacement []uint16, tagId uint16, name string) (err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): !! It would be nicer to provide a list of names in the placement rather than tag-IDs.
-
- ptr, err := im.Get(parentPlacement)
- log.PanicIf(err)
-
- path := make([]string, len(parentPlacement)+1)
- if len(parentPlacement) > 0 {
- copy(path, ptr.Path)
- }
-
- path[len(path)-1] = name
-
- placement := make([]uint16, len(parentPlacement)+1)
- if len(placement) > 0 {
- copy(placement, ptr.Placement)
- }
-
- placement[len(placement)-1] = tagId
-
- childIfd := &MappedIfd{
- ParentTagId: ptr.TagId,
- Path: path,
- Placement: placement,
- Name: name,
- TagId: tagId,
- Children: make(map[uint16]*MappedIfd),
- }
-
- if _, found := ptr.Children[tagId]; found == true {
- log.Panicf("child IFD with tag-ID (%04x) already registered under IFD [%s] with tag-ID (%04x)", tagId, ptr.Name, ptr.TagId)
- }
-
- ptr.Children[tagId] = childIfd
-
- return nil
-}
-
-func (im *IfdMapping) dumpLineages(stack []*MappedIfd, input []string) (output []string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- currentIfd := stack[len(stack)-1]
-
- output = input
- for _, childIfd := range currentIfd.Children {
- stackCopy := make([]*MappedIfd, len(stack)+1)
-
- copy(stackCopy, stack)
- stackCopy[len(stack)] = childIfd
-
- // Add to output, but don't include the obligatory root node.
- parts := make([]string, len(stackCopy)-1)
- for i, mi := range stackCopy[1:] {
- parts[i] = mi.Name
- }
-
- output = append(output, strings.Join(parts, "/"))
-
- output, err = im.dumpLineages(stackCopy, output)
- log.PanicIf(err)
- }
-
- return output, nil
-}
-
-// DumpLineages returns a slice of strings representing all mappings.
-func (im *IfdMapping) DumpLineages() (output []string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- stack := []*MappedIfd{im.rootNode}
- output = make([]string, 0)
-
- output, err = im.dumpLineages(stack, output)
- log.PanicIf(err)
-
- return output, nil
-}
-
-// LoadStandardIfds loads the standard IFDs into the mapping.
-func LoadStandardIfds(im *IfdMapping) (err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- err = im.Add(
- []uint16{},
- IfdStandardIfdIdentity.TagId(), IfdStandardIfdIdentity.Name())
-
- log.PanicIf(err)
-
- err = im.Add(
- []uint16{IfdStandardIfdIdentity.TagId()},
- IfdExifStandardIfdIdentity.TagId(), IfdExifStandardIfdIdentity.Name())
-
- log.PanicIf(err)
-
- err = im.Add(
- []uint16{IfdStandardIfdIdentity.TagId(), IfdExifStandardIfdIdentity.TagId()},
- IfdExifIopStandardIfdIdentity.TagId(), IfdExifIopStandardIfdIdentity.Name())
-
- log.PanicIf(err)
-
- err = im.Add(
- []uint16{IfdStandardIfdIdentity.TagId()},
- IfdGpsInfoStandardIfdIdentity.TagId(), IfdGpsInfoStandardIfdIdentity.Name())
-
- log.PanicIf(err)
-
- return nil
-}
-
-// IfdTag describes a single IFD tag and its parent (if any).
-type IfdTag struct {
- parentIfdTag *IfdTag
- tagId uint16
- name string
-}
-
-func NewIfdTag(parentIfdTag *IfdTag, tagId uint16, name string) IfdTag {
- return IfdTag{
- parentIfdTag: parentIfdTag,
- tagId: tagId,
- name: name,
- }
-}
-
-// ParentIfd returns the IfdTag of this IFD's parent.
-func (it IfdTag) ParentIfd() *IfdTag {
- return it.parentIfdTag
-}
-
-// TagId returns the tag-ID of this IFD.
-func (it IfdTag) TagId() uint16 {
- return it.tagId
-}
-
-// Name returns the simple name of this IFD.
-func (it IfdTag) Name() string {
- return it.name
-}
-
-// String returns a descriptive string.
-func (it IfdTag) String() string {
- parentIfdPhrase := ""
- if it.parentIfdTag != nil {
- parentIfdPhrase = fmt.Sprintf(" PARENT=(0x%04x)[%s]", it.parentIfdTag.tagId, it.parentIfdTag.name)
- }
-
- return fmt.Sprintf("IfdTag<TAG-ID=(0x%04x) NAME=[%s]%s>", it.tagId, it.name, parentIfdPhrase)
-}
-
-var (
- // rootStandardIfd is the standard root IFD.
- rootStandardIfd = NewIfdTag(nil, 0x0000, "IFD") // IFD
-
- // exifStandardIfd is the standard "Exif" IFD.
- exifStandardIfd = NewIfdTag(&rootStandardIfd, 0x8769, "Exif") // IFD/Exif
-
- // iopStandardIfd is the standard "Iop" IFD.
- iopStandardIfd = NewIfdTag(&exifStandardIfd, 0xA005, "Iop") // IFD/Exif/Iop
-
- // gpsInfoStandardIfd is the standard "GPS" IFD.
- gpsInfoStandardIfd = NewIfdTag(&rootStandardIfd, 0x8825, "GPSInfo") // IFD/GPSInfo
-)
-
-// IfdIdentityPart represents one component in an IFD path.
-type IfdIdentityPart struct {
- Name string
- Index int
-}
-
-// String returns a fully-qualified IFD path.
-func (iip IfdIdentityPart) String() string {
- if iip.Index > 0 {
- return fmt.Sprintf("%s%d", iip.Name, iip.Index)
- } else {
- return iip.Name
- }
-}
-
-// UnindexedString returned a non-fully-qualified IFD path.
-func (iip IfdIdentityPart) UnindexedString() string {
- return iip.Name
-}
-
-// IfdIdentity represents a single IFD path and provides access to various
-// information and representations.
-//
-// Only global instances can be used for equality checks.
-type IfdIdentity struct {
- ifdTag IfdTag
- parts []IfdIdentityPart
- ifdPath string
- fqIfdPath string
-}
-
-// NewIfdIdentity returns a new IfdIdentity struct.
-func NewIfdIdentity(ifdTag IfdTag, parts ...IfdIdentityPart) (ii *IfdIdentity) {
- ii = &IfdIdentity{
- ifdTag: ifdTag,
- parts: parts,
- }
-
- ii.ifdPath = ii.getIfdPath()
- ii.fqIfdPath = ii.getFqIfdPath()
-
- return ii
-}
-
-// NewIfdIdentityFromString parses a string like "IFD/Exif" or "IFD1" or
-// something more exotic with custom IFDs ("SomeIFD4/SomeChildIFD6"). Note that
-// this will valid the unindexed IFD structure (because the standard tags from
-// the specification are unindexed), but not, obviously, any indices (e.g.
-// the numbers in "IFD0", "IFD1", "SomeIFD4/SomeChildIFD6"). It is
-// required for the caller to check whether these specific instances
-// were actually parsed out of the stream.
-func NewIfdIdentityFromString(im *IfdMapping, fqIfdPath string) (ii *IfdIdentity, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- lineage, err := im.ResolvePath(fqIfdPath)
- log.PanicIf(err)
-
- var lastIt *IfdTag
- identityParts := make([]IfdIdentityPart, len(lineage))
- for i, itii := range lineage {
- // Build out the tag that will eventually point to the IFD represented
- // by the right-most part in the IFD path.
-
- it := &IfdTag{
- parentIfdTag: lastIt,
- tagId: itii.TagId,
- name: itii.Name,
- }
-
- lastIt = it
-
- // Create the next IfdIdentity part.
-
- iip := IfdIdentityPart{
- Name: itii.Name,
- Index: itii.Index,
- }
-
- identityParts[i] = iip
- }
-
- ii = NewIfdIdentity(*lastIt, identityParts...)
- return ii, nil
-}
-
-func (ii *IfdIdentity) getFqIfdPath() string {
- partPhrases := make([]string, len(ii.parts))
- for i, iip := range ii.parts {
- partPhrases[i] = iip.String()
- }
-
- return strings.Join(partPhrases, "/")
-}
-
-func (ii *IfdIdentity) getIfdPath() string {
- partPhrases := make([]string, len(ii.parts))
- for i, iip := range ii.parts {
- partPhrases[i] = iip.UnindexedString()
- }
-
- return strings.Join(partPhrases, "/")
-}
-
-// String returns a fully-qualified IFD path.
-func (ii *IfdIdentity) String() string {
- return ii.fqIfdPath
-}
-
-// UnindexedString returns a non-fully-qualified IFD path.
-func (ii *IfdIdentity) UnindexedString() string {
- return ii.ifdPath
-}
-
-// IfdTag returns the tag struct behind this IFD.
-func (ii *IfdIdentity) IfdTag() IfdTag {
- return ii.ifdTag
-}
-
-// TagId returns the tag-ID of the IFD.
-func (ii *IfdIdentity) TagId() uint16 {
- return ii.ifdTag.TagId()
-}
-
-// LeafPathPart returns the last right-most path-part, which represents the
-// current IFD.
-func (ii *IfdIdentity) LeafPathPart() IfdIdentityPart {
- return ii.parts[len(ii.parts)-1]
-}
-
-// Name returns the simple name of this IFD.
-func (ii *IfdIdentity) Name() string {
- return ii.LeafPathPart().Name
-}
-
-// Index returns the index of this IFD (more then one IFD under a parent IFD
-// will be numbered [0..n]).
-func (ii *IfdIdentity) Index() int {
- return ii.LeafPathPart().Index
-}
-
-// Equals returns true if the two IfdIdentity instances are effectively
-// identical.
-//
-// Since there's no way to get a specific fully-qualified IFD path without a
-// certain slice of parts and all other fields are also derived from this,
-// checking that the fully-qualified IFD path is equals is sufficient.
-func (ii *IfdIdentity) Equals(ii2 *IfdIdentity) bool {
- return ii.String() == ii2.String()
-}
-
-// NewChild creates an IfdIdentity for an IFD that is a child of the current
-// IFD.
-func (ii *IfdIdentity) NewChild(childIfdTag IfdTag, index int) (iiChild *IfdIdentity) {
- if *childIfdTag.parentIfdTag != ii.ifdTag {
- log.Panicf("can not add child; we are not the parent:\nUS=%v\nCHILD=%v", ii.ifdTag, childIfdTag)
- }
-
- childPart := IfdIdentityPart{childIfdTag.name, index}
- childParts := append(ii.parts, childPart)
-
- iiChild = NewIfdIdentity(childIfdTag, childParts...)
- return iiChild
-}
-
-// NewSibling creates an IfdIdentity for an IFD that is a sibling to the current
-// one.
-func (ii *IfdIdentity) NewSibling(index int) (iiSibling *IfdIdentity) {
- parts := make([]IfdIdentityPart, len(ii.parts))
-
- copy(parts, ii.parts)
- parts[len(parts)-1].Index = index
-
- iiSibling = NewIfdIdentity(ii.ifdTag, parts...)
- return iiSibling
-}
-
-var (
- // IfdStandardIfdIdentity represents the IFD path for IFD0.
- IfdStandardIfdIdentity = NewIfdIdentity(rootStandardIfd, IfdIdentityPart{"IFD", 0})
-
- // IfdExifStandardIfdIdentity represents the IFD path for IFD0/Exif0.
- IfdExifStandardIfdIdentity = IfdStandardIfdIdentity.NewChild(exifStandardIfd, 0)
-
- // IfdExifIopStandardIfdIdentity represents the IFD path for IFD0/Exif0/Iop0.
- IfdExifIopStandardIfdIdentity = IfdExifStandardIfdIdentity.NewChild(iopStandardIfd, 0)
-
- // IfdGPSInfoStandardIfdIdentity represents the IFD path for IFD0/GPSInfo0.
- IfdGpsInfoStandardIfdIdentity = IfdStandardIfdIdentity.NewChild(gpsInfoStandardIfd, 0)
-
- // Ifd1StandardIfdIdentity represents the IFD path for IFD1.
- Ifd1StandardIfdIdentity = NewIfdIdentity(rootStandardIfd, IfdIdentityPart{"IFD", 1})
-)
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/parser.go b/vendor/github.com/dsoprea/go-exif/v3/common/parser.go
deleted file mode 100644
index 76e8ef425..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/parser.go
+++ /dev/null
@@ -1,280 +0,0 @@
-package exifcommon
-
-import (
- "bytes"
- "errors"
- "math"
-
- "encoding/binary"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- parserLogger = log.NewLogger("exifcommon.parser")
-)
-
-var (
- ErrParseFail = errors.New("parse failure")
-)
-
-// Parser knows how to parse all well-defined, encoded EXIF types.
-type Parser struct {
-}
-
-// ParseBytesknows how to parse a byte-type value.
-func (p *Parser) ParseBytes(data []byte, unitCount uint32) (value []uint8, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeByte.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = []uint8(data[:count])
-
- return value, nil
-}
-
-// ParseAscii returns a string and auto-strips the trailing NUL character that
-// should be at the end of the encoding.
-func (p *Parser) ParseAscii(data []byte, unitCount uint32) (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeAscii.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- if len(data) == 0 || data[count-1] != 0 {
- s := string(data[:count])
- parserLogger.Warningf(nil, "ASCII not terminated with NUL as expected: [%v]", s)
-
- for i, c := range s {
- if c > 127 {
- // Binary
-
- t := s[:i]
- parserLogger.Warningf(nil, "ASCII also had binary characters. Truncating: [%v]->[%s]", s, t)
-
- return t, nil
- }
- }
-
- return s, nil
- }
-
- // Auto-strip the NUL from the end. It serves no purpose outside of
- // encoding semantics.
-
- return string(data[:count-1]), nil
-}
-
-// ParseAsciiNoNul returns a string without any consideration for a trailing NUL
-// character.
-func (p *Parser) ParseAsciiNoNul(data []byte, unitCount uint32) (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeAscii.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- return string(data[:count]), nil
-}
-
-// ParseShorts knows how to parse an encoded list of shorts.
-func (p *Parser) ParseShorts(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint16, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeShort.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = make([]uint16, count)
- for i := 0; i < count; i++ {
- value[i] = byteOrder.Uint16(data[i*2:])
- }
-
- return value, nil
-}
-
-// ParseLongs knows how to encode an encoded list of unsigned longs.
-func (p *Parser) ParseLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeLong.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = make([]uint32, count)
- for i := 0; i < count; i++ {
- value[i] = byteOrder.Uint32(data[i*4:])
- }
-
- return value, nil
-}
-
-// ParseFloats knows how to encode an encoded list of floats.
-func (p *Parser) ParseFloats(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []float32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- count := int(unitCount)
-
- if len(data) != (TypeFloat.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = make([]float32, count)
- for i := 0; i < count; i++ {
- value[i] = math.Float32frombits(byteOrder.Uint32(data[i*4 : (i+1)*4]))
- }
-
- return value, nil
-}
-
-// ParseDoubles knows how to encode an encoded list of doubles.
-func (p *Parser) ParseDoubles(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []float64, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- count := int(unitCount)
-
- if len(data) != (TypeDouble.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = make([]float64, count)
- for i := 0; i < count; i++ {
- value[i] = math.Float64frombits(byteOrder.Uint64(data[i*8 : (i+1)*8]))
- }
-
- return value, nil
-}
-
-// ParseRationals knows how to parse an encoded list of unsigned rationals.
-func (p *Parser) ParseRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []Rational, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeRational.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- value = make([]Rational, count)
- for i := 0; i < count; i++ {
- value[i].Numerator = byteOrder.Uint32(data[i*8:])
- value[i].Denominator = byteOrder.Uint32(data[i*8+4:])
- }
-
- return value, nil
-}
-
-// ParseSignedLongs knows how to parse an encoded list of signed longs.
-func (p *Parser) ParseSignedLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []int32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeSignedLong.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- b := bytes.NewBuffer(data)
-
- value = make([]int32, count)
- for i := 0; i < count; i++ {
- err := binary.Read(b, byteOrder, &value[i])
- log.PanicIf(err)
- }
-
- return value, nil
-}
-
-// ParseSignedRationals knows how to parse an encoded list of signed
-// rationals.
-func (p *Parser) ParseSignedRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []SignedRational, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): Add test
-
- count := int(unitCount)
-
- if len(data) < (TypeSignedRational.Size() * count) {
- log.Panic(ErrNotEnoughData)
- }
-
- b := bytes.NewBuffer(data)
-
- value = make([]SignedRational, count)
- for i := 0; i < count; i++ {
- err = binary.Read(b, byteOrder, &value[i].Numerator)
- log.PanicIf(err)
-
- err = binary.Read(b, byteOrder, &value[i].Denominator)
- log.PanicIf(err)
- }
-
- return value, nil
-}
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/testing_common.go b/vendor/github.com/dsoprea/go-exif/v3/common/testing_common.go
deleted file mode 100644
index f04fa22b6..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/testing_common.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package exifcommon
-
-import (
- "os"
- "path"
-
- "encoding/binary"
- "io/ioutil"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- moduleRootPath = ""
-
- testExifData []byte = nil
-
- // EncodeDefaultByteOrder is the default byte-order for encoding operations.
- EncodeDefaultByteOrder = binary.BigEndian
-
- // Default byte order for tests.
- TestDefaultByteOrder = binary.BigEndian
-)
-
-func GetModuleRootPath() string {
- if moduleRootPath == "" {
- moduleRootPath = os.Getenv("EXIF_MODULE_ROOT_PATH")
- if moduleRootPath != "" {
- return moduleRootPath
- }
-
- currentWd, err := os.Getwd()
- log.PanicIf(err)
-
- currentPath := currentWd
-
- visited := make([]string, 0)
-
- for {
- tryStampFilepath := path.Join(currentPath, ".MODULE_ROOT")
-
- _, err := os.Stat(tryStampFilepath)
- if err != nil && os.IsNotExist(err) != true {
- log.Panic(err)
- } else if err == nil {
- break
- }
-
- visited = append(visited, tryStampFilepath)
-
- currentPath = path.Dir(currentPath)
- if currentPath == "/" {
- log.Panicf("could not find module-root: %v", visited)
- }
- }
-
- moduleRootPath = currentPath
- }
-
- return moduleRootPath
-}
-
-func GetTestAssetsPath() string {
- moduleRootPath := GetModuleRootPath()
- assetsPath := path.Join(moduleRootPath, "assets")
-
- return assetsPath
-}
-
-func getTestImageFilepath() string {
- assetsPath := GetTestAssetsPath()
- testImageFilepath := path.Join(assetsPath, "NDM_8901.jpg")
- return testImageFilepath
-}
-
-func getTestExifData() []byte {
- if testExifData == nil {
- assetsPath := GetTestAssetsPath()
- filepath := path.Join(assetsPath, "NDM_8901.jpg.exif")
-
- var err error
-
- testExifData, err = ioutil.ReadFile(filepath)
- log.PanicIf(err)
- }
-
- return testExifData
-}
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/type.go b/vendor/github.com/dsoprea/go-exif/v3/common/type.go
deleted file mode 100644
index e79bcb9a1..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/type.go
+++ /dev/null
@@ -1,482 +0,0 @@
-package exifcommon
-
-import (
- "errors"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "unicode"
-
- "encoding/binary"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- typeLogger = log.NewLogger("exif.type")
-)
-
-var (
- // ErrNotEnoughData is used when there isn't enough data to accommodate what
- // we're trying to parse (sizeof(type) * unit_count).
- ErrNotEnoughData = errors.New("not enough data for type")
-
- // ErrWrongType is used when we try to parse anything other than the
- // current type.
- ErrWrongType = errors.New("wrong type, can not parse")
-
- // ErrUnhandledUndefinedTypedTag is used when we try to parse a tag that's
- // recorded as an "unknown" type but not a documented tag (therefore
- // leaving us not knowning how to read it).
- ErrUnhandledUndefinedTypedTag = errors.New("not a standard unknown-typed tag")
-)
-
-// TagTypePrimitive is a type-alias that let's us easily lookup type properties.
-type TagTypePrimitive uint16
-
-const (
- // TypeByte describes an encoded list of bytes.
- TypeByte TagTypePrimitive = 1
-
- // TypeAscii describes an encoded list of characters that is terminated
- // with a NUL in its encoded form.
- TypeAscii TagTypePrimitive = 2
-
- // TypeShort describes an encoded list of shorts.
- TypeShort TagTypePrimitive = 3
-
- // TypeLong describes an encoded list of longs.
- TypeLong TagTypePrimitive = 4
-
- // TypeRational describes an encoded list of rationals.
- TypeRational TagTypePrimitive = 5
-
- // TypeUndefined describes an encoded value that has a complex/non-clearcut
- // interpretation.
- TypeUndefined TagTypePrimitive = 7
-
- // We've seen type-8, but have no documentation on it.
-
- // TypeSignedLong describes an encoded list of signed longs.
- TypeSignedLong TagTypePrimitive = 9
-
- // TypeSignedRational describes an encoded list of signed rationals.
- TypeSignedRational TagTypePrimitive = 10
-
- // TypeFloat describes an encoded list of floats
- TypeFloat TagTypePrimitive = 11
-
- // TypeDouble describes an encoded list of doubles.
- TypeDouble TagTypePrimitive = 12
-
- // TypeAsciiNoNul is just a pseudo-type, for our own purposes.
- TypeAsciiNoNul TagTypePrimitive = 0xf0
-)
-
-// String returns the name of the type
-func (typeType TagTypePrimitive) String() string {
- return TypeNames[typeType]
-}
-
-// Size returns the size of one atomic unit of the type.
-func (tagType TagTypePrimitive) Size() int {
- switch tagType {
- case TypeByte, TypeAscii, TypeAsciiNoNul:
- return 1
- case TypeShort:
- return 2
- case TypeLong, TypeSignedLong, TypeFloat:
- return 4
- case TypeRational, TypeSignedRational, TypeDouble:
- return 8
- default:
- log.Panicf("can not determine tag-value size for type (%d): [%s]",
- tagType,
- TypeNames[tagType])
- // Never called.
- return 0
- }
-}
-
-// IsValid returns true if tagType is a valid type.
-func (tagType TagTypePrimitive) IsValid() bool {
-
- // TODO(dustin): Add test
-
- return tagType == TypeByte ||
- tagType == TypeAscii ||
- tagType == TypeAsciiNoNul ||
- tagType == TypeShort ||
- tagType == TypeLong ||
- tagType == TypeRational ||
- tagType == TypeSignedLong ||
- tagType == TypeSignedRational ||
- tagType == TypeFloat ||
- tagType == TypeDouble ||
- tagType == TypeUndefined
-}
-
-var (
- // TODO(dustin): Rename TypeNames() to typeNames() and add getter.
- TypeNames = map[TagTypePrimitive]string{
- TypeByte: "BYTE",
- TypeAscii: "ASCII",
- TypeShort: "SHORT",
- TypeLong: "LONG",
- TypeRational: "RATIONAL",
- TypeUndefined: "UNDEFINED",
- TypeSignedLong: "SLONG",
- TypeSignedRational: "SRATIONAL",
- TypeFloat: "FLOAT",
- TypeDouble: "DOUBLE",
-
- TypeAsciiNoNul: "_ASCII_NO_NUL",
- }
-
- typeNamesR = map[string]TagTypePrimitive{}
-)
-
-// Rational describes an unsigned rational value.
-type Rational struct {
- // Numerator is the numerator of the rational value.
- Numerator uint32
-
- // Denominator is the numerator of the rational value.
- Denominator uint32
-}
-
-// SignedRational describes a signed rational value.
-type SignedRational struct {
- // Numerator is the numerator of the rational value.
- Numerator int32
-
- // Denominator is the numerator of the rational value.
- Denominator int32
-}
-
-func isPrintableText(s string) bool {
- for _, c := range s {
- // unicode.IsPrint() returns false for newline characters.
- if c == 0x0d || c == 0x0a {
- continue
- } else if unicode.IsPrint(rune(c)) == false {
- return false
- }
- }
-
- return true
-}
-
-// Format returns a stringified value for the given encoding. Automatically
-// parses. Automatically calculates count based on type size. This function
-// also supports undefined-type values (the ones that we support, anyway) by
-// way of the String() method that they all require. We can't be more specific
-// because we're a base package and we can't refer to it.
-func FormatFromType(value interface{}, justFirst bool) (phrase string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): !! Add test
-
- switch t := value.(type) {
- case []byte:
- return DumpBytesToString(t), nil
- case string:
- for i, c := range t {
- if c == 0 {
- t = t[:i]
- break
- }
- }
-
- if isPrintableText(t) == false {
- phrase = fmt.Sprintf("string with binary data (%d bytes)", len(t))
- return phrase, nil
- }
-
- return t, nil
- case []uint16, []uint32, []int32, []float64, []float32:
- val := reflect.ValueOf(t)
-
- if val.Len() == 0 {
- return "", nil
- }
-
- if justFirst == true {
- var valueSuffix string
- if val.Len() > 1 {
- valueSuffix = "..."
- }
-
- return fmt.Sprintf("%v%s", val.Index(0), valueSuffix), nil
- }
-
- return fmt.Sprintf("%v", val), nil
- case []Rational:
- if len(t) == 0 {
- return "", nil
- }
-
- parts := make([]string, len(t))
- for i, r := range t {
- parts[i] = fmt.Sprintf("%d/%d", r.Numerator, r.Denominator)
-
- if justFirst == true {
- break
- }
- }
-
- if justFirst == true {
- var valueSuffix string
- if len(t) > 1 {
- valueSuffix = "..."
- }
-
- return fmt.Sprintf("%v%s", parts[0], valueSuffix), nil
- }
-
- return fmt.Sprintf("%v", parts), nil
- case []SignedRational:
- if len(t) == 0 {
- return "", nil
- }
-
- parts := make([]string, len(t))
- for i, r := range t {
- parts[i] = fmt.Sprintf("%d/%d", r.Numerator, r.Denominator)
-
- if justFirst == true {
- break
- }
- }
-
- if justFirst == true {
- var valueSuffix string
- if len(t) > 1 {
- valueSuffix = "..."
- }
-
- return fmt.Sprintf("%v%s", parts[0], valueSuffix), nil
- }
-
- return fmt.Sprintf("%v", parts), nil
- case fmt.Stringer:
- s := t.String()
- if isPrintableText(s) == false {
- phrase = fmt.Sprintf("stringable with binary data (%d bytes)", len(s))
- return phrase, nil
- }
-
- // An undefined value that is documented (or that we otherwise support).
- return s, nil
- default:
- // Affects only "unknown" values, in general.
- log.Panicf("type can not be formatted into string: %v", reflect.TypeOf(value).Name())
-
- // Never called.
- return "", nil
- }
-}
-
-// Format returns a stringified value for the given encoding. Automatically
-// parses. Automatically calculates count based on type size.
-func FormatFromBytes(rawBytes []byte, tagType TagTypePrimitive, justFirst bool, byteOrder binary.ByteOrder) (phrase string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- // TODO(dustin): !! Add test
-
- typeSize := tagType.Size()
-
- if len(rawBytes)%typeSize != 0 {
- log.Panicf("byte-count (%d) does not align for [%s] type with a size of (%d) bytes", len(rawBytes), TypeNames[tagType], typeSize)
- }
-
- // unitCount is the calculated unit-count. This should equal the original
- // value from the tag (pre-resolution).
- unitCount := uint32(len(rawBytes) / typeSize)
-
- // Truncate the items if it's not bytes or a string and we just want the first.
-
- var value interface{}
-
- switch tagType {
- case TypeByte:
- var err error
-
- value, err = parser.ParseBytes(rawBytes, unitCount)
- log.PanicIf(err)
- case TypeAscii:
- var err error
-
- value, err = parser.ParseAscii(rawBytes, unitCount)
- log.PanicIf(err)
- case TypeAsciiNoNul:
- var err error
-
- value, err = parser.ParseAsciiNoNul(rawBytes, unitCount)
- log.PanicIf(err)
- case TypeShort:
- var err error
-
- value, err = parser.ParseShorts(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeLong:
- var err error
-
- value, err = parser.ParseLongs(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeFloat:
- var err error
-
- value, err = parser.ParseFloats(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeDouble:
- var err error
-
- value, err = parser.ParseDoubles(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeRational:
- var err error
-
- value, err = parser.ParseRationals(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeSignedLong:
- var err error
-
- value, err = parser.ParseSignedLongs(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- case TypeSignedRational:
- var err error
-
- value, err = parser.ParseSignedRationals(rawBytes, unitCount, byteOrder)
- log.PanicIf(err)
- default:
- // Affects only "unknown" values, in general.
- log.Panicf("value of type [%s] can not be formatted into string", tagType.String())
-
- // Never called.
- return "", nil
- }
-
- phrase, err = FormatFromType(value, justFirst)
- log.PanicIf(err)
-
- return phrase, nil
-}
-
-// TranslateStringToType converts user-provided strings to properly-typed
-// values. If a string, returns a string. Else, assumes that it's a single
-// number. If a list needs to be processed, it is the caller's responsibility to
-// split it (according to whichever convention has been established).
-func TranslateStringToType(tagType TagTypePrimitive, valueString string) (value interface{}, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- if tagType == TypeUndefined {
- // The caller should just call String() on the decoded type.
- log.Panicf("undefined-type values are not supported")
- }
-
- if tagType == TypeByte {
- wide, err := strconv.ParseInt(valueString, 16, 8)
- log.PanicIf(err)
-
- return byte(wide), nil
- } else if tagType == TypeAscii || tagType == TypeAsciiNoNul {
- // Whether or not we're putting an NUL on the end is only relevant for
- // byte-level encoding. This function really just supports a user
- // interface.
-
- return valueString, nil
- } else if tagType == TypeShort {
- n, err := strconv.ParseUint(valueString, 10, 16)
- log.PanicIf(err)
-
- return uint16(n), nil
- } else if tagType == TypeLong {
- n, err := strconv.ParseUint(valueString, 10, 32)
- log.PanicIf(err)
-
- return uint32(n), nil
- } else if tagType == TypeRational {
- parts := strings.SplitN(valueString, "/", 2)
-
- numerator, err := strconv.ParseUint(parts[0], 10, 32)
- log.PanicIf(err)
-
- denominator, err := strconv.ParseUint(parts[1], 10, 32)
- log.PanicIf(err)
-
- return Rational{
- Numerator: uint32(numerator),
- Denominator: uint32(denominator),
- }, nil
- } else if tagType == TypeSignedLong {
- n, err := strconv.ParseInt(valueString, 10, 32)
- log.PanicIf(err)
-
- return int32(n), nil
- } else if tagType == TypeFloat {
- n, err := strconv.ParseFloat(valueString, 32)
- log.PanicIf(err)
-
- return float32(n), nil
- } else if tagType == TypeDouble {
- n, err := strconv.ParseFloat(valueString, 64)
- log.PanicIf(err)
-
- return float64(n), nil
- } else if tagType == TypeSignedRational {
- parts := strings.SplitN(valueString, "/", 2)
-
- numerator, err := strconv.ParseInt(parts[0], 10, 32)
- log.PanicIf(err)
-
- denominator, err := strconv.ParseInt(parts[1], 10, 32)
- log.PanicIf(err)
-
- return SignedRational{
- Numerator: int32(numerator),
- Denominator: int32(denominator),
- }, nil
- }
-
- log.Panicf("from-string encoding for type not supported; this shouldn't happen: [%s]", tagType.String())
- return nil, nil
-}
-
-// GetTypeByName returns the `TagTypePrimitive` for the given type name.
-// Returns (0) if not valid.
-func GetTypeByName(typeName string) (tagType TagTypePrimitive, found bool) {
- tagType, found = typeNamesR[typeName]
- return tagType, found
-}
-
-// BasicTag describes a single tag for any purpose.
-type BasicTag struct {
- // FqIfdPath is the fully-qualified IFD-path.
- FqIfdPath string
-
- // IfdPath is the unindexed IFD-path.
- IfdPath string
-
- // TagId is the tag-ID.
- TagId uint16
-}
-
-func init() {
- for typeId, typeName := range TypeNames {
- typeNamesR[typeName] = typeId
- }
-}
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/utility.go b/vendor/github.com/dsoprea/go-exif/v3/common/utility.go
deleted file mode 100644
index 575049706..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/utility.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package exifcommon
-
-import (
- "bytes"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "time"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- timeType = reflect.TypeOf(time.Time{})
-)
-
-// DumpBytes prints a list of hex-encoded bytes.
-func DumpBytes(data []byte) {
- fmt.Printf("DUMP: ")
- for _, x := range data {
- fmt.Printf("%02x ", x)
- }
-
- fmt.Printf("\n")
-}
-
-// DumpBytesClause prints a list like DumpBytes(), but encapsulated in
-// "[]byte { ... }".
-func DumpBytesClause(data []byte) {
- fmt.Printf("DUMP: ")
-
- fmt.Printf("[]byte { ")
-
- for i, x := range data {
- fmt.Printf("0x%02x", x)
-
- if i < len(data)-1 {
- fmt.Printf(", ")
- }
- }
-
- fmt.Printf(" }\n")
-}
-
-// DumpBytesToString returns a stringified list of hex-encoded bytes.
-func DumpBytesToString(data []byte) string {
- b := new(bytes.Buffer)
-
- for i, x := range data {
- _, err := b.WriteString(fmt.Sprintf("%02x", x))
- log.PanicIf(err)
-
- if i < len(data)-1 {
- _, err := b.WriteRune(' ')
- log.PanicIf(err)
- }
- }
-
- return b.String()
-}
-
-// DumpBytesClauseToString returns a comma-separated list of hex-encoded bytes.
-func DumpBytesClauseToString(data []byte) string {
- b := new(bytes.Buffer)
-
- for i, x := range data {
- _, err := b.WriteString(fmt.Sprintf("0x%02x", x))
- log.PanicIf(err)
-
- if i < len(data)-1 {
- _, err := b.WriteString(", ")
- log.PanicIf(err)
- }
- }
-
- return b.String()
-}
-
-// ExifFullTimestampString produces a string like "2018:11:30 13:01:49" from a
-// `time.Time` struct. It will attempt to convert to UTC first.
-func ExifFullTimestampString(t time.Time) (fullTimestampPhrase string) {
- t = t.UTC()
-
- return fmt.Sprintf("%04d:%02d:%02d %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
-}
-
-// ParseExifFullTimestamp parses dates like "2018:11:30 13:01:49" into a UTC
-// `time.Time` struct.
-func ParseExifFullTimestamp(fullTimestampPhrase string) (timestamp time.Time, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- parts := strings.Split(fullTimestampPhrase, " ")
- datestampValue, timestampValue := parts[0], parts[1]
-
- // Normalize the separators.
- datestampValue = strings.ReplaceAll(datestampValue, "-", ":")
- timestampValue = strings.ReplaceAll(timestampValue, "-", ":")
-
- dateParts := strings.Split(datestampValue, ":")
-
- year, err := strconv.ParseUint(dateParts[0], 10, 16)
- if err != nil {
- log.Panicf("could not parse year")
- }
-
- month, err := strconv.ParseUint(dateParts[1], 10, 8)
- if err != nil {
- log.Panicf("could not parse month")
- }
-
- day, err := strconv.ParseUint(dateParts[2], 10, 8)
- if err != nil {
- log.Panicf("could not parse day")
- }
-
- timeParts := strings.Split(timestampValue, ":")
-
- hour, err := strconv.ParseUint(timeParts[0], 10, 8)
- if err != nil {
- log.Panicf("could not parse hour")
- }
-
- minute, err := strconv.ParseUint(timeParts[1], 10, 8)
- if err != nil {
- log.Panicf("could not parse minute")
- }
-
- second, err := strconv.ParseUint(timeParts[2], 10, 8)
- if err != nil {
- log.Panicf("could not parse second")
- }
-
- timestamp = time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.UTC)
- return timestamp, nil
-}
-
-// IsTime returns true if the value is a `time.Time`.
-func IsTime(v interface{}) bool {
-
- // TODO(dustin): Add test
-
- return reflect.TypeOf(v) == timeType
-}
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/value_context.go b/vendor/github.com/dsoprea/go-exif/v3/common/value_context.go
deleted file mode 100644
index b9e634106..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/value_context.go
+++ /dev/null
@@ -1,464 +0,0 @@
-package exifcommon
-
-import (
- "errors"
- "io"
-
- "encoding/binary"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- parser *Parser
-)
-
-var (
- // ErrNotFarValue indicates that an offset-based lookup was attempted for a
- // non-offset-based (embedded) value.
- ErrNotFarValue = errors.New("not a far value")
-)
-
-// ValueContext embeds all of the parameters required to find and extract the
-// actual tag value.
-type ValueContext struct {
- unitCount uint32
- valueOffset uint32
- rawValueOffset []byte
- rs io.ReadSeeker
-
- tagType TagTypePrimitive
- byteOrder binary.ByteOrder
-
- // undefinedValueTagType is the effective type to use if this is an
- // "undefined" value.
- undefinedValueTagType TagTypePrimitive
-
- ifdPath string
- tagId uint16
-}
-
-// TODO(dustin): We can update newValueContext() to derive `valueOffset` itself (from `rawValueOffset`).
-
-// NewValueContext returns a new ValueContext struct.
-func NewValueContext(ifdPath string, tagId uint16, unitCount, valueOffset uint32, rawValueOffset []byte, rs io.ReadSeeker, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext {
- return &ValueContext{
- unitCount: unitCount,
- valueOffset: valueOffset,
- rawValueOffset: rawValueOffset,
- rs: rs,
-
- tagType: tagType,
- byteOrder: byteOrder,
-
- ifdPath: ifdPath,
- tagId: tagId,
- }
-}
-
-// SetUndefinedValueType sets the effective type if this is an unknown-type tag.
-func (vc *ValueContext) SetUndefinedValueType(tagType TagTypePrimitive) {
- if vc.tagType != TypeUndefined {
- log.Panicf("can not set effective type for unknown-type tag because this is *not* an unknown-type tag")
- }
-
- vc.undefinedValueTagType = tagType
-}
-
-// UnitCount returns the embedded unit-count.
-func (vc *ValueContext) UnitCount() uint32 {
- return vc.unitCount
-}
-
-// ValueOffset returns the value-offset decoded as a `uint32`.
-func (vc *ValueContext) ValueOffset() uint32 {
- return vc.valueOffset
-}
-
-// RawValueOffset returns the uninterpreted value-offset. This is used for
-// embedded values (values small enough to fit within the offset bytes rather
-// than needing to be stored elsewhere and referred to by an actual offset).
-func (vc *ValueContext) RawValueOffset() []byte {
- return vc.rawValueOffset
-}
-
-// AddressableData returns the block of data that we can dereference into.
-func (vc *ValueContext) AddressableData() io.ReadSeeker {
-
- // RELEASE)dustin): Rename from AddressableData() to ReadSeeker()
-
- return vc.rs
-}
-
-// ByteOrder returns the byte-order of numbers.
-func (vc *ValueContext) ByteOrder() binary.ByteOrder {
- return vc.byteOrder
-}
-
-// IfdPath returns the path of the IFD containing this tag.
-func (vc *ValueContext) IfdPath() string {
- return vc.ifdPath
-}
-
-// TagId returns the ID of the tag that we represent.
-func (vc *ValueContext) TagId() uint16 {
- return vc.tagId
-}
-
-// isEmbedded returns whether the value is embedded or a reference. This can't
-// be precalculated since the size is not defined for all types (namely the
-// "undefined" types).
-func (vc *ValueContext) isEmbedded() bool {
- tagType := vc.effectiveValueType()
-
- return (tagType.Size() * int(vc.unitCount)) <= 4
-}
-
-// SizeInBytes returns the number of bytes that this value requires. The
-// underlying call will panic if the type is UNDEFINED. It is the
-// responsibility of the caller to preemptively check that.
-func (vc *ValueContext) SizeInBytes() int {
- tagType := vc.effectiveValueType()
-
- return tagType.Size() * int(vc.unitCount)
-}
-
-// effectiveValueType returns the effective type of the unknown-type tag or, if
-// not unknown, the actual type.
-func (vc *ValueContext) effectiveValueType() (tagType TagTypePrimitive) {
- if vc.tagType == TypeUndefined {
- tagType = vc.undefinedValueTagType
-
- if tagType == 0 {
- log.Panicf("undefined-value type not set")
- }
- } else {
- tagType = vc.tagType
- }
-
- return tagType
-}
-
-// readRawEncoded returns the encoded bytes for the value that we represent.
-func (vc *ValueContext) readRawEncoded() (rawBytes []byte, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- tagType := vc.effectiveValueType()
-
- unitSizeRaw := uint32(tagType.Size())
-
- if vc.isEmbedded() == true {
- byteLength := unitSizeRaw * vc.unitCount
- return vc.rawValueOffset[:byteLength], 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
-// pointer itself] or an error if an embedded value.
-func (vc *ValueContext) GetFarOffset() (offset uint32, err error) {
- if vc.isEmbedded() == true {
- return 0, ErrNotFarValue
- }
-
- return vc.valueOffset, nil
-}
-
-// ReadRawEncoded returns the encoded bytes for the value that we represent.
-func (vc *ValueContext) ReadRawEncoded() (rawBytes []byte, err error) {
-
- // TODO(dustin): Remove this method and rename readRawEncoded in its place.
-
- return vc.readRawEncoded()
-}
-
-// Format returns a string representation for the value.
-//
-// Where the type is not ASCII, `justFirst` indicates whether to just stringify
-// the first item in the slice (or return an empty string if the slice is
-// empty).
-//
-// Since this method lacks the information to process undefined-type tags (e.g.
-// byte-order, tag-ID, IFD type), it will return an error if attempted. See
-// `Undefined()`.
-func (vc *ValueContext) Format() (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawBytes, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- phrase, err := FormatFromBytes(rawBytes, vc.effectiveValueType(), false, vc.byteOrder)
- log.PanicIf(err)
-
- return phrase, nil
-}
-
-// FormatFirst is similar to `Format` but only gets and stringifies the first
-// item.
-func (vc *ValueContext) FormatFirst() (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawBytes, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- phrase, err := FormatFromBytes(rawBytes, vc.tagType, true, vc.byteOrder)
- log.PanicIf(err)
-
- return phrase, nil
-}
-
-// ReadBytes parses the encoded byte-array from the value-context.
-func (vc *ValueContext) ReadBytes() (value []byte, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseBytes(rawValue, vc.unitCount)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadAscii parses the encoded NUL-terminated ASCII string from the value-
-// context.
-func (vc *ValueContext) ReadAscii() (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseAscii(rawValue, vc.unitCount)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadAsciiNoNul parses the non-NUL-terminated encoded ASCII string from the
-// value-context.
-func (vc *ValueContext) ReadAsciiNoNul() (value string, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseAsciiNoNul(rawValue, vc.unitCount)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadShorts parses the list of encoded shorts from the value-context.
-func (vc *ValueContext) ReadShorts() (value []uint16, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseShorts(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadLongs parses the list of encoded, unsigned longs from the value-context.
-func (vc *ValueContext) ReadLongs() (value []uint32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseLongs(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadFloats parses the list of encoded, floats from the value-context.
-func (vc *ValueContext) ReadFloats() (value []float32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseFloats(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadDoubles parses the list of encoded, doubles from the value-context.
-func (vc *ValueContext) ReadDoubles() (value []float64, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseDoubles(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadRationals parses the list of encoded, unsigned rationals from the value-
-// context.
-func (vc *ValueContext) ReadRationals() (value []Rational, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseRationals(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadSignedLongs parses the list of encoded, signed longs from the value-context.
-func (vc *ValueContext) ReadSignedLongs() (value []int32, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseSignedLongs(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// ReadSignedRationals parses the list of encoded, signed rationals from the
-// value-context.
-func (vc *ValueContext) ReadSignedRationals() (value []SignedRational, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- rawValue, err := vc.readRawEncoded()
- log.PanicIf(err)
-
- value, err = parser.ParseSignedRationals(rawValue, vc.unitCount, vc.byteOrder)
- log.PanicIf(err)
-
- return value, nil
-}
-
-// Values knows how to resolve the given value. This value is always a list
-// (undefined-values aside), so we're named accordingly.
-//
-// Since this method lacks the information to process unknown-type tags (e.g.
-// byte-order, tag-ID, IFD type), it will return an error if attempted. See
-// `Undefined()`.
-func (vc *ValueContext) Values() (values interface{}, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- if vc.tagType == TypeByte {
- values, err = vc.ReadBytes()
- log.PanicIf(err)
- } else if vc.tagType == TypeAscii {
- values, err = vc.ReadAscii()
- log.PanicIf(err)
- } else if vc.tagType == TypeAsciiNoNul {
- values, err = vc.ReadAsciiNoNul()
- log.PanicIf(err)
- } else if vc.tagType == TypeShort {
- values, err = vc.ReadShorts()
- log.PanicIf(err)
- } else if vc.tagType == TypeLong {
- values, err = vc.ReadLongs()
- log.PanicIf(err)
- } else if vc.tagType == TypeRational {
- values, err = vc.ReadRationals()
- log.PanicIf(err)
- } else if vc.tagType == TypeSignedLong {
- values, err = vc.ReadSignedLongs()
- log.PanicIf(err)
- } else if vc.tagType == TypeSignedRational {
- values, err = vc.ReadSignedRationals()
- log.PanicIf(err)
- } else if vc.tagType == TypeFloat {
- values, err = vc.ReadFloats()
- log.PanicIf(err)
- } else if vc.tagType == TypeDouble {
- values, err = vc.ReadDoubles()
- log.PanicIf(err)
- } else if vc.tagType == TypeUndefined {
- log.Panicf("will not parse undefined-type value")
-
- // Never called.
- return nil, nil
- } else {
- log.Panicf("value of type [%s] is unparseable", vc.tagType)
- // Never called.
- return nil, nil
- }
-
- return values, nil
-}
-
-func init() {
- parser = new(Parser)
-}
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/value_encoder.go b/vendor/github.com/dsoprea/go-exif/v3/common/value_encoder.go
deleted file mode 100644
index 2cd26cc7b..000000000
--- a/vendor/github.com/dsoprea/go-exif/v3/common/value_encoder.go
+++ /dev/null
@@ -1,273 +0,0 @@
-package exifcommon
-
-import (
- "bytes"
- "math"
- "reflect"
- "time"
-
- "encoding/binary"
-
- "github.com/dsoprea/go-logging"
-)
-
-var (
- typeEncodeLogger = log.NewLogger("exif.type_encode")
-)
-
-// EncodedData encapsulates the compound output of an encoding operation.
-type EncodedData struct {
- Type TagTypePrimitive
- Encoded []byte
-
- // TODO(dustin): Is this really necessary? We might have this just to correlate to the incoming stream format (raw bytes and a unit-count both for incoming and outgoing).
- UnitCount uint32
-}
-
-// ValueEncoder knows how to encode values of every type to bytes.
-type ValueEncoder struct {
- byteOrder binary.ByteOrder
-}
-
-// NewValueEncoder returns a new ValueEncoder.
-func NewValueEncoder(byteOrder binary.ByteOrder) *ValueEncoder {
- return &ValueEncoder{
- byteOrder: byteOrder,
- }
-}
-
-func (ve *ValueEncoder) encodeBytes(value []uint8) (ed EncodedData, err error) {
- ed.Type = TypeByte
- ed.Encoded = []byte(value)
- ed.UnitCount = uint32(len(value))
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeAscii(value string) (ed EncodedData, err error) {
- ed.Type = TypeAscii
-
- ed.Encoded = []byte(value)
- ed.Encoded = append(ed.Encoded, 0)
-
- ed.UnitCount = uint32(len(ed.Encoded))
-
- return ed, nil
-}
-
-// encodeAsciiNoNul returns a string encoded as a byte-string without a trailing
-// NUL byte.
-//
-// Note that:
-//
-// 1. This type can not be automatically encoded using `Encode()`. The default
-// mode is to encode *with* a trailing NUL byte using `encodeAscii`. Only
-// certain undefined-type tags using an unterminated ASCII string and these
-// are exceptional in nature.
-//
-// 2. The presence of this method allows us to completely test the complimentary
-// no-nul parser.
-//
-func (ve *ValueEncoder) encodeAsciiNoNul(value string) (ed EncodedData, err error) {
- ed.Type = TypeAsciiNoNul
- ed.Encoded = []byte(value)
- ed.UnitCount = uint32(len(ed.Encoded))
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeShorts(value []uint16) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
- ed.Encoded = make([]byte, ed.UnitCount*2)
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- ve.byteOrder.PutUint16(ed.Encoded[i*2:(i+1)*2], value[i])
- }
-
- ed.Type = TypeShort
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeLongs(value []uint32) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
- ed.Encoded = make([]byte, ed.UnitCount*4)
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- ve.byteOrder.PutUint32(ed.Encoded[i*4:(i+1)*4], value[i])
- }
-
- ed.Type = TypeLong
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeFloats(value []float32) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
- ed.Encoded = make([]byte, ed.UnitCount*4)
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- ve.byteOrder.PutUint32(ed.Encoded[i*4:(i+1)*4], math.Float32bits(value[i]))
- }
-
- ed.Type = TypeFloat
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeDoubles(value []float64) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
- ed.Encoded = make([]byte, ed.UnitCount*8)
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- ve.byteOrder.PutUint64(ed.Encoded[i*8:(i+1)*8], math.Float64bits(value[i]))
- }
-
- ed.Type = TypeDouble
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeRationals(value []Rational) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
- ed.Encoded = make([]byte, ed.UnitCount*8)
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- ve.byteOrder.PutUint32(ed.Encoded[i*8+0:i*8+4], value[i].Numerator)
- ve.byteOrder.PutUint32(ed.Encoded[i*8+4:i*8+8], value[i].Denominator)
- }
-
- ed.Type = TypeRational
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeSignedLongs(value []int32) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
-
- b := bytes.NewBuffer(make([]byte, 0, 8*ed.UnitCount))
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- err := binary.Write(b, ve.byteOrder, value[i])
- log.PanicIf(err)
- }
-
- ed.Type = TypeSignedLong
- ed.Encoded = b.Bytes()
-
- return ed, nil
-}
-
-func (ve *ValueEncoder) encodeSignedRationals(value []SignedRational) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- ed.UnitCount = uint32(len(value))
-
- b := bytes.NewBuffer(make([]byte, 0, 8*ed.UnitCount))
-
- for i := uint32(0); i < ed.UnitCount; i++ {
- err := binary.Write(b, ve.byteOrder, value[i].Numerator)
- log.PanicIf(err)
-
- err = binary.Write(b, ve.byteOrder, value[i].Denominator)
- log.PanicIf(err)
- }
-
- ed.Type = TypeSignedRational
- ed.Encoded = b.Bytes()
-
- return ed, nil
-}
-
-// Encode returns bytes for the given value, infering type from the actual
-// value. This does not support `TypeAsciiNoNull` (all strings are encoded as
-// `TypeAscii`).
-func (ve *ValueEncoder) Encode(value interface{}) (ed EncodedData, err error) {
- defer func() {
- if state := recover(); state != nil {
- err = log.Wrap(state.(error))
- }
- }()
-
- switch t := value.(type) {
- case []byte:
- ed, err = ve.encodeBytes(t)
- log.PanicIf(err)
- case string:
- ed, err = ve.encodeAscii(t)
- log.PanicIf(err)
- case []uint16:
- ed, err = ve.encodeShorts(t)
- log.PanicIf(err)
- case []uint32:
- ed, err = ve.encodeLongs(t)
- log.PanicIf(err)
- case []float32:
- ed, err = ve.encodeFloats(t)
- log.PanicIf(err)
- case []float64:
- ed, err = ve.encodeDoubles(t)
- log.PanicIf(err)
- case []Rational:
- ed, err = ve.encodeRationals(t)
- log.PanicIf(err)
- case []int32:
- ed, err = ve.encodeSignedLongs(t)
- log.PanicIf(err)
- case []SignedRational:
- ed, err = ve.encodeSignedRationals(t)
- log.PanicIf(err)
- case time.Time:
- // For convenience, if the user doesn't want to deal with translation
- // semantics with timestamps.
-
- s := ExifFullTimestampString(t)
-
- ed, err = ve.encodeAscii(s)
- log.PanicIf(err)
- default:
- log.Panicf("value not encodable: [%s] [%v]", reflect.TypeOf(value), value)
- }
-
- return ed, nil
-}