ifdentry.h

00001 /*
00002  * libopenraw - ifdentry.h
00003  *
00004  * Copyright (C) 2006-2008 Hubert Figuiere
00005  *
00006  * This library is free software: you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation, either version 3 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 
00022 #ifndef _OPENRAW_INTERNALS_IFDENTRY_H
00023 #define _OPENRAW_INTERNALS_IFDENTRY_H
00024 
00025 #include <vector>
00026 #include <boost/shared_ptr.hpp>
00027 #include <libopenraw/types.h>
00028 
00029 #include "exception.h"
00030 #include "endianutils.h"
00031 #include "rawcontainer.h"
00032 #include "ifd.h"
00033 
00034 namespace OpenRaw {
00035     namespace Internals {
00036 
00037         class IFDFileContainer;
00038 
00039         class IFDEntry;
00040 
00042         template <typename T>
00043         struct IFDTypeTrait
00044         {
00045             static const uint16_t type; 
00046             static const size_t   size; 
00047             static T EL(const uint8_t* d);
00048             static T BE(const uint8_t* d);
00049             static T get(IFDEntry & e, uint32_t idx = 0, bool ignore_type = false)
00050                 throw (BadTypeException, OutOfRangeException, TooBigException);
00051         };
00052 
00053 
00054         template <>
00055         inline uint8_t IFDTypeTrait<uint8_t>::EL(const uint8_t* b)
00056         {
00057             return *b;
00058         }
00059 
00060         template <>
00061         inline uint8_t IFDTypeTrait<uint8_t>::BE(const uint8_t* b)
00062         {
00063             return *b;
00064         }
00065 
00066 
00067         template <>
00068         inline uint16_t IFDTypeTrait<uint16_t>::EL(const uint8_t* b)
00069         {
00070             return EL16(b);
00071         }
00072 
00073         template <>
00074         inline uint16_t IFDTypeTrait<uint16_t>::BE(const uint8_t* b)
00075         {
00076             return BE16(b);
00077         }
00078 
00079         template <>
00080         inline uint32_t IFDTypeTrait<uint32_t>::EL(const uint8_t* b)
00081         {
00082             return EL32(b);
00083         }
00084 
00085         template <>
00086         inline uint32_t IFDTypeTrait<uint32_t>::BE(const uint8_t* b)
00087         {
00088             return BE32(b);
00089         }
00090 
00091         template <>
00092         inline std::string IFDTypeTrait<std::string>::EL(const uint8_t* b)
00093         {
00094             return std::string((const char*)b);
00095         }
00096 
00097         template <>
00098         inline std::string IFDTypeTrait<std::string>::BE(const uint8_t* b)
00099         {
00100             return std::string((const char*)b);
00101         }
00102         
00103 #if defined(__APPLE_CC__)
00104 // Apple broken C++ needs this
00105         template <>
00106         inline unsigned long IFDTypeTrait<unsigned long>::EL(const uint8_t* b)
00107         {
00108             return EL32(b);
00109         }
00110 
00111         template <>
00112         inline unsigned long IFDTypeTrait<unsigned long>::BE(const uint8_t* b)
00113         {
00114             return BE32(b);
00115         }
00116 #endif
00117 
00118         class IFDEntry
00119         {
00120         public:
00122             typedef boost::shared_ptr<IFDEntry> Ref;
00123 
00124             IFDEntry(uint16_t _id, int16_t _type, int32_t _count, 
00125                      uint32_t _data,
00126                      IFDFileContainer &_container);
00127             virtual ~IFDEntry();
00128 
00129             int16_t type() const
00130                 {
00131                     return m_type;
00132                 }
00133             
00135             uint16_t count() const
00136                 {
00137                     return m_count;
00138                 }
00139 
00143             off_t offset()
00144                 {
00145                     if (endian() == RawContainer::ENDIAN_LITTLE) {
00146                         return IFDTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
00147                     }
00148                     return IFDTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
00149                 }
00150 
00151             RawContainer::EndianType endian() const;
00152 
00153         public:
00159             bool loadData(size_t unit_size);
00160 
00161 
00167             template <typename T>
00168             void getArray(std::vector<T> & array)
00169                 {
00170                     try {
00171                         array.reserve(m_count);
00172                         for (uint32_t i = 0; i < m_count; i++) {
00173                             array.push_back(IFDTypeTrait<T>::get(*this, i));
00174                         }
00175                     }
00176                     catch(std::exception & e)
00177                     {
00178                         throw e;
00179                     }
00180                 }
00181 
00182 
00183         private:
00184             uint16_t m_id;
00185             uint16_t m_type;
00186             uint32_t m_count;
00187             uint32_t m_data; 
00188             bool m_loaded;
00189             uint8_t *m_dataptr;
00190             IFDFileContainer & m_container;
00191             template <typename T> friend struct IFDTypeTrait;
00192 
00194             IFDEntry(const IFDEntry& f);
00196             IFDEntry & operator=(const IFDEntry&);
00197 
00198         };
00199 
00200 
00201 
00210         template <typename T> 
00211         T IFDTypeTrait<T>::get(IFDEntry & e, uint32_t idx, bool ignore_type)
00212             throw (BadTypeException, OutOfRangeException, TooBigException)
00213         {
00214             /* format undefined means that we don't check the type */
00215             if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
00216                 if (e.m_type != IFDTypeTrait<T>::type) {
00217                     throw BadTypeException();
00218                 }
00219             }
00220             if (idx + 1 > e.m_count) {
00221                 throw OutOfRangeException();
00222             }
00223             if (!e.m_loaded) {
00224                 e.m_loaded = e.loadData(IFDTypeTrait<T>::size);
00225                 if (!e.m_loaded) {
00226                     throw TooBigException();
00227                 }
00228             }
00229             uint8_t *data;
00230             if (e.m_dataptr == NULL) {
00231                 data = (uint8_t*)&e.m_data;
00232             }
00233             else {
00234                 data = e.m_dataptr;
00235             }
00236             data += (IFDTypeTrait<T>::size * idx);
00237             T val;
00238             if (e.endian() == RawContainer::ENDIAN_LITTLE) {
00239                 val = IFDTypeTrait<T>::EL(data);
00240             }
00241             else {
00242                 val = IFDTypeTrait<T>::BE(data);
00243             }
00244             return val;
00245         }
00246 
00247     }
00248 }
00249 
00250 
00251 /*
00252   Local Variables:
00253   mode:c++
00254   c-file-style:"stroustrup"
00255   c-file-offsets:((innamespace . 0))
00256   indent-tabs-mode:nil
00257   fill-column:80
00258   End:
00259 */
00260 #endif
00261 
00262 

Generated on Sat Aug 15 17:27:04 2009 for libopenraw by  doxygen 1.5.9