libopenraw
ifdentry.h
1 /*
2  * libopenraw - ifdentry.h
3  *
4  * Copyright (C) 2006-2008 Hubert Figuiere
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 _OPENRAW_INTERNALS_IFDENTRY_H
23 #define _OPENRAW_INTERNALS_IFDENTRY_H
24 
25 #include <vector>
26 #include <boost/shared_ptr.hpp>
27 #include <libopenraw/types.h>
28 
29 #include "exception.h"
30 #include "endianutils.h"
31 #include "rawcontainer.h"
32 #include "ifd.h"
33 
34 namespace OpenRaw {
35  namespace Internals {
36 
37  class IFDFileContainer;
38 
39  class IFDEntry;
40 
42  template <typename T>
43  struct IFDTypeTrait
44  {
45  static const uint16_t type;
46  static const size_t size;
47  static T EL(const uint8_t* d);
48  static T BE(const uint8_t* d);
49  static T get(IFDEntry & e, uint32_t idx = 0, bool ignore_type = false)
51  };
52 
53 
54  template <>
55  inline uint8_t IFDTypeTrait<uint8_t>::EL(const uint8_t* b)
56  {
57  return *b;
58  }
59 
60  template <>
61  inline uint8_t IFDTypeTrait<uint8_t>::BE(const uint8_t* b)
62  {
63  return *b;
64  }
65 
66 
67  template <>
68  inline uint16_t IFDTypeTrait<uint16_t>::EL(const uint8_t* b)
69  {
70  return EL16(b);
71  }
72 
73  template <>
74  inline uint16_t IFDTypeTrait<uint16_t>::BE(const uint8_t* b)
75  {
76  return BE16(b);
77  }
78 
79  template <>
80  inline uint32_t IFDTypeTrait<uint32_t>::EL(const uint8_t* b)
81  {
82  return EL32(b);
83  }
84 
85  template <>
86  inline uint32_t IFDTypeTrait<uint32_t>::BE(const uint8_t* b)
87  {
88  return BE32(b);
89  }
90 
91  template <>
92  inline std::string IFDTypeTrait<std::string>::EL(const uint8_t* b)
93  {
94  return std::string((const char*)b);
95  }
96 
97  template <>
98  inline std::string IFDTypeTrait<std::string>::BE(const uint8_t* b)
99  {
100  return std::string((const char*)b);
101  }
102 
103 #if defined(__APPLE_CC__)
104 // Apple broken C++ needs this
105  template <>
106  inline unsigned long IFDTypeTrait<unsigned long>::EL(const uint8_t* b)
107  {
108  return EL32(b);
109  }
110 
111  template <>
112  inline unsigned long IFDTypeTrait<unsigned long>::BE(const uint8_t* b)
113  {
114  return BE32(b);
115  }
116 #endif
117 
118  class IFDEntry
119  {
120  public:
122  typedef boost::shared_ptr<IFDEntry> Ref;
123 
124  IFDEntry(uint16_t _id, int16_t _type, int32_t _count,
125  uint32_t _data,
126  IFDFileContainer &_container);
127  virtual ~IFDEntry();
128 
129  int16_t type() const
130  {
131  return m_type;
132  }
133 
135  uint16_t count() const
136  {
137  return m_count;
138  }
139 
143  off_t offset()
144  {
145  if (endian() == RawContainer::ENDIAN_LITTLE) {
146  return IFDTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
147  }
148  return IFDTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
149  }
150 
151  RawContainer::EndianType endian() const;
152 
153  public:
159  bool loadData(size_t unit_size);
160 
161 
167  template <typename T>
168  void getArray(std::vector<T> & array)
169  {
170  try {
171  array.reserve(m_count);
172  for (uint32_t i = 0; i < m_count; i++) {
173  array.push_back(IFDTypeTrait<T>::get(*this, i));
174  }
175  }
176  catch(std::exception & e)
177  {
178  throw e;
179  }
180  }
181 
182 
183  private:
184  uint16_t m_id;
185  uint16_t m_type;
186  uint32_t m_count;
187  uint32_t m_data;
188  bool m_loaded;
189  uint8_t *m_dataptr;
190  IFDFileContainer & m_container;
191  template <typename T> friend struct IFDTypeTrait;
192 
194  IFDEntry(const IFDEntry& f);
196  IFDEntry & operator=(const IFDEntry&);
197 
198  };
199 
200 
201 
210  template <typename T>
211  T IFDTypeTrait<T>::get(IFDEntry & e, uint32_t idx, bool ignore_type)
213  {
214  /* format undefined means that we don't check the type */
215  if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
216  if (e.m_type != IFDTypeTrait<T>::type) {
217  throw BadTypeException();
218  }
219  }
220  if (idx + 1 > e.m_count) {
221  throw OutOfRangeException();
222  }
223  if (!e.m_loaded) {
224  e.m_loaded = e.loadData(IFDTypeTrait<T>::size);
225  if (!e.m_loaded) {
226  throw TooBigException();
227  }
228  }
229  uint8_t *data;
230  if (e.m_dataptr == NULL) {
231  data = (uint8_t*)&e.m_data;
232  }
233  else {
234  data = e.m_dataptr;
235  }
236  data += (IFDTypeTrait<T>::size * idx);
237  T val;
238  if (e.endian() == RawContainer::ENDIAN_LITTLE) {
239  val = IFDTypeTrait<T>::EL(data);
240  }
241  else {
242  val = IFDTypeTrait<T>::BE(data);
243  }
244  return val;
245  }
246 
247  }
248 }
249 
250 
251 /*
252  Local Variables:
253  mode:c++
254  c-file-style:"stroustrup"
255  c-file-offsets:((innamespace . 0))
256  indent-tabs-mode:nil
257  fill-column:80
258  End:
259 */
260 #endif
261 
262