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
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of 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, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
00019  */
00020 
00021 
00022 #ifndef _OPENRAW_INTERNALS_IFDENTRY_H
00023 #define _OPENRAW_INTERNALS_IFDENTRY_H
00024 
00025 #include <boost/shared_ptr.hpp>
00026 #include <libopenraw/types.h>
00027 
00028 #include "exception.h"
00029 #include "endianutils.h"
00030 #include "rawcontainer.h"
00031 #include "ifd.h"
00032 
00033 namespace OpenRaw {
00034     namespace Internals {
00035 
00036         class IFDFileContainer;
00037 
00038         class IFDEntry;
00039 
00041         template <typename T>
00042         struct IFDTypeTrait
00043         {
00044             static const uint16_t type; 
00045             static const size_t   size; 
00046             static T EL(const uint8_t* d);
00047             static T BE(const uint8_t* d);
00048             static T get(IFDEntry & e, uint32_t idx = 0, bool ignore_type = false)
00049                 throw (BadTypeException, OutOfRangeException, TooBigException);
00050         };
00051 
00052 
00053         template <>
00054         inline uint8_t IFDTypeTrait<uint8_t>::EL(const uint8_t* b)
00055         {
00056             return *b;
00057         }
00058 
00059         template <>
00060         inline uint8_t IFDTypeTrait<uint8_t>::BE(const uint8_t* b)
00061         {
00062             return *b;
00063         }
00064 
00065 
00066         template <>
00067         inline uint16_t IFDTypeTrait<uint16_t>::EL(const uint8_t* b)
00068         {
00069             return EL16(b);
00070         }
00071 
00072         template <>
00073         inline uint16_t IFDTypeTrait<uint16_t>::BE(const uint8_t* b)
00074         {
00075             return BE16(b);
00076         }
00077 
00078         template <>
00079         inline uint32_t IFDTypeTrait<uint32_t>::EL(const uint8_t* b)
00080         {
00081             return EL32(b);
00082         }
00083 
00084         template <>
00085         inline uint32_t IFDTypeTrait<uint32_t>::BE(const uint8_t* b)
00086         {
00087             return BE32(b);
00088         }
00089         
00090 #if defined(__APPLE_CC__)
00091 // Apple broken C++ needs this
00092         template <>
00093         inline unsigned long IFDTypeTrait<unsigned long>::EL(const uint8_t* b)
00094         {
00095             return EL32(b);
00096         }
00097 
00098         template <>
00099         inline unsigned long IFDTypeTrait<unsigned long>::BE(const uint8_t* b)
00100         {
00101             return BE32(b);
00102         }
00103 #endif
00104 
00105         class IFDEntry
00106         {
00107         public:
00109             typedef boost::shared_ptr<IFDEntry> Ref;
00110 
00111             IFDEntry(uint16_t _id, int16_t _type, int32_t _count, 
00112                      uint32_t _data,
00113                      IFDFileContainer &_container);
00114             virtual ~IFDEntry();
00115 
00116             int16_t type() const
00117                 {
00118                     return m_type;
00119                 }
00120             
00122             uint16_t count() const
00123                 {
00124                     return m_count;
00125                 }
00126 
00130             off_t offset()
00131                 {
00132                     if (endian() == RawContainer::ENDIAN_LITTLE) {
00133                         return IFDTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
00134                     }
00135                     return IFDTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
00136                 }
00137 
00138             RawContainer::EndianType endian() const;
00139 
00140         public:
00146             bool loadData(size_t unit_size);
00147 
00148 
00154             template <typename T>
00155             void getArray(std::vector<T> & array)
00156                 {
00157                     try {
00158                         array.reserve(m_count);
00159                         for (uint32_t i = 0; i < m_count; i++) {
00160                             array.push_back(IFDTypeTrait<T>::get(*this, i));
00161                         }
00162                     }
00163                     catch(std::exception & e)
00164                     {
00165                         throw e;
00166                     }
00167                 }
00168 
00169 
00170         private:
00171             uint16_t m_id;
00172             uint16_t m_type;
00173             uint32_t m_count;
00174             uint32_t m_data; 
00175             bool m_loaded;
00176             uint8_t *m_dataptr;
00177             IFDFileContainer & m_container;
00178             template <typename T> friend struct IFDTypeTrait;
00179 
00181             IFDEntry(const IFDEntry& f);
00183             IFDEntry & operator=(const IFDEntry&);
00184 
00185         };
00186 
00187 
00188 
00197         template <typename T> 
00198         T IFDTypeTrait<T>::get(IFDEntry & e, uint32_t idx, bool ignore_type)
00199             throw (BadTypeException, OutOfRangeException, TooBigException)
00200         {
00201             /* format undefined means that we don't check the type */
00202             if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
00203                 if (e.m_type != IFDTypeTrait<T>::type) {
00204                     throw BadTypeException();
00205                 }
00206             }
00207             if (idx + 1 > e.m_count) {
00208                 throw OutOfRangeException();
00209             }
00210             if (!e.m_loaded) {
00211                 e.m_loaded = e.loadData(IFDTypeTrait<T>::size);
00212                 if (!e.m_loaded) {
00213                     throw TooBigException();
00214                 }
00215             }
00216             uint8_t *data;
00217             if (e.m_dataptr == NULL) {
00218                 data = (uint8_t*)&e.m_data;
00219             }
00220             else {
00221                 data = e.m_dataptr;
00222             }
00223             data += (IFDTypeTrait<T>::size * idx);
00224             T val;
00225             if (e.endian() == RawContainer::ENDIAN_LITTLE) {
00226                 val = IFDTypeTrait<T>::EL(data);
00227             }
00228             else {
00229                 val = IFDTypeTrait<T>::BE(data);
00230             }
00231             return val;
00232         }
00233 
00234     }
00235 }
00236 
00237 
00238 #endif
00239 
00240 

Generated on Sun Mar 23 09:28:21 2008 for libopenraw by  doxygen 1.5.5