imagingmodules/exiflib/src/ExifEndian.cpp
changeset 0 469c91dae73b
equal deleted inserted replaced
-1:000000000000 0:469c91dae73b
       
     1 /*
       
     2 * Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Exif data parser, that can parse both Little and Big endian 
       
    15 *                formats
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "ExifEndian.h"
       
    22 #include "ExifCommon.h"
       
    23 
       
    24 // ============================ CLASS CExifEndianBase ==========================
       
    25 // ============================ MEMBER FUNCTIONS ===============================
       
    26 
       
    27 // -----------------------------------------------------------------------------
       
    28 // CExifEndianBase::CExifEndianBase
       
    29 // C++ default constructor can NOT contain any code, that
       
    30 // might leave.
       
    31 // -----------------------------------------------------------------------------
       
    32 //
       
    33 CExifEndianBase::CExifEndianBase()
       
    34     {
       
    35     }
       
    36 
       
    37 // -----------------------------------------------------------------------------
       
    38 // CExifEndianBase::ConstructL
       
    39 // Symbian 2nd phase constructor can leave.
       
    40 // -----------------------------------------------------------------------------
       
    41 //
       
    42 void CExifEndianBase::ConstructL()
       
    43     {
       
    44     }
       
    45 
       
    46 // -----------------------------------------------------------------------------
       
    47 // CExifEndianBase::NewBaseL
       
    48 // Two-phased constructor. Instantiates and returns relevant derived class.
       
    49 // -----------------------------------------------------------------------------
       
    50 //
       
    51 CExifEndianBase* CExifEndianBase::NewBaseL( 
       
    52     const TUint8* aExifDataPtr, 
       
    53     TUint aDataLength, 
       
    54     TBool aIsExif )
       
    55     {
       
    56     // 
       
    57     // Parse header. 
       
    58     // Find SOI (FFD8 )
       
    59     // ptr = SOI pos.
       
    60     // Then check the following 10 bytes:
       
    61     // APP1 Marker (FFE1) + APP1 Length (no check) + Identifier ("Exif"00) + 
       
    62     // Pad (00) (no check)
       
    63 
       
    64     //TUint8* dataStartPtr = CONST_CAST( TUint8*, aExifData.Ptr() ); 
       
    65     if ( !aExifDataPtr )
       
    66         {
       
    67         User::Leave( KErrGeneral );
       
    68         }
       
    69     TUint8* ptr = CONST_CAST( TUint8*, aExifDataPtr ) - 1;
       
    70     TUint8 *pE = CONST_CAST( TUint8*, aExifDataPtr ) + aDataLength; 
       
    71 
       
    72     // Locate the SOI marker.
       
    73     do
       
    74         {
       
    75         if ( ptr == pE )
       
    76             {
       
    77             User::Leave( KErrCorrupt );
       
    78             }
       
    79         } 
       
    80     while ( *++ptr != KMarkerStart );
       
    81     
       
    82     if ( *( ptr + 1 ) != KSoiEnd )
       
    83         {
       
    84         User::Leave( KErrCorrupt );
       
    85         }
       
    86     // ptr is now at SOI.
       
    87 
       
    88     // If original is Exif, check whether it is Little- or Big-endian.
       
    89     // Otherwise create Little-endian reader.
       
    90     if ( aIsExif )
       
    91         {
       
    92         // Locate the APP1 marker
       
    93         do
       
    94             {
       
    95             do
       
    96                 {
       
    97                 if ( ptr == pE )
       
    98                     {
       
    99                     User::Leave( KErrCorrupt );
       
   100                     }
       
   101                 } 
       
   102             while ( *++ptr != KMarkerStart );
       
   103             } 
       
   104         while ( *( ptr + 1 ) != KApp1End );
       
   105         // ptr is now at APP1
       
   106         // Skip App1 length.
       
   107         ptr += 4;
       
   108 
       
   109         // Check the APP1 and Exif header.
       
   110         if ( TExifCommon::Uint32L( ptr ) != KExifIdentifierRev ) 
       
   111             {
       
   112             User::Leave( KErrCorrupt );
       
   113             }
       
   114         ptr += 4;
       
   115 
       
   116         // Padding 0 after 8 bytes of data. No need to check, skip.
       
   117         //if ( ( *ptr ) != 0)
       
   118         //    {
       
   119         //    User::Leave( KErrCorrupt );
       
   120         //    }
       
   121         ptr += 2;
       
   122 
       
   123         // Check if little- or big- endian, and create the reader.
       
   124         if ( TExifCommon::Uint16L( ptr ) == KLittleEndian )
       
   125             {
       
   126             return CExifLittleEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
       
   127             }
       
   128         else if ( TExifCommon::Uint16L( ptr ) == KBigEndian )
       
   129             {
       
   130             return CExifBigEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
       
   131             }
       
   132         else // None of the formats match!!
       
   133             {
       
   134             User::Leave( KErrCorrupt );
       
   135             }
       
   136         }
       
   137     else
       
   138         {
       
   139         return CExifLittleEndian::NewL( aExifDataPtr, ptr, pE, aIsExif );
       
   140         }
       
   141 
       
   142     return NULL;
       
   143     }
       
   144 
       
   145 // Destructor
       
   146 CExifEndianBase::~CExifEndianBase()
       
   147     {
       
   148     }
       
   149 
       
   150 // -----------------------------------------------------------------------------
       
   151 // CExifEndianBase::CopyBufferL
       
   152 // Copies the data from the location, which starts and ends with the given 
       
   153 // Jpeg Markers.
       
   154 // -----------------------------------------------------------------------------
       
   155 //
       
   156 void CExifEndianBase::CopyBufferL( 
       
   157     TUint16 aStartMarker, 
       
   158     TUint16 aEndMarker, 
       
   159     HBufC8*& aDestBuffer, 
       
   160     TBool aIncludeEnd )
       
   161     {
       
   162     TUint32 startOffset = 0;
       
   163     if ( LocateJpegMarker( aStartMarker, startOffset ) )
       
   164         {
       
   165         User::Leave( KErrCorrupt );
       
   166         }
       
   167     TUint32 endOffset = 0;
       
   168     if ( LocateJpegMarker( aEndMarker, endOffset ) )
       
   169         {
       
   170         User::Leave( KErrCorrupt );
       
   171         }
       
   172     TUint32 size =  endOffset - startOffset;
       
   173     if ( aIncludeEnd )
       
   174         {
       
   175         size += 2;
       
   176         }
       
   177     aDestBuffer = HBufC8::NewL( size );
       
   178     CleanupStack::PushL( aDestBuffer );
       
   179 
       
   180     iPosOffset = startOffset;
       
   181 
       
   182     CopyBuffer( size, 1 , aDestBuffer );
       
   183     CleanupStack::Pop();
       
   184     }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CExifEndianBase::ReadUint8
       
   188 // Gets the next 8-bit unsigned integer from the data.
       
   189 // -----------------------------------------------------------------------------
       
   190 //
       
   191 TInt CExifEndianBase::ReadUint8( TUint8& aInt8 )
       
   192     {
       
   193     if ( iPosOffset + 1 >= iExifEndOffset )
       
   194         {
       
   195         return KErrCorrupt;
       
   196         }
       
   197     aInt8 = *( iDataStartPtr + iPosOffset );
       
   198     ++iPosOffset;
       
   199     return KErrNone;
       
   200     }
       
   201 
       
   202 // -----------------------------------------------------------------------------
       
   203 // CExifEndianBase::MoveTo
       
   204 // Moves to the specified offset.
       
   205 // -----------------------------------------------------------------------------
       
   206 //
       
   207 TInt CExifEndianBase::MoveTo( TUint aOffset )
       
   208     {
       
   209     if ( iExifStartOffset + aOffset >= iExifEndOffset )
       
   210         {
       
   211         return KErrCorrupt;
       
   212         }
       
   213     iPosOffset = iExifStartOffset + aOffset;
       
   214     return KErrNone;
       
   215     }
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CExifEndianBase::Skip
       
   219 // Moves the current position forward by the given number of bytes.
       
   220 // -----------------------------------------------------------------------------
       
   221 //
       
   222 TInt CExifEndianBase::Skip( TUint aNoBytes )
       
   223     {
       
   224     if ( iPosOffset + aNoBytes >= iExifEndOffset )
       
   225         {
       
   226         return KErrCorrupt;
       
   227         }
       
   228     iPosOffset += aNoBytes;
       
   229     return KErrNone;
       
   230     }
       
   231 
       
   232 // -----------------------------------------------------------------------------
       
   233 // CExifEndianBase::Locate8
       
   234 // Locates the offset of the next specified 8-bit unsigned integer 
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 TInt CExifEndianBase::Locate8( TUint8 aSearch, TUint32& aOffset )
       
   238     {
       
   239     TUint8 *pBuf = iDataStartPtr + iPosOffset;
       
   240     TUint8 *pB = pBuf - 1;
       
   241     TUint8* pE = iDataStartPtr + iExifEndOffset;
       
   242     do
       
   243         {
       
   244         if ( pB == pE )
       
   245             {
       
   246             return KErrCorrupt;
       
   247             }
       
   248         } 
       
   249     while ( *++pB != aSearch );
       
   250     aOffset = pB - iDataStartPtr;
       
   251     return KErrNone;
       
   252     }
       
   253 
       
   254 // -----------------------------------------------------------------------------
       
   255 // CExifEndianBase::LocateJpegMarker
       
   256 // Locates the offset of the specified Jpeg Marker, which resides after the 
       
   257 // given offset.
       
   258 // -----------------------------------------------------------------------------
       
   259 //
       
   260 TInt CExifEndianBase::LocateJpegMarker( 
       
   261     TUint16 aMarker, 
       
   262     TUint32& aOffset, 
       
   263     TUint32 aAfter,
       
   264     TUint32 aBefore )
       
   265     {
       
   266     if ( aAfter < iPosOffset )
       
   267         {
       
   268         aAfter = iPosOffset;
       
   269         }
       
   270     TUint8* startPtr = iDataStartPtr + aAfter;
       
   271     if ( !aBefore )
       
   272         {
       
   273         aBefore = iExifEndOffset;
       
   274         }
       
   275     TUint8* endPtr = iDataStartPtr + aBefore;
       
   276     TUint8* pB = TExifCommon::LocateJpegMarkerPtr( 
       
   277         aMarker, startPtr, endPtr );
       
   278     if ( !pB )
       
   279         {
       
   280         return KErrCorrupt;
       
   281         }
       
   282     aOffset = pB - iDataStartPtr;
       
   283     return KErrNone;    
       
   284     }
       
   285 
       
   286 // -----------------------------------------------------------------------------
       
   287 // CExifEndianBase::LocateJpegMarkerFromEnd
       
   288 // Locates the offset of the last specified Jpeg Marker.
       
   289 // -----------------------------------------------------------------------------
       
   290 //
       
   291 TInt CExifEndianBase::LocateJpegMarkerFromEnd( 
       
   292     TUint16 aMarker, 
       
   293     TUint32& aOffset,
       
   294     TUint32 aAfter,
       
   295     TUint32 aBefore )
       
   296     {
       
   297     if ( aAfter < iPosOffset)
       
   298         {
       
   299         aAfter = iPosOffset;
       
   300         }
       
   301     TUint8* startPtr = iDataStartPtr + aAfter;
       
   302     if ( !aBefore )
       
   303         {
       
   304         aBefore = iExifEndOffset;
       
   305         }
       
   306     TUint8* endPtr = iDataStartPtr + aBefore;
       
   307     TUint8* pB = TExifCommon::LocateJpegMarkerPtrFromEnd( aMarker, 
       
   308         startPtr, endPtr );
       
   309     if ( !pB )
       
   310         {
       
   311         return KErrCorrupt;
       
   312         }
       
   313     aOffset = pB - iDataStartPtr;
       
   314     return KErrNone;    
       
   315     }
       
   316 
       
   317 
       
   318 // ============================ CLASS CExifLittleEndian ========================
       
   319 // ============================ MEMBER FUNCTIONS ===============================
       
   320 
       
   321 // -----------------------------------------------------------------------------
       
   322 // CExifLittleEndian::NewL
       
   323 // Two-phased constructor.
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 CExifLittleEndian* CExifLittleEndian::NewL( 
       
   327     const TUint8* aDataStartPtr, 
       
   328     TUint8* aExifStartPtr, 
       
   329     TUint8* aExifEndPtr, 
       
   330     TBool aIsExif )
       
   331     {
       
   332     CExifLittleEndian* self = new( ELeave ) CExifLittleEndian();
       
   333     CleanupStack::PushL( self );
       
   334     self->ConstructL( CONST_CAST( TUint8*, aDataStartPtr ), aExifStartPtr, 
       
   335         aExifEndPtr, aIsExif );
       
   336     CleanupStack::Pop();
       
   337     return self;
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 // CExifLittleEndian::CExifLittleEndian
       
   342 // C++ default constructor can NOT contain any code, that
       
   343 // might leave.
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 CExifLittleEndian::CExifLittleEndian()
       
   347     {
       
   348     }
       
   349 
       
   350 // -----------------------------------------------------------------------------
       
   351 // CExifLittleEndian::ConstructL
       
   352 // Symbian 2nd phase constructor can leave.
       
   353 // -----------------------------------------------------------------------------
       
   354 //
       
   355 void CExifLittleEndian::ConstructL( 
       
   356     TUint8* aDataStartPtr, 
       
   357     TUint8* aExifStartPtr, 
       
   358     TUint8* aExifEndPtr, 
       
   359     TBool aIsExif )
       
   360     {
       
   361     if ( !aDataStartPtr || !aExifStartPtr || !aExifEndPtr )
       
   362         {
       
   363         User::Leave( KErrGeneral );
       
   364         }
       
   365     iDataStartPtr = aDataStartPtr;
       
   366     iExifEndOffset = aExifEndPtr - iDataStartPtr;
       
   367     if ( aIsExif )
       
   368         {
       
   369         iExifStartOffset = aExifStartPtr - iDataStartPtr;
       
   370         if ( TExifCommon::Uint16L( aExifStartPtr + 2 ) != KExifDummyRev )
       
   371             {
       
   372             User::Leave( KErrCorrupt );
       
   373             }
       
   374         TUint32 ifdOffset = TExifCommon::Uint32L( aExifStartPtr + 4 );
       
   375         iPosOffset = iExifStartOffset + ifdOffset; //Locate 0th IFD position
       
   376         if ( iPosOffset >= iExifEndOffset )
       
   377             {
       
   378             User::Leave( KErrCorrupt );
       
   379             }
       
   380         }
       
   381     else
       
   382         {
       
   383         iPosOffset = aExifStartPtr - iDataStartPtr;
       
   384         }
       
   385     }
       
   386 
       
   387 // Destructor
       
   388 CExifLittleEndian::~CExifLittleEndian()
       
   389     {
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // CExifLittleEndian::Locate16
       
   394 // Locates the offset of the next specified 16-bit unsigned integer.
       
   395 // -----------------------------------------------------------------------------
       
   396 //
       
   397 TInt CExifLittleEndian::Locate16( TUint16 aSearch, TUint32& aOffset )
       
   398     {
       
   399     TUint8* pB = iDataStartPtr + iPosOffset - 1;
       
   400     TUint16 atHand = *pB;
       
   401     TUint8* pE = iDataStartPtr + iExifEndOffset;
       
   402     TInt error = KErrNone;
       
   403     do
       
   404         {
       
   405         if ( pB >= pE )
       
   406             {
       
   407             return KErrCorrupt;
       
   408             }
       
   409         TRAP( error, atHand =TExifCommon::Uint16L( ++pB ) );
       
   410         } 
       
   411     while ( ( atHand != aSearch ) && ( error == KErrNone ) );
       
   412     if ( error )
       
   413         {
       
   414         return error;
       
   415         }
       
   416     aOffset = pB - iDataStartPtr;
       
   417     return KErrNone;
       
   418     }
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // CExifLittleEndian::ReadUint16
       
   422 // Gets the next 16-bit unsigned integer from the data.
       
   423 // -----------------------------------------------------------------------------
       
   424 //
       
   425 TInt CExifLittleEndian::ReadUInt16( TUint16& aInt16 )
       
   426     {
       
   427     if ( iPosOffset + 2 >= iExifEndOffset )
       
   428         {
       
   429         return KErrCorrupt;
       
   430         }
       
   431     
       
   432     TRAPD( error, aInt16 = TExifCommon::Uint16L( iDataStartPtr + iPosOffset ) );
       
   433 
       
   434     if ( error )
       
   435         {
       
   436         return error;
       
   437         }
       
   438     
       
   439     iPosOffset += 2;
       
   440     return KErrNone;
       
   441     }
       
   442 
       
   443 // -----------------------------------------------------------------------------
       
   444 // CExifLittleEndian::ReadUint32
       
   445 // Gets the next 32-bit unsigned integer from the data.
       
   446 // -----------------------------------------------------------------------------
       
   447 //
       
   448 TInt CExifLittleEndian::ReadUInt32( TUint32& aInt32 )
       
   449     {
       
   450     if ( iPosOffset + 4 >= iExifEndOffset )
       
   451         {
       
   452         return KErrCorrupt;
       
   453         }
       
   454     
       
   455     TRAPD( error, aInt32 = TExifCommon::Uint32L( iDataStartPtr + iPosOffset ) );
       
   456     if ( error )
       
   457         {
       
   458         return error;
       
   459         }
       
   460     
       
   461     iPosOffset += 4;
       
   462     return KErrNone;
       
   463     }
       
   464 
       
   465 // -----------------------------------------------------------------------------
       
   466 // CExifLittleEndian::CopyBuffer
       
   467 // Copies the next specified amount of data to the given descriptor.
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 TInt CExifLittleEndian::CopyBuffer( 
       
   471     TUint32 aCount, 
       
   472     TUint8 aWordSize, 
       
   473     HBufC8*& aBuffer )
       
   474     {
       
   475     if ( !aBuffer )
       
   476         {
       
   477         return KErrCorrupt;
       
   478         }
       
   479     TUint bufferSize = aCount * aWordSize;
       
   480     if ( iPosOffset + bufferSize >= iExifEndOffset )
       
   481         {
       
   482         return KErrCorrupt;
       
   483         }
       
   484     
       
   485     aBuffer->Des().Copy( iDataStartPtr + iPosOffset, bufferSize );
       
   486 
       
   487     iPosOffset += bufferSize;
       
   488 
       
   489     return KErrNone;
       
   490     }
       
   491 
       
   492 // -----------------------------------------------------------------------------
       
   493 // CExifLittleEndian::CopyBuffer
       
   494 // Copies the specified amount of data located in the given offset to the 
       
   495 // given descriptor.
       
   496 // -----------------------------------------------------------------------------
       
   497 //
       
   498 TInt CExifLittleEndian::CopyBuffer( 
       
   499     TUint32 aOffset, 
       
   500     TUint32 aCount, 
       
   501     TUint8 aWordSize, 
       
   502     HBufC8*& aBuffer )
       
   503     {
       
   504     if ( !aBuffer )
       
   505         {
       
   506         return KErrCorrupt;
       
   507         }
       
   508     TUint bufferSize = aCount * aWordSize;
       
   509     if ( ( aOffset + iExifStartOffset + bufferSize ) >= iExifEndOffset )
       
   510         {
       
   511         return KErrCorrupt;
       
   512         }
       
   513     
       
   514     TUint8* ptr = iDataStartPtr + iExifStartOffset + aOffset;
       
   515     aBuffer->Des().Copy( ptr, bufferSize );
       
   516 
       
   517     return KErrNone;
       
   518     }
       
   519 
       
   520 
       
   521 // ============================ CLASS CExifBigEndian ===========================
       
   522 // ============================ MEMBER FUNCTIONS ===============================
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CExifBigEndian::NewL
       
   526 // Two-phased constructor.
       
   527 // -----------------------------------------------------------------------------
       
   528 //
       
   529 CExifBigEndian* CExifBigEndian::NewL( 
       
   530     const TUint8* aDataStartPtr, 
       
   531     TUint8* aExifStartPtr, 
       
   532     TUint8* aExifEndPtr, 
       
   533     TBool aIsExif )
       
   534     {
       
   535     CExifBigEndian* self = new( ELeave ) CExifBigEndian();
       
   536     CleanupStack::PushL( self );
       
   537     self->ConstructL( CONST_CAST( TUint8*, aDataStartPtr ), aExifStartPtr, 
       
   538         aExifEndPtr, aIsExif );
       
   539     CleanupStack::Pop();
       
   540     return self;
       
   541     }
       
   542 
       
   543 // -----------------------------------------------------------------------------
       
   544 // CExifBigEndian::CExifBigEndian
       
   545 // C++ default constructor can NOT contain any code, that
       
   546 // might leave.
       
   547 // -----------------------------------------------------------------------------
       
   548 //
       
   549 CExifBigEndian::CExifBigEndian()
       
   550     {
       
   551     }
       
   552 
       
   553 // -----------------------------------------------------------------------------
       
   554 // CExifBigEndian::ConstructL
       
   555 // Symbian 2nd phase constructor can leave.
       
   556 // -----------------------------------------------------------------------------
       
   557 //
       
   558 void CExifBigEndian::ConstructL( 
       
   559     TUint8* aDataStartPtr, 
       
   560     TUint8* aExifStartPtr, 
       
   561     TUint8* aExifEndPtr, 
       
   562     TBool aIsExif )
       
   563     {
       
   564     if ( !aDataStartPtr || !aExifStartPtr || !aExifEndPtr )
       
   565         {
       
   566         User::Leave( KErrGeneral );
       
   567         }
       
   568     iDataStartPtr = aDataStartPtr;
       
   569     iExifEndOffset = aExifEndPtr - iDataStartPtr;
       
   570     if ( aIsExif )
       
   571         {
       
   572         iExifStartOffset = aExifStartPtr - iDataStartPtr;
       
   573         if ( TExifCommon::Uint16L( aExifStartPtr + 2 ) != KExifDummy )
       
   574             {
       
   575             User::Leave( KErrCorrupt );
       
   576             }
       
   577 
       
   578         TUint8* tmpPtr = aExifStartPtr + 4;
       
   579         TUint32 ifdOffset = STATIC_CAST( TUint32,  ( *tmpPtr << 24 ) 
       
   580             + ( ( *( tmpPtr + 1 ) ) << 16 ) +  ( ( *( tmpPtr + 2 ) ) << 8 ) 
       
   581             + ( *( tmpPtr + 3 ) ) ); 
       
   582         iPosOffset = ( iExifStartOffset + ifdOffset ); //Locate 0th IFD pos.
       
   583         if ( iPosOffset >= iExifEndOffset )
       
   584             {
       
   585             User::Leave( KErrCorrupt );
       
   586             }
       
   587         }
       
   588     else
       
   589         {
       
   590         iPosOffset = aExifStartPtr - iDataStartPtr;
       
   591         }
       
   592     }
       
   593 
       
   594 // Destructor
       
   595 CExifBigEndian::~CExifBigEndian()
       
   596     {
       
   597     }
       
   598 
       
   599 // -----------------------------------------------------------------------------
       
   600 // CExifBigEndian::Locate16
       
   601 // Locates the offset of the next specified 16-bit unsigned integer.
       
   602 // -----------------------------------------------------------------------------
       
   603 //
       
   604 TInt CExifBigEndian::Locate16( TUint16 aSearch, TUint32& aOffset )
       
   605     {
       
   606     TUint8* pB = iDataStartPtr + iPosOffset;
       
   607     TUint16 atHand = *pB;
       
   608     TUint8* pE = iDataStartPtr + iExifEndOffset;
       
   609     do
       
   610         {
       
   611         if ( pB >= pE )
       
   612             {
       
   613             return KErrCorrupt;
       
   614             }
       
   615         atHand = STATIC_CAST( TUint16, ( atHand << 8 ) + *++pB );
       
   616         } 
       
   617     while ( atHand != aSearch );
       
   618     aOffset = ( pB - 1 ) - iDataStartPtr;
       
   619     return KErrNone;
       
   620     }
       
   621 
       
   622 // -----------------------------------------------------------------------------
       
   623 // CExifBigEndian::ReadUInt16
       
   624 // Gets the next 16-bit unsigned integer from the data.
       
   625 // -----------------------------------------------------------------------------
       
   626 //
       
   627 TInt CExifBigEndian::ReadUInt16( TUint16& aInt16 )
       
   628     {
       
   629     if ( iPosOffset + 2 >= iExifEndOffset )
       
   630         {
       
   631         return KErrCorrupt;
       
   632         }
       
   633 
       
   634     aInt16 = STATIC_CAST( TUint16,  ( *( iDataStartPtr + iPosOffset ) << 8 ) 
       
   635         + *( iDataStartPtr + iPosOffset + 1 ) ); 
       
   636     
       
   637     iPosOffset += 2;
       
   638     return KErrNone;
       
   639     }
       
   640 
       
   641 // -----------------------------------------------------------------------------
       
   642 // CExifBigEndian::ReadUInt32
       
   643 // Gets the next 32-bit unsigned integer from the data.
       
   644 // -----------------------------------------------------------------------------
       
   645 //
       
   646 TInt CExifBigEndian::ReadUInt32( TUint32& aInt32 )
       
   647     {
       
   648     if ( iPosOffset + 4 >= iExifEndOffset )
       
   649         {
       
   650         return KErrCorrupt;
       
   651         }
       
   652 
       
   653     aInt32 = STATIC_CAST( TUint32,  ( *( iDataStartPtr + iPosOffset ) << 24 ) 
       
   654         + ( *( iDataStartPtr + iPosOffset + 1 ) << 16 ) 
       
   655         + ( *( iDataStartPtr + iPosOffset + 2 ) << 8 ) 
       
   656         + *( iDataStartPtr + iPosOffset + 3 ) ); 
       
   657 
       
   658     iPosOffset += 4;
       
   659     return KErrNone;
       
   660     }
       
   661 
       
   662 // -----------------------------------------------------------------------------
       
   663 // CExifBigEndian::CopyBuffer
       
   664 // Copies the next specified amount of data to the given descriptor.
       
   665 // -----------------------------------------------------------------------------
       
   666 //
       
   667 TInt CExifBigEndian::CopyBuffer( 
       
   668     TUint32 aCount, 
       
   669     TUint8 aWordSize, 
       
   670     HBufC8*& aBuffer )
       
   671     {
       
   672     if ( !aBuffer )
       
   673         {
       
   674         return KErrCorrupt;
       
   675         }
       
   676     TInt bufferSize = aCount * aWordSize;
       
   677     if ( iPosOffset + bufferSize >= iExifEndOffset )
       
   678         {
       
   679         return KErrCorrupt;
       
   680         }
       
   681     
       
   682     TUint8* posPtr = iDataStartPtr + iPosOffset;
       
   683     if ( aWordSize == 1 )
       
   684         {
       
   685         aBuffer->Des().Copy( posPtr, bufferSize );
       
   686         iPosOffset += bufferSize;
       
   687         }
       
   688     else if ( aWordSize == 2 )
       
   689         {    
       
   690         TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
       
   691         for( TUint i = 0; i < aCount; ++i)
       
   692             {
       
   693             destPtr[0] = posPtr[1];
       
   694             destPtr[1] = *posPtr;
       
   695             posPtr += 2;
       
   696             iPosOffset += 2;
       
   697             destPtr += 2;
       
   698             }
       
   699         }
       
   700     else
       
   701         {    
       
   702         TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
       
   703         for( TInt i = 0; i < bufferSize / 4; ++i)
       
   704             {
       
   705             destPtr[0] = posPtr[3];
       
   706             destPtr[1] = posPtr[2];
       
   707             destPtr[2] = posPtr[1];
       
   708             destPtr[3] = *posPtr;
       
   709             posPtr += 4;
       
   710             iPosOffset += 4;
       
   711             destPtr += 4;
       
   712             }
       
   713         }
       
   714     aBuffer->Des().SetLength( bufferSize );
       
   715     return KErrNone;
       
   716     }
       
   717 
       
   718 // -----------------------------------------------------------------------------
       
   719 // CExifBigEndian::CopyBuffer
       
   720 // Copies the specified amount of data located in the given offset to the 
       
   721 // given descriptor.
       
   722 // -----------------------------------------------------------------------------
       
   723 //
       
   724 TInt CExifBigEndian::CopyBuffer( 
       
   725     TUint32 aOffset, 
       
   726     TUint32 aCount, 
       
   727     TUint8 aWordSize, 
       
   728     HBufC8*& aBuffer )
       
   729     {
       
   730     if ( !aBuffer )
       
   731         {
       
   732         return KErrCorrupt;
       
   733         }
       
   734     TInt bufferSize = aCount * aWordSize;
       
   735     if ( ( aOffset + iExifStartOffset + bufferSize ) >= iExifEndOffset )
       
   736         {
       
   737         return KErrCorrupt;
       
   738         }
       
   739     
       
   740     TUint8* ptr = iDataStartPtr + iExifStartOffset + aOffset;
       
   741     if ( aWordSize == 1 )
       
   742         {
       
   743         aBuffer->Des().Copy( ptr, bufferSize );
       
   744         }
       
   745     else if ( aWordSize == 2 )
       
   746         {
       
   747         TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
       
   748         for( TUint i = 0; i < aCount; ++i)
       
   749             {
       
   750             destPtr[0] = ptr[1];
       
   751             destPtr[1] = *ptr;
       
   752             destPtr += 2;
       
   753             ptr += 2;
       
   754             }
       
   755         }
       
   756     else
       
   757         {
       
   758         TUint8* destPtr = CONST_CAST( TUint8*, aBuffer->Ptr() );
       
   759         for( TInt i = 0; i < bufferSize / 4; ++i)
       
   760             {
       
   761             destPtr[0] = ptr[3];
       
   762             destPtr[1] = ptr[2];
       
   763             destPtr[2] = ptr[1];
       
   764             destPtr[3] = *ptr;
       
   765             destPtr += 4;
       
   766             ptr += 4;
       
   767             }
       
   768         }
       
   769     aBuffer->Des().SetLength( bufferSize );
       
   770     return KErrNone;
       
   771     }
       
   772 
       
   773 // -----------------------------------------------------------------------------
       
   774 // CExifEndianBase::CurrentPosOffset
       
   775 // Returns the current position of decoded data
       
   776 // -----------------------------------------------------------------------------
       
   777 //
       
   778 void CExifEndianBase::CurrentPosOffset( TUint32& aOffset )
       
   779     {
       
   780     aOffset = iPosOffset;
       
   781     }