libopenraw  0.3.7
metadata.cpp
1 /*
2  * libopenraw - metadata.cpp
3  *
4  * Copyright (C) 2020 Hubert Figuière
5  *
6  * This library is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation, either version 3 of
9  * the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "trace.hpp"
22 #include "rawfile.hpp"
23 #include "metadata.hpp"
24 
25 namespace OpenRaw {
26 
27 MetadataIterator::MetadataIterator(RawFile& rf)
28  : m_is_initialized(false)
29  , m_is_valid(true)
30  , m_next_ifd(0)
31 {
32  auto ifd = rf.mainIfd();
33  if (ifd) {
34  m_ifds.push_back(ifd);
35  auto subifds = ifd->getSubIFDs();
36  if (subifds) {
37  auto v = subifds.value();
38  m_ifds.insert(m_ifds.end(), v.begin(), v.end());
39  }
40  }
41  ifd = rf.exifIfd();
42  if (ifd) {
43  m_ifds.push_back(ifd);
44  }
45  ifd = rf.makerNoteIfd();
46  if (ifd) {
47  m_ifds.push_back(ifd);
48  }
49 }
50 
51 Internals::IfdDir::Ref MetadataIterator::nextIfd()
52 {
53  m_is_initialized = true;
54  if (m_ifds.size() <= m_next_ifd) {
55  return Internals::IfdDir::Ref();
56  }
57  auto ifd = m_ifds[m_next_ifd];
58  m_next_ifd++;
59  m_current_entry = ifd->entries().begin();
60  if (m_current_entry == ifd->entries().end()) {
61  LOGWARN("IFD is empty\n");
62  return nextIfd();
63  }
64  return ifd;
65 }
66 
67 bool MetadataIterator::next()
68 {
69  if (!m_is_valid) {
70  LOGDBG1("Invalid iterator\n");
71  return false;
72  }
73  LOGDBG1("next\n");
74  if (m_current_ifd) {
75  // We might already be at the end, check before incrementing.
76  // This is a corner case that led to an infinite loop.
77  if (m_current_entry != m_current_ifd->entries().end()) {
78  m_current_entry++;
79  }
80  if (m_current_entry == m_current_ifd->entries().end()) {
81  LOGDBG1("end of IFD, moving on\n");
82  m_current_ifd = nextIfd();
83  }
84  } else {
85  m_current_ifd = nextIfd();
86  }
87  if (!m_current_ifd) {
88  m_is_valid = false;
89  LOGDBG1("no more current ifd\n");
90  return false;
91  }
92 
93  return true;
94 }
95 
97 Internals::IfdDir::Ref MetadataIterator::getIfd() const
98 {
99  if (!(isInitialized() && isValid())) {
100  return Internals::IfdDir::Ref();
101  }
102  return m_current_ifd;
103 }
104 
106 Option<ExifTagType> MetadataIterator::getEntryType() const
107 {
108  if (!(isInitialized() && isValid())) {
109  return OptionNone();
110  }
111  return static_cast<ExifTagType>(m_current_entry->second->type());
112 }
113 
115 Option<uint16_t> MetadataIterator::getEntryId() const
116 {
117  if (!(isInitialized() && isValid())) {
118  return OptionNone();
119  }
120  return m_current_entry->first;
121 }
122 
123 MetaValue* MetadataIterator::getMetaValue() const
124 {
125  if (!(isInitialized() && isValid())) {
126  return nullptr;
127  }
128  return m_current_ifd->makeMetaValue(*(m_current_entry->second));
129 }
130 
131 }
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Definition: ifddir.hpp:56
Metadata value.
Definition: metavalue.hpp:35
Tag class to help create an empty Option.
Definition: option.hpp:41
An option type inspired by Rust.
Definition: option.hpp:47
ExifTagType
Definition: exif.h:271
Global namespace for libopenraw.
Definition: arwfile.cpp:29