libopenraw
ifdentry.hpp
1 /*
2  * libopenraw - ifdentry.hpp
3  *
4  * Copyright (C) 2006-2017 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 
22 #ifndef OR_INTERNALS_IFDENTRY_H
23 #define OR_INTERNALS_IFDENTRY_H
24 
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <string.h>
28 #include <sys/types.h>
29 
30 #include <exception>
31 #include <string>
32 #include <vector>
33 #include <memory>
34 
35 #include "exception.hpp"
36 #include "trace.hpp"
37 #include "endianutils.hpp"
38 #include "rawcontainer.hpp"
39 #include "ifd.hpp"
40 
41 namespace OpenRaw {
42 
43 class MetaValue;
44 
45 namespace Internals {
46 
47 class IfdFileContainer;
48 
49 class IfdEntry;
50 
52 template <typename T>
54 {
55  static const uint16_t type;
56  static const size_t size;
57  static T EL(const uint8_t* d, size_t len) noexcept;
58  static T BE(const uint8_t* d, size_t len) noexcept;
59  static T get(IfdEntry & e, uint32_t idx = 0, bool ignore_type = false)
60  noexcept(false);
61 };
62 
63 
64 template <>
65 inline uint8_t IfdTypeTrait<uint8_t>::EL(const uint8_t* b, size_t) noexcept
66 {
67  return *b;
68 }
69 
70 template <>
71 inline uint8_t IfdTypeTrait<uint8_t>::BE(const uint8_t* b, size_t) noexcept
72 {
73  return *b;
74 }
75 
76 
77 template <>
78 inline uint16_t IfdTypeTrait<uint16_t>::EL(const uint8_t* b, size_t) noexcept
79 {
80  return EL16(b);
81 }
82 
83 template <>
84 inline uint16_t IfdTypeTrait<uint16_t>::BE(const uint8_t* b, size_t) noexcept
85 {
86  return BE16(b);
87 }
88 
89 template <>
90 inline uint32_t IfdTypeTrait<uint32_t>::EL(const uint8_t* b, size_t) noexcept
91 {
92  return EL32(b);
93 }
94 
95 template <>
96 inline uint32_t IfdTypeTrait<uint32_t>::BE(const uint8_t* b, size_t) noexcept
97 {
98  return BE32(b);
99 }
100 
101 template <>
102 inline std::string IfdTypeTrait<std::string>::EL(const uint8_t* b, size_t len) noexcept
103 {
104  std::string s;
105  try {
106  s.assign((const char*)b, strnlen((const char*)b, len));
107  }
108  catch(...) {
109  }
110  return s;
111 }
112 
113 template <>
114 inline std::string IfdTypeTrait<std::string>::BE(const uint8_t* b, size_t len) noexcept
115 {
116  std::string s;
117  try {
118  s.assign((const char*)b, strnlen((const char*)b, len));
119  }
120  catch(...) {
121  }
122  return s;
123 }
124 
125 template <>
126 inline IFD::Rational IfdTypeTrait<IFD::Rational>::EL(const uint8_t* b, size_t) noexcept
127 {
128  IFD::Rational r;
129  r.num = EL32(b);
130  r.denom = EL32(b + 4);
131  return r;
132 }
133 
134 template <>
135 inline IFD::Rational IfdTypeTrait<IFD::Rational>::BE(const uint8_t* b, size_t) noexcept
136 {
137  IFD::Rational r;
138  r.num = BE32(b);
139  r.denom = BE32(b + 4);
140  return r;
141 }
142 
143 template <>
144 inline IFD::SRational IfdTypeTrait<IFD::SRational>::EL(const uint8_t* b, size_t) noexcept
145 {
146  IFD::SRational r;
147  r.num = EL32(b);
148  r.denom = EL32(b + 4);
149  return r;
150 }
151 
152 template <>
153 inline IFD::SRational IfdTypeTrait<IFD::SRational>::BE(const uint8_t* b, size_t) noexcept
154 {
155  IFD::SRational r;
156  r.num = BE32(b);
157  r.denom = BE32(b + 4);
158  return r;
159 }
160 
161 class IfdEntry
162 {
163 public:
165  typedef std::shared_ptr<IfdEntry> Ref;
166 
167  IfdEntry(uint16_t _id, int16_t _type, int32_t _count,
168  uint32_t _data,
169  IfdFileContainer &_container);
170  virtual ~IfdEntry();
171 
172  int16_t type() const noexcept
173  {
174  return m_type;
175  }
176 
178  uint32_t count() const noexcept
179  {
180  return m_count;
181  }
182 
186  off_t offset() noexcept
187  {
188  if (endian() == RawContainer::ENDIAN_LITTLE) {
189  return IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data, sizeof(uint32_t));
190  }
191  return IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data, sizeof(uint32_t));
192  }
193 
194  RawContainer::EndianType endian() const;
195 
196 public:
197  MetaValue* make_meta_value();
201  static size_t type_unit_size(IFD::ExifTagType _type);
207  bool loadData(size_t unit_size);
208 
209 
215  template <typename T>
217  {
218  try {
219  std::vector<T> array;
220  array.reserve(m_count);
221  for (uint32_t i = 0; i < m_count; i++) {
222  array.push_back(IfdTypeTrait<T>::get(*this, i));
223  }
224  return Option<decltype(array)>(array);
225  }
226  catch(const std::exception & e)
227  {
228  LOGERR("Exception: %s\n", e.what());
229  }
230  return Option<std::vector<T>>();
231  }
232  uint32_t getIntegerArrayItem(int idx);
233 
234 private:
235  uint16_t m_id;
236  uint16_t m_type;
237  uint32_t m_count;
238  uint32_t m_data;
239  bool m_loaded;
240  uint8_t *m_dataptr;
241  IfdFileContainer & m_container;
242  template <typename T> friend struct IfdTypeTrait;
243 
245  IfdEntry(const IfdEntry& f);
247  IfdEntry & operator=(const IfdEntry&);
248 
249 };
250 
251 
252 
261 template <typename T>
262 T IfdTypeTrait<T>::get(IfdEntry & e, uint32_t idx, bool ignore_type)
263  noexcept(false)
264 {
265  /* format undefined means that we don't check the type */
266  if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
267  if (e.m_type != IfdTypeTrait<T>::type) {
268  throw BadTypeException();
269  }
270  }
271  if (idx + 1 > e.m_count) {
272  throw OutOfRangeException();
273  }
274  if (!e.m_loaded) {
275  e.m_loaded = e.loadData(IfdTypeTrait<T>::size);
276  if (!e.m_loaded) {
277  throw TooBigException();
278  }
279  }
280  uint8_t *data;
281  if (e.m_dataptr == NULL) {
282  data = (uint8_t*)&e.m_data;
283  }
284  else {
285  data = e.m_dataptr;
286  }
287  data += (IfdTypeTrait<T>::size * idx);
288  T val;
289  if (e.endian() == RawContainer::ENDIAN_LITTLE) {
290  val = IfdTypeTrait<T>::EL(data, e.m_count - idx);
291  }
292  else {
293  val = IfdTypeTrait<T>::BE(data, e.m_count - idx);
294  }
295  return val;
296 }
297 
298 
299 }
300 }
301 
302 
303 /*
304  Local Variables:
305  mode:c++
306  c-file-style:"stroustrup"
307  c-file-offsets:((innamespace . 0))
308  tab-width:2
309  c-basic-offset:2
310  indent-tabs-mode:nil
311  fill-column:80
312  End:
313 */
314 #endif
315 
316 
uint32_t count() const noexcept
Definition: ifdentry.hpp:178
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
Definition: arwfile.cpp:30
static T get(IfdEntry &e, uint32_t idx=0, bool ignore_type=false) noexcept(false)
Definition: ifdentry.hpp:262
std::shared_ptr< IfdEntry > Ref
Definition: ifdentry.hpp:165
static const size_t size
Definition: ifdentry.hpp:56
off_t offset() noexcept
Definition: ifdentry.hpp:186
Option< std::vector< T > > getArray()
Definition: ifdentry.hpp:216
static const uint16_t type
Definition: ifdentry.hpp:55