Added an ARM cross-compile build to Travis.
[platform/upstream/libexif.git] / contrib / c++ / exif.hxx
1 /* exif.hxx
2  *
3  * Copyright  2002,2003 Hans Meine <hans_meine@gmx.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, 
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA.
19  */
20
21 #ifndef EXIF_HXX
22 #define EXIF_HXX
23
24 #include <libexif/exif-entry.h>
25 #include <libexif/exif-content.h>
26 #include <libexif/exif-ifd.h>
27 #include <libexif/exif-data.h>
28 #include <libexif/exif-format.h>
29 #include <libexif/exif-utils.h>
30 #include <stdexcept>
31 #include <string>
32
33 namespace Exif {
34
35 #ifndef EXIF_NO_EXCEPTIONS
36 struct InvalidIndex : std::runtime_error
37 {
38     InvalidIndex(const std::string& s)
39     : std::runtime_error(s) {}
40 };
41
42 struct InvalidFormat : std::runtime_error
43 {
44     InvalidFormat(const std::string& s)
45     : std::runtime_error(s) {}
46 };
47
48 struct IOError : std::runtime_error
49 {
50     IOError(const std::string& s)
51     : std::runtime_error(s) {}
52 };
53 #endif // EXIF_NO_EXCEPTIONS
54
55 struct Entry
56 {
57     ExifEntry *entry_;
58
59         // construct an empty entry, FIXME: is this needed in the public API?
60     Entry()
61     : entry_(exif_entry_new())
62     {}
63
64         // construct an entry for the given tag
65     Entry(ExifTag tag)
66     : entry_(exif_entry_new())
67     {
68         exif_entry_initialize(entry_, tag);
69     }
70
71         // copy constructor
72     Entry(Entry const &other)
73     : entry_(other.entry_)
74     {
75         exif_entry_ref(entry_);
76     }
77
78         // internal, do not use directly
79     Entry(ExifEntry *entry)
80     : entry_(entry)
81     {
82         exif_entry_ref(entry_);
83     }
84
85     ~Entry()
86     {
87         exif_entry_unref(entry_);
88     }
89
90     Entry &operator=(Entry const &other)
91     {
92         exif_entry_unref(entry_);
93         entry_ = other.entry_;
94         exif_entry_ref(entry_);
95         return *this;
96     }
97
98     ExifTag tag() const
99     {
100         return entry_->tag;
101     }
102
103 /*
104     void setTag(ExifTag tag)
105     {
106         entry_->tag = tag;
107     }
108 */
109
110     ExifFormat format() const
111     {
112         return entry_->format;
113     }
114
115 /*
116     void setFormat(ExifFormat format)
117     {
118         entry_->format = format;
119     }
120 */
121
122     unsigned long components() const
123     {
124         return entry_->components;
125     }
126
127 /*
128     void setComponents(unsigned long components)
129     {
130         entry_->components = components;
131     }
132
133     void initialize(ExifTag tag)
134     {
135         exif_entry_initialize(entry_, tag);
136     }
137 */
138
139     ExifByte getByte(unsigned int index) const
140     {
141 #ifndef EXIF_NO_EXCEPTIONS
142         if(entry_->format != EXIF_FORMAT_BYTE)
143             throw InvalidFormat(
144                 "Exif::Entry::getByte(): Format is not EXIF_FORMAT_BYTE");
145         if(index >= components())
146             throw InvalidIndex(
147                 "Exif::getByte: component index out of range");
148 #endif
149         return *(entry_->data
150                  + index * exif_format_get_size(entry_->format));
151     }
152
153     const ExifAscii getAscii() const
154     {
155 #ifndef EXIF_NO_EXCEPTIONS
156         if(entry_->format != EXIF_FORMAT_ASCII)
157             throw InvalidFormat(
158                 "Exif::Entry::getAscii(): Format is not EXIF_FORMAT_ASCII");
159 #endif
160         return (ExifAscii)entry_->data;
161     }
162
163     ExifShort getShort(unsigned int index) const
164     {
165 #ifndef EXIF_NO_EXCEPTIONS
166         if(entry_->format != EXIF_FORMAT_SHORT)
167             throw InvalidFormat(
168                 "Exif::Entry::getShort(): Format is not EXIF_FORMAT_SHORT");
169         if(index >= components())
170             throw InvalidIndex(
171                 "Exif::getShort: component index out of range");
172 #endif
173         return exif_get_short(entry_->data
174                               + index * exif_format_get_size(entry_->format),
175                               exif_data_get_byte_order(entry_->parent->parent));
176     }
177
178     ExifLong getLong(unsigned int index) const
179     {
180 #ifndef EXIF_NO_EXCEPTIONS
181         if(entry_->format != EXIF_FORMAT_LONG)
182             throw InvalidFormat(
183                 "Exif::Entry::getLong(): Format is not EXIF_FORMAT_LONG");
184         if(index >= components())
185             throw InvalidIndex(
186                 "Exif::getLong: component index out of range");
187 #endif
188         return exif_get_long(entry_->data
189                              + index * exif_format_get_size(entry_->format),
190                              exif_data_get_byte_order(entry_->parent->parent));
191     }
192
193     ExifSLong getSLong(unsigned int index) const
194     {
195 #ifndef EXIF_NO_EXCEPTIONS
196         if(entry_->format != EXIF_FORMAT_SLONG)
197             throw InvalidFormat(
198                 "Exif::Entry::getSLong(): Format is not EXIF_FORMAT_SLONG");
199         if(index >= components())
200             throw InvalidIndex(
201                 "Exif::getSLong: component index out of range");
202 #endif
203         return exif_get_slong(entry_->data
204                               + index * exif_format_get_size(entry_->format),
205                               exif_data_get_byte_order(entry_->parent->parent));
206     }
207
208     ExifRational getRational(unsigned int index) const
209     {
210 #ifndef EXIF_NO_EXCEPTIONS
211         if(entry_->format != EXIF_FORMAT_RATIONAL)
212             throw InvalidFormat(
213                 "Exif::Entry::getRational(): Format is not EXIF_FORMAT_RATIONAL");
214         if(index >= components())
215             throw InvalidIndex(
216                 "Exif::getRational: component index out of range");
217 #endif
218         return exif_get_rational(entry_->data
219                                  + index * exif_format_get_size(entry_->format),
220                                  exif_data_get_byte_order(entry_->parent->parent));
221     }
222
223     ExifSRational getSRational(unsigned int index) const
224     {
225 #ifndef EXIF_NO_EXCEPTIONS
226         if(entry_->format != EXIF_FORMAT_SRATIONAL)
227             throw InvalidFormat(
228                 "Exif::Entry::getSRational(): Format is not EXIF_FORMAT_SRATIONAL");
229         if(index >= components())
230             throw InvalidIndex(
231                 "Exif::getSRational: component index out of range");
232 #endif
233         return exif_get_srational(entry_->data
234                                   + index * exif_format_get_size(entry_->format),
235                                   exif_data_get_byte_order(entry_->parent->parent));
236     }
237
238     void setByte(unsigned int index, ExifByte value) const
239     {
240 #ifndef EXIF_NO_EXCEPTIONS
241         if(entry_->format != EXIF_FORMAT_BYTE)
242             throw InvalidFormat(
243                 "Exif::Entry::setByte(): Format is not EXIF_FORMAT_BYTE");
244         if(index >= components())
245             throw InvalidIndex(
246                 "Exif::setByte: component index out of range");
247 #endif
248         *(entry_->data
249           + index * exif_format_get_size(entry_->format)) = value;
250     }
251
252 /*
253     const ExifAscii setAscii() const
254     {
255 #ifndef EXIF_NO_EXCEPTIONS
256         if(entry_->format != EXIF_FORMAT_ASCII)
257             throw InvalidFormat(
258                 "Exif::Entry::setAscii(): Format is not EXIF_FORMAT_ASCII");
259 #endif
260         return (ExifAscii)entry_->data;
261     }
262 */
263
264     void setShort(unsigned int index, ExifShort value) const
265     {
266 #ifndef EXIF_NO_EXCEPTIONS
267         if(entry_->format != EXIF_FORMAT_SHORT)
268             throw InvalidFormat(
269                 "Exif::Entry::setShort(): Format is not EXIF_FORMAT_SHORT");
270         if(index >= components())
271             throw InvalidIndex(
272                 "Exif::setShort: component index out of range");
273 #endif
274         return exif_set_short(entry_->data
275                               + index * exif_format_get_size(entry_->format),
276                               exif_data_get_byte_order(entry_->parent->parent),
277                               value);
278     }
279
280     void setLong(unsigned int index, ExifLong value) const
281     {
282 #ifndef EXIF_NO_EXCEPTIONS
283         if(entry_->format != EXIF_FORMAT_LONG)
284             throw InvalidFormat(
285                 "Exif::Entry::setLong(): Format is not EXIF_FORMAT_LONG");
286         if(index >= components())
287             throw InvalidIndex(
288                 "Exif::setLong: component index out of range");
289 #endif
290         return exif_set_long(entry_->data
291                              + index * exif_format_get_size(entry_->format),
292                              exif_data_get_byte_order(entry_->parent->parent),
293                              value);
294     }
295
296     void setSLong(unsigned int index, ExifSLong value) const
297     {
298 #ifndef EXIF_NO_EXCEPTIONS
299         if(entry_->format != EXIF_FORMAT_SLONG)
300             throw InvalidFormat(
301                 "Exif::Entry::setSLong(): Format is not EXIF_FORMAT_SLONG");
302         if(index >= components())
303             throw InvalidIndex(
304                 "Exif::setSLong: component index out of range");
305 #endif
306         return exif_set_slong(entry_->data
307                               + index * exif_format_get_size(entry_->format),
308                               exif_data_get_byte_order(entry_->parent->parent),
309                               value);
310     }
311
312     void setRational(unsigned int index, ExifRational value) const
313     {
314 #ifndef EXIF_NO_EXCEPTIONS
315         if(entry_->format != EXIF_FORMAT_RATIONAL)
316             throw InvalidFormat(
317                 "Exif::Entry::setRational(): Format is not EXIF_FORMAT_RATIONAL");
318         if(index >= components())
319             throw InvalidIndex(
320                 "Exif::setRational: component index out of range");
321 #endif
322         return exif_set_rational(entry_->data
323                                  + index * exif_format_get_size(entry_->format),
324                                  exif_data_get_byte_order(entry_->parent->parent),
325                                  value);
326     }
327
328     void setSRational(unsigned int index, ExifSRational value) const
329     {
330 #ifndef EXIF_NO_EXCEPTIONS
331         if(entry_->format != EXIF_FORMAT_SRATIONAL)
332             throw InvalidFormat(
333                 "Exif::Entry::setSRational(): Format is not EXIF_FORMAT_SRATIONAL");
334         if(index >= components())
335             throw InvalidIndex(
336                 "Exif::setSRational: component index out of range");
337 #endif
338         return exif_set_srational(entry_->data
339                                   + index * exif_format_get_size(entry_->format),
340                                   exif_data_get_byte_order(entry_->parent->parent),
341                                   value);
342     }
343
344     const char *value()
345     {
346         return exif_entry_get_value(entry_);
347     }
348
349     const char *briefValue()
350     {
351         return exif_entry_get_value_brief(entry_);
352     }
353
354     void dump(unsigned int indent = 0) const
355     {
356         exif_entry_dump(entry_, indent);
357     }
358 };
359
360 struct Content
361 {
362     ExifContent *content_;
363
364     Content()
365     : content_(exif_content_new())
366     {}
367
368     Content(Content const &other)
369     : content_(other.content_)
370     {
371         exif_content_ref(content_);
372     }
373
374         // internal, do not use directly
375     Content(ExifContent *content)
376     : content_(content)
377     {
378         exif_content_ref(content_);
379     }
380
381     ~Content()
382     {
383         exif_content_unref(content_);
384     }
385
386     Content &operator=(Content const &other)
387     {
388         exif_content_unref(content_);
389         content_ = other.content_;
390         exif_content_ref(content_);
391         return *this;
392     }
393
394     Entry operator[](ExifTag tag)
395     {
396         ExifEntry *result = exif_content_get_entry(content_, tag);
397         if(result)
398             return Entry(result);
399 #ifndef EXIF_NO_EXCEPTIONS
400         throw InvalidIndex(
401             "Exif::Content: IFD does not contain given tag");
402 #endif
403         return Entry();
404     }
405
406     Entry operator[](unsigned int index)
407     {
408         if(index < size())
409             return Entry(content_->entries[index]);
410 #ifndef EXIF_NO_EXCEPTIONS
411         throw InvalidIndex(
412             "Exif::Content: numeric entry index out of range");
413 #endif // EXIF_NO_EXCEPTIONS
414         return Entry();
415     }
416
417     unsigned int size() const
418     {
419         // FIXME: content_ should never be NULL, so this is unneeded!?
420         return content_ ? content_->count : 0;
421     }
422
423     void add(Entry &entry)
424     {
425         exif_content_add_entry(content_, entry.entry_);
426     }
427
428     void remove(Entry &entry)
429     {
430         exif_content_remove_entry(content_, entry.entry_);
431     }
432
433         // for your convenience
434     const char *value(ExifTag tag)
435     {
436         return exif_content_get_value(content_, tag);
437     }
438
439         // for your convenience
440     const char *briefValue(ExifTag tag)
441     {
442         return exif_content_get_value_brief(content_, tag);
443     }
444
445     void dump(unsigned int indent = 0) const
446     {
447         exif_content_dump(content_, indent);
448     }
449 };
450
451 struct Data
452 {
453     ExifData *data_;
454
455     Data()
456     : data_(exif_data_new())
457     {}
458
459     Data(const char *path, bool *success = 0)
460     : data_(exif_data_new_from_file(path))
461     {
462         if(success)
463             *success = data_;
464 #ifndef EXIF_NO_EXCEPTIONS
465         else
466             if(!data_)
467                 throw IOError("Exif::Data: Could not load file");
468 #endif // EXIF_NO_EXCEPTIONS
469         if(!data_)
470             exif_data_new();
471     }
472
473     Data(const unsigned char *data,
474          unsigned int size)
475     : data_(exif_data_new_from_data(data, size))
476     {}
477
478     Data(Data const &other)
479     : data_(other.data_)
480     {
481         exif_data_ref(data_);
482     }
483
484     ~Data()
485     {
486         exif_data_unref(data_);
487     }
488
489     Data &operator=(Data const &other)
490     {
491         exif_data_unref(data_);
492         data_ = other.data_;
493         exif_data_ref(data_);
494         return *this;
495     }
496
497     void save(unsigned char **d, unsigned int *size)
498     {
499         exif_data_save_data(data_, d, size);
500     }
501
502     unsigned int size() const
503     {
504         return EXIF_IFD_COUNT;
505     }
506
507     Content operator[](unsigned int index)
508     {
509         if(index < size())
510             return Content(data_->ifd[index]);
511 #ifndef EXIF_NO_EXCEPTIONS
512         throw InvalidIndex(
513             "Exif::Data: IFD index out of range");
514 #endif // EXIF_NO_EXCEPTIONS
515         return Content();
516     }
517
518     ExifByteOrder byteOrder() const
519     {
520         return exif_data_get_byte_order(data_);
521     }
522
523     void setByteOrder(ExifByteOrder bo) const
524     {
525         exif_data_set_byte_order(data_, bo);
526     }
527
528     void dump()
529     {
530         exif_data_dump(data_);
531     }
532 };
533
534 } // namespace Exif
535
536 #endif // EXIF_HXX