LCOV - code coverage report
Current view: top level - basic/source/classes - image.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 95 257 37.0 %
Date: 2015-06-13 12:38:46 Functions: 10 19 52.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/stream.hxx>
      21             : #include <tools/tenccvt.hxx>
      22             : #include <osl/thread.h>
      23             : #include <basic/sbx.hxx>
      24             : #include "sb.hxx"
      25             : #include <string.h>
      26             : #include "image.hxx"
      27             : #include <codegen.hxx>
      28             : #include <boost/scoped_array.hpp>
      29             : 
      30         185 : SbiImage::SbiImage()
      31             : {
      32         185 :     pStringOff = NULL;
      33         185 :     pStrings   = NULL;
      34         185 :     pCode      = NULL;
      35         185 :     pLegacyPCode = NULL;
      36         185 :     nFlags     = SbiImageFlags::NONE;
      37         185 :     nStrings   = 0;
      38         185 :     nStringSize= 0;
      39         185 :     nCodeSize  = 0;
      40             :     nLegacyCodeSize  =
      41         185 :     nDimBase   = 0;
      42             :     bInit      =
      43         185 :     bError     = false;
      44         185 :     bFirstInit = true;
      45         185 :     eCharSet   = osl_getThreadTextEncoding();
      46         185 :     nStringIdx = 0;
      47         185 :     nStringOff = 0;
      48         185 : }
      49             : 
      50         366 : SbiImage::~SbiImage()
      51             : {
      52         183 :     Clear();
      53         183 : }
      54             : 
      55         183 : void SbiImage::Clear()
      56             : {
      57         183 :     delete[] pStringOff;
      58         183 :     delete[] pStrings;
      59         183 :     delete[] pCode;
      60         183 :     ReleaseLegacyBuffer();
      61         183 :     pStringOff = NULL;
      62         183 :     pStrings   = NULL;
      63         183 :     pCode      = NULL;
      64         183 :     nFlags     = SbiImageFlags::NONE;
      65         183 :     nStrings   = 0;
      66         183 :     nStringSize= 0;
      67         183 :     nLegacyCodeSize  = 0;
      68         183 :     nCodeSize  = 0;
      69         183 :     eCharSet   = osl_getThreadTextEncoding();
      70         183 :     nDimBase   = 0;
      71         183 :     bError     = false;
      72         183 : }
      73             : 
      74             : /**************************************************************************
      75             : *
      76             : *    Service-Routines for Load/Store
      77             : *
      78             : **************************************************************************/
      79             : 
      80           0 : bool SbiGood( SvStream& r )
      81             : {
      82           0 :     return !r.IsEof() && r.GetError() == SVSTREAM_OK;
      83             : }
      84             : 
      85             : // Open Record
      86           0 : sal_uIntPtr SbiOpenRecord( SvStream& r, sal_uInt16 nSignature, sal_uInt16 nElem )
      87             : {
      88           0 :     sal_Size nPos = r.Tell();
      89           0 :     r.WriteUInt16( nSignature ).WriteInt32( 0 ).WriteUInt16( nElem );
      90           0 :     return nPos;
      91             : }
      92             : 
      93             : // Close Record
      94           0 : void SbiCloseRecord( SvStream& r, sal_Size nOff )
      95             : {
      96           0 :     sal_Size nPos = r.Tell();
      97           0 :     r.Seek( nOff + 2 );
      98           0 :     r.WriteInt32(nPos - nOff - 8 );
      99           0 :     r.Seek( nPos );
     100           0 : }
     101             : 
     102             : /**************************************************************************
     103             : *
     104             : *    Load/Store
     105             : *
     106             : **************************************************************************/
     107             : 
     108           0 : bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
     109             : {
     110             : 
     111             :     sal_uInt16 nSign, nCount;
     112             :     sal_uInt32 nLen, nOff;
     113             : 
     114           0 :     Clear();
     115             :     // Read Master-Record
     116           0 :     r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
     117           0 :     sal_Size nLast = r.Tell() + nLen;
     118             :     sal_uInt32 nCharSet;               // System charset
     119             :     sal_uInt32 lDimBase;
     120             :     sal_uInt16 nReserved1;
     121             :     sal_uInt32 nReserved2;
     122             :     sal_uInt32 nReserved3;
     123           0 :     bool bBadVer = false;
     124           0 :     if( nSign == B_MODULE )
     125             :     {
     126             :         sal_uInt16 nTmpFlags;
     127           0 :         r.ReadUInt32( nVersion ).ReadUInt32( nCharSet ).ReadUInt32( lDimBase )
     128           0 :          .ReadUInt16( nTmpFlags ).ReadUInt16( nReserved1 ).ReadUInt32( nReserved2 ).ReadUInt32( nReserved3 );
     129           0 :         nFlags = static_cast<SbiImageFlags>(nTmpFlags);
     130           0 :         eCharSet = nCharSet;
     131           0 :         eCharSet = GetSOLoadTextEncoding( eCharSet );
     132           0 :         bBadVer  = ( nVersion > B_CURVERSION );
     133           0 :         nDimBase = (sal_uInt16) lDimBase;
     134             :     }
     135             : 
     136           0 :     bool bLegacy = ( nVersion < B_EXT_IMG_VERSION );
     137             : 
     138             :     sal_Size nNext;
     139           0 :     while( ( nNext = r.Tell() ) < nLast )
     140             :     {
     141             : 
     142           0 :         r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
     143           0 :         nNext += nLen + 8;
     144           0 :         if( r.GetError() == SVSTREAM_OK )
     145             :         {
     146           0 :             switch( nSign )
     147             :             {
     148             :             case B_NAME:
     149           0 :                 aName = r.ReadUniOrByteString(eCharSet);
     150           0 :                 break;
     151             :             case B_COMMENT:
     152           0 :                 aComment = r.ReadUniOrByteString(eCharSet );
     153           0 :                 break;
     154             :             case B_SOURCE:
     155             :             {
     156           0 :                 aOUSource = r.ReadUniOrByteString(eCharSet);
     157           0 :                 break;
     158             :             }
     159             :             case B_EXTSOURCE:
     160             :             {
     161             :                 //assuming an empty string with just the lead 32bit/16bit len indicator
     162           0 :                 const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
     163           0 :                 const size_t nMaxStrings = r.remainingSize() / nMinStringSize;
     164           0 :                 if (nCount > nMaxStrings)
     165             :                 {
     166             :                     SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
     167             :                              " max possible entries, but " << nCount << " claimed, truncating");
     168           0 :                     nCount = nMaxStrings;
     169             :                 }
     170           0 :                 for( sal_uInt16 j = 0; j < nCount; ++j)
     171             :                 {
     172           0 :                     aOUSource += r.ReadUniOrByteString(eCharSet);
     173             :                 }
     174           0 :                 break;
     175             :             }
     176             :             case B_PCODE:
     177           0 :                 if( bBadVer ) break;
     178           0 :                 pCode = new char[ nLen ];
     179           0 :                 nCodeSize = nLen;
     180           0 :                 r.Read( pCode, nCodeSize );
     181           0 :                 if ( bLegacy )
     182             :                 {
     183           0 :                     ReleaseLegacyBuffer(); // release any previously held buffer
     184           0 :                     nLegacyCodeSize = (sal_uInt16) nCodeSize;
     185           0 :                     pLegacyPCode = pCode;
     186             : 
     187           0 :                     PCodeBuffConvertor< sal_uInt16, sal_uInt32 > aLegacyToNew( reinterpret_cast<sal_uInt8*>(pLegacyPCode), nLegacyCodeSize );
     188           0 :                     aLegacyToNew.convert();
     189           0 :                     pCode = reinterpret_cast<char*>(aLegacyToNew.GetBuffer());
     190           0 :                     nCodeSize = aLegacyToNew.GetSize();
     191             :                     // we don't release the legacy buffer
     192             :                     // right now, thats because the module
     193             :                     // needs it to fix up the method
     194             :                     // nStart members. When that is done
     195             :                     // the module can release the buffer
     196             :                     // or it can wait until this routine
     197             :                     // is called again or when this class                       // destructs all of which will trigger
     198             :                     // release of the buffer.
     199             :                 }
     200           0 :                 break;
     201             :             case B_PUBLICS:
     202             :             case B_POOLDIR:
     203             :             case B_SYMPOOL:
     204             :             case B_LINERANGES:
     205           0 :                 break;
     206             :             case B_STRINGPOOL:
     207             :             {
     208           0 :                 if( bBadVer ) break;
     209             :                 //assuming an empty string with just the lead 32bit len indicator
     210           0 :                 const size_t nMinStringSize = 4;
     211           0 :                 const size_t nMaxStrings = r.remainingSize() / nMinStringSize;
     212           0 :                 if (nCount > nMaxStrings)
     213             :                 {
     214             :                     SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
     215             :                              " max possible entries, but " << nCount << " claimed, truncating");
     216           0 :                     nCount = nMaxStrings;
     217             :                 }
     218           0 :                 MakeStrings( nCount );
     219             :                 short i;
     220           0 :                 for( i = 0; i < nStrings && SbiGood( r ); i++ )
     221             :                 {
     222           0 :                     r.ReadUInt32( nOff );
     223           0 :                     pStringOff[ i ] = (sal_uInt16) nOff;
     224             :                 }
     225           0 :                 r.ReadUInt32( nLen );
     226           0 :                 if( SbiGood( r ) )
     227             :                 {
     228           0 :                     delete [] pStrings;
     229           0 :                     pStrings = new sal_Unicode[ nLen ];
     230           0 :                     nStringSize = (sal_uInt16) nLen;
     231             : 
     232           0 :                     boost::scoped_array<char> pByteStrings(new char[ nLen ]);
     233           0 :                     r.Read( pByteStrings.get(), nStringSize );
     234           0 :                     for( short j = 0; j < nStrings; j++ )
     235             :                     {
     236           0 :                         sal_uInt16 nOff2 = (sal_uInt16) pStringOff[ j ];
     237           0 :                         OUString aStr( pByteStrings.get() + nOff2, strlen(pByteStrings.get() + nOff2), eCharSet );
     238           0 :                         memcpy( pStrings + nOff2, aStr.getStr(), (aStr.getLength() + 1) * sizeof( sal_Unicode ) );
     239           0 :                     }
     240             :                 }
     241           0 :                 break;
     242             :             }
     243             :             case B_MODEND:
     244           0 :                 goto done;
     245             :             default:
     246           0 :                 break;
     247             :             }
     248             :         }
     249             :         else
     250             :         {
     251           0 :             break;
     252             :         }
     253           0 :         r.Seek( nNext );
     254             :     }
     255             : done:
     256           0 :     r.Seek( nLast );
     257           0 :     if( !SbiGood( r ) )
     258             :     {
     259           0 :         bError = true;
     260             :     }
     261           0 :     return !bError;
     262             : }
     263             : 
     264           0 : bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
     265             : {
     266           0 :     bool bLegacy = ( nVer < B_EXT_IMG_VERSION );
     267             : 
     268             :     // detect if old code exceeds legacy limits
     269             :     // if so, then disallow save
     270           0 :     if ( bLegacy && ExceedsLegacyLimits() )
     271             :     {
     272           0 :         SbiImage aEmptyImg;
     273           0 :         aEmptyImg.aName = aName;
     274           0 :         aEmptyImg.Save( r, B_LEGACYVERSION );
     275           0 :         return true;
     276             :     }
     277             :     // First of all the header
     278           0 :     sal_uIntPtr nStart = SbiOpenRecord( r, B_MODULE, 1 );
     279             :     sal_uIntPtr nPos;
     280             : 
     281           0 :     eCharSet = GetSOStoreTextEncoding( eCharSet );
     282           0 :     if ( bLegacy )
     283             :     {
     284           0 :         r.WriteInt32( B_LEGACYVERSION );
     285             :     }
     286             :     else
     287             :     {
     288           0 :         r.WriteInt32( B_CURVERSION );
     289             :     }
     290           0 :     r .WriteInt32( eCharSet )
     291           0 :       .WriteInt32( nDimBase )
     292           0 :       .WriteInt16( static_cast<sal_uInt16>(nFlags) )
     293           0 :       .WriteInt16( 0 )
     294           0 :       .WriteInt32( 0 )
     295           0 :       .WriteInt32( 0 );
     296             : 
     297             :     // Name?
     298           0 :     if( !aName.isEmpty() && SbiGood( r ) )
     299             :     {
     300           0 :         nPos = SbiOpenRecord( r, B_NAME, 1 );
     301           0 :         r.WriteUniOrByteString( aName, eCharSet );
     302           0 :         SbiCloseRecord( r, nPos );
     303             :     }
     304             :     // Comment?
     305           0 :     if( !aComment.isEmpty() && SbiGood( r ) )
     306             :     {
     307           0 :         nPos = SbiOpenRecord( r, B_COMMENT, 1 );
     308           0 :         r.WriteUniOrByteString( aComment, eCharSet );
     309           0 :         SbiCloseRecord( r, nPos );
     310             :     }
     311             :     // Source?
     312           0 :     if( !aOUSource.isEmpty() && SbiGood( r ) )
     313             :     {
     314           0 :         nPos = SbiOpenRecord( r, B_SOURCE, 1 );
     315           0 :         r.WriteUniOrByteString( aOUSource, eCharSet );
     316           0 :         SbiCloseRecord( r, nPos );
     317             :     }
     318             :     // Binary data?
     319           0 :     if( pCode && SbiGood( r ) )
     320             :     {
     321           0 :         nPos = SbiOpenRecord( r, B_PCODE, 1 );
     322           0 :         if ( bLegacy )
     323             :         {
     324           0 :             ReleaseLegacyBuffer(); // release any previously held buffer
     325           0 :             PCodeBuffConvertor< sal_uInt32, sal_uInt16 > aNewToLegacy( reinterpret_cast<sal_uInt8*>(pCode), nCodeSize );
     326           0 :             aNewToLegacy.convert();
     327           0 :             pLegacyPCode = reinterpret_cast<char*>(aNewToLegacy.GetBuffer());
     328           0 :             nLegacyCodeSize = aNewToLegacy.GetSize();
     329           0 :             r.Write( pLegacyPCode, nLegacyCodeSize );
     330             :         }
     331             :         else
     332             :         {
     333           0 :             r.Write( pCode, nCodeSize );
     334             :         }
     335           0 :         SbiCloseRecord( r, nPos );
     336             :     }
     337             :     // String-Pool?
     338           0 :     if( nStrings )
     339             :     {
     340           0 :         nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings );
     341             :         // For every String:
     342             :         //  sal_uInt32 Offset of the Strings in the Stringblock
     343             :         short i;
     344             : 
     345           0 :         for( i = 0; i < nStrings && SbiGood( r ); i++ )
     346             :         {
     347           0 :             r.WriteUInt32( pStringOff[ i ] );
     348             :         }
     349             :         // Then the String-Block
     350           0 :         boost::scoped_array<char> pByteStrings(new char[ nStringSize ]);
     351           0 :         for( i = 0; i < nStrings; i++ )
     352             :         {
     353           0 :             sal_uInt16 nOff = (sal_uInt16) pStringOff[ i ];
     354           0 :             OString aStr(OUStringToOString(OUString(pStrings + nOff), eCharSet));
     355           0 :             memcpy( pByteStrings.get() + nOff, aStr.getStr(), (aStr.getLength() + 1) * sizeof( char ) );
     356           0 :         }
     357           0 :         r.WriteUInt32( nStringSize );
     358           0 :         r.Write( pByteStrings.get(), nStringSize );
     359             : 
     360           0 :         pByteStrings.reset();
     361           0 :         SbiCloseRecord( r, nPos );
     362             :     }
     363             :     // Set overall length
     364           0 :     SbiCloseRecord( r, nStart );
     365           0 :     if( !SbiGood( r ) )
     366             :     {
     367           0 :         bError = true;
     368             :     }
     369           0 :     return !bError;
     370             : }
     371             : 
     372             : /**************************************************************************
     373             : *
     374             : *    Routines called by the compiler
     375             : *
     376             : **************************************************************************/
     377             : 
     378         185 : void SbiImage::MakeStrings( short nSize )
     379             : {
     380         185 :     nStrings = 0;
     381         185 :     nStringIdx = 0;
     382         185 :     nStringOff = 0;
     383         185 :     nStringSize = 1024;
     384         185 :     pStrings = new sal_Unicode[ nStringSize ];
     385         185 :     pStringOff = new sal_uInt32[ nSize ];
     386         185 :     nStrings = nSize;
     387         185 :     memset( pStringOff, 0, nSize * sizeof( sal_uInt32 ) );
     388         185 :     memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) );
     389         185 : }
     390             : 
     391             : // Add a string to StringPool. The String buffer is dynamically
     392             : // growing in 1K-Steps
     393        6057 : void SbiImage::AddString( const OUString& r )
     394             : {
     395        6057 :     if( nStringIdx >= nStrings )
     396             :     {
     397           0 :         bError = true;
     398             :     }
     399        6057 :     if( !bError )
     400             :     {
     401        6057 :         sal_Int32  len = r.getLength() + 1;
     402        6057 :         sal_uInt32 needed = nStringOff + len;
     403        6057 :         if( needed > 0xFFFFFF00L )
     404             :         {
     405           0 :             bError = true;  // out of mem!
     406             :         }
     407        6057 :         else if( needed > nStringSize )
     408             :         {
     409          37 :             sal_uInt32 nNewLen = needed + 1024;
     410          37 :             nNewLen &= 0xFFFFFC00;  // trim to 1K border
     411          37 :             sal_Unicode* p = new sal_Unicode[nNewLen];
     412          37 :             memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) );
     413          37 :             delete[] pStrings;
     414          37 :             pStrings = p;
     415          37 :             nStringSize = sal::static_int_cast< sal_uInt16 >(nNewLen);
     416             :         }
     417        6057 :         if( !bError )
     418             :         {
     419        6057 :             pStringOff[ nStringIdx++ ] = nStringOff;
     420        6057 :             memcpy( pStrings + nStringOff, r.getStr(), len * sizeof( sal_Unicode ) );
     421        6057 :             nStringOff = nStringOff + len;
     422             :             // Last String? The update the size of the buffer
     423        6057 :             if( nStringIdx >= nStrings )
     424             :             {
     425         185 :                 nStringSize = nStringOff;
     426             :             }
     427             :         }
     428             :     }
     429        6057 : }
     430             : 
     431             : // Add code block
     432             : // The block was fetched by the compiler from class SbBuffer and
     433             : // is already created with new. Additionally it contains all Integers
     434             : // in Big Endian format, so can be directly read/written.
     435         185 : void SbiImage::AddCode( char* p, sal_uInt32 s )
     436             : {
     437         185 :     pCode = p;
     438         185 :     nCodeSize = s;
     439         185 : }
     440             : 
     441             : // Add user type
     442           1 : void SbiImage::AddType(SbxObject* pObject)
     443             : {
     444           1 :     if( !rTypes.Is() )
     445             :     {
     446           1 :         rTypes = new SbxArray;
     447             :     }
     448           1 :     SbxObject *pCopyObject = new SbxObject(*pObject);
     449           1 :     rTypes->Insert (pCopyObject,rTypes->Count());
     450           1 : }
     451             : 
     452           0 : void SbiImage::AddEnum(SbxObject* pObject) // Register enum type
     453             : {
     454           0 :     if( !rEnums.Is() )
     455             :     {
     456           0 :         rEnums = new SbxArray;
     457             :     }
     458           0 :     rEnums->Insert( pObject, rEnums->Count() );
     459           0 : }
     460             : 
     461             : 
     462             : /**************************************************************************
     463             : *
     464             : *    Accessing the image
     465             : *
     466             : **************************************************************************/
     467             : 
     468             : // Note: IDs start with 1
     469       22739 : OUString SbiImage::GetString( short nId ) const
     470             : {
     471       22739 :     if( nId && nId <= nStrings )
     472             :     {
     473       22739 :         sal_uInt32 nOff = pStringOff[ nId - 1 ];
     474       22739 :         sal_Unicode* pStr = pStrings + nOff;
     475             : 
     476             :         // #i42467: Special treatment for vbNullChar
     477       22739 :         if( *pStr == 0 )
     478             :         {
     479         183 :             sal_uInt32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff;
     480         183 :             sal_uInt32 nLen = nNextOff - nOff - 1;
     481         183 :             if( nLen == 1 )
     482             :             {
     483             :                 // Force length 1 and make char 0 afterwards
     484           0 :                 OUString aNullCharStr( (sal_Unicode)0);
     485           0 :                 return aNullCharStr;
     486             :             }
     487             :         }
     488             :         else
     489             :         {
     490       22556 :             return OUString(pStr);
     491             :         }
     492             :     }
     493         183 :     return OUString();
     494             : }
     495             : 
     496         155 : const SbxObject* SbiImage::FindType (const OUString& aTypeName) const
     497             : {
     498         155 :     return rTypes.Is() ? static_cast<SbxObject*>(rTypes->Find(aTypeName,SbxCLASS_OBJECT)) : NULL;
     499             : }
     500             : 
     501           0 : sal_uInt16 SbiImage::CalcLegacyOffset( sal_Int32 nOffset )
     502             : {
     503           0 :     return SbiCodeGen::calcLegacyOffSet( reinterpret_cast<sal_uInt8*>(pCode), nOffset ) ;
     504             : }
     505             : 
     506           0 : sal_uInt32 SbiImage::CalcNewOffset( sal_Int16 nOffset )
     507             : {
     508           0 :     return SbiCodeGen::calcNewOffSet( reinterpret_cast<sal_uInt8*>(pLegacyPCode), nOffset ) ;
     509             : }
     510             : 
     511         183 : void  SbiImage::ReleaseLegacyBuffer()
     512             : {
     513         183 :     delete[] pLegacyPCode;
     514         183 :     pLegacyPCode = NULL;
     515         183 :     nLegacyCodeSize = 0;
     516         183 : }
     517             : 
     518           0 : bool SbiImage::ExceedsLegacyLimits()
     519             : {
     520           0 :     return ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L );
     521             : }
     522             : 
     523             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11