LCOV - code coverage report
Current view: top level - basic/source/classes - image.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 97 252 38.5 %
Date: 2014-11-03 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         348 : SbiImage::SbiImage()
      31             : {
      32         348 :     pStringOff = NULL;
      33         348 :     pStrings   = NULL;
      34         348 :     pCode      = NULL;
      35         348 :     pLegacyPCode = NULL;
      36         348 :     nFlags     = 0;
      37         348 :     nStrings   = 0;
      38         348 :     nStringSize= 0;
      39         348 :     nCodeSize  = 0;
      40             :     nLegacyCodeSize  =
      41         348 :     nDimBase   = 0;
      42             :     bInit      =
      43         348 :     bError     = false;
      44         348 :     bFirstInit = true;
      45         348 :     eCharSet   = osl_getThreadTextEncoding();
      46         348 :     nStringIdx = 0;
      47         348 :     nStringOff = 0;
      48         348 : }
      49             : 
      50         692 : SbiImage::~SbiImage()
      51             : {
      52         346 :     Clear();
      53         346 : }
      54             : 
      55         346 : void SbiImage::Clear()
      56             : {
      57         346 :     delete[] pStringOff;
      58         346 :     delete[] pStrings;
      59         346 :     delete[] pCode;
      60         346 :     ReleaseLegacyBuffer();
      61         346 :     pStringOff = NULL;
      62         346 :     pStrings   = NULL;
      63         346 :     pCode      = NULL;
      64         346 :     nFlags     = 0;
      65         346 :     nStrings   = 0;
      66         346 :     nStringSize= 0;
      67         346 :     nLegacyCodeSize  = 0;
      68         346 :     nCodeSize  = 0;
      69         346 :     eCharSet   = osl_getThreadTextEncoding();
      70         346 :     nDimBase   = 0;
      71         346 :     bError     = false;
      72         346 : }
      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           0 :         r.ReadUInt32( nVersion ).ReadUInt32( nCharSet ).ReadUInt32( lDimBase )
     127           0 :          .ReadUInt16( nFlags ).ReadUInt16( nReserved1 ).ReadUInt32( nReserved2 ).ReadUInt32( nReserved3 );
     128           0 :         eCharSet = nCharSet;
     129           0 :         eCharSet = GetSOLoadTextEncoding( eCharSet );
     130           0 :         bBadVer  = ( nVersion > B_CURVERSION );
     131           0 :         nDimBase = (sal_uInt16) lDimBase;
     132             :     }
     133             : 
     134           0 :     bool bLegacy = ( nVersion < B_EXT_IMG_VERSION );
     135             : 
     136             :     sal_Size nNext;
     137           0 :     while( ( nNext = r.Tell() ) < nLast )
     138             :     {
     139             : 
     140           0 :         r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
     141           0 :         nNext += nLen + 8;
     142           0 :         if( r.GetError() == SVSTREAM_OK )
     143             :         {
     144           0 :             switch( nSign )
     145             :             {
     146             :             case B_NAME:
     147           0 :                 aName = r.ReadUniOrByteString(eCharSet);
     148           0 :                 break;
     149             :             case B_COMMENT:
     150           0 :                 aComment = r.ReadUniOrByteString(eCharSet );
     151           0 :                 break;
     152             :             case B_SOURCE:
     153             :             {
     154           0 :                 aOUSource = r.ReadUniOrByteString(eCharSet);
     155           0 :                 break;
     156             :             }
     157             :             case B_EXTSOURCE:
     158             :             {
     159           0 :                 for( sal_uInt16 j = 0 ; j < nCount ; j++ )
     160             :                 {
     161           0 :                     aOUSource += r.ReadUniOrByteString(eCharSet);
     162             :                 }
     163           0 :                 break;
     164             :             }
     165             :             case B_PCODE:
     166           0 :                 if( bBadVer ) break;
     167           0 :                 pCode = new char[ nLen ];
     168           0 :                 nCodeSize = nLen;
     169           0 :                 r.Read( pCode, nCodeSize );
     170           0 :                 if ( bLegacy )
     171             :                 {
     172           0 :                     ReleaseLegacyBuffer(); // release any previously held buffer
     173           0 :                     nLegacyCodeSize = (sal_uInt16) nCodeSize;
     174           0 :                     pLegacyPCode = pCode;
     175             : 
     176           0 :                     PCodeBuffConvertor< sal_uInt16, sal_uInt32 > aLegacyToNew( (sal_uInt8*)pLegacyPCode, nLegacyCodeSize );
     177           0 :                     aLegacyToNew.convert();
     178           0 :                     pCode = (char*)aLegacyToNew.GetBuffer();
     179           0 :                     nCodeSize = aLegacyToNew.GetSize();
     180             :                     // we don't release the legacy buffer
     181             :                     // right now, thats because the module
     182             :                     // needs it to fix up the method
     183             :                     // nStart members. When that is done
     184             :                     // the module can release the buffer
     185             :                     // or it can wait until this routine
     186             :                     // is called again or when this class                       // destructs all of which will trigger
     187             :                     // release of the buffer.
     188             :                 }
     189           0 :                 break;
     190             :             case B_PUBLICS:
     191             :             case B_POOLDIR:
     192             :             case B_SYMPOOL:
     193             :             case B_LINERANGES:
     194           0 :                 break;
     195             :             case B_STRINGPOOL:
     196           0 :                 if( bBadVer ) break;
     197           0 :                 MakeStrings( nCount );
     198             :                 short i;
     199           0 :                 for( i = 0; i < nStrings && SbiGood( r ); i++ )
     200             :                 {
     201           0 :                     r.ReadUInt32( nOff );
     202           0 :                     pStringOff[ i ] = (sal_uInt16) nOff;
     203             :                 }
     204           0 :                 r.ReadUInt32( nLen );
     205           0 :                 if( SbiGood( r ) )
     206             :                 {
     207           0 :                     delete [] pStrings;
     208           0 :                     pStrings = new sal_Unicode[ nLen ];
     209           0 :                     nStringSize = (sal_uInt16) nLen;
     210             : 
     211           0 :                     boost::scoped_array<char> pByteStrings(new char[ nLen ]);
     212           0 :                     r.Read( pByteStrings.get(), nStringSize );
     213           0 :                     for( short j = 0; j < nStrings; j++ )
     214             :                     {
     215           0 :                         sal_uInt16 nOff2 = (sal_uInt16) pStringOff[ j ];
     216           0 :                         OUString aStr( pByteStrings.get() + nOff2, strlen(pByteStrings.get() + nOff2), eCharSet );
     217           0 :                         memcpy( pStrings + nOff2, aStr.getStr(), (aStr.getLength() + 1) * sizeof( sal_Unicode ) );
     218           0 :                     }
     219             :                 }
     220           0 :                 break;
     221             :             case B_MODEND:
     222           0 :                 goto done;
     223             :             default:
     224           0 :                 break;
     225             :             }
     226             :         }
     227             :         else
     228             :         {
     229           0 :             break;
     230             :         }
     231           0 :         r.Seek( nNext );
     232             :     }
     233             : done:
     234           0 :     r.Seek( nLast );
     235           0 :     if( !SbiGood( r ) )
     236             :     {
     237           0 :         bError = true;
     238             :     }
     239           0 :     return !bError;
     240             : }
     241             : 
     242           0 : bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
     243             : {
     244           0 :     bool bLegacy = ( nVer < B_EXT_IMG_VERSION );
     245             : 
     246             :     // detect if old code exceeds legacy limits
     247             :     // if so, then disallow save
     248           0 :     if ( bLegacy && ExceedsLegacyLimits() )
     249             :     {
     250           0 :         SbiImage aEmptyImg;
     251           0 :         aEmptyImg.aName = aName;
     252           0 :         aEmptyImg.Save( r, B_LEGACYVERSION );
     253           0 :         return true;
     254             :     }
     255             :     // First of all the header
     256           0 :     sal_uIntPtr nStart = SbiOpenRecord( r, B_MODULE, 1 );
     257             :     sal_uIntPtr nPos;
     258             : 
     259           0 :     eCharSet = GetSOStoreTextEncoding( eCharSet );
     260           0 :     if ( bLegacy )
     261             :     {
     262           0 :         r.WriteInt32( B_LEGACYVERSION );
     263             :     }
     264             :     else
     265             :     {
     266           0 :         r.WriteInt32( B_CURVERSION );
     267             :     }
     268           0 :     r .WriteInt32( eCharSet )
     269           0 :       .WriteInt32( nDimBase )
     270           0 :       .WriteInt16(  nFlags )
     271           0 :       .WriteInt16(  0 )
     272           0 :       .WriteInt32( 0 )
     273           0 :       .WriteInt32( 0 );
     274             : 
     275             :     // Name?
     276           0 :     if( !aName.isEmpty() && SbiGood( r ) )
     277             :     {
     278           0 :         nPos = SbiOpenRecord( r, B_NAME, 1 );
     279           0 :         r.WriteUniOrByteString( aName, eCharSet );
     280           0 :         SbiCloseRecord( r, nPos );
     281             :     }
     282             :     // Comment?
     283           0 :     if( !aComment.isEmpty() && SbiGood( r ) )
     284             :     {
     285           0 :         nPos = SbiOpenRecord( r, B_COMMENT, 1 );
     286           0 :         r.WriteUniOrByteString( aComment, eCharSet );
     287           0 :         SbiCloseRecord( r, nPos );
     288             :     }
     289             :     // Source?
     290           0 :     if( !aOUSource.isEmpty() && SbiGood( r ) )
     291             :     {
     292           0 :         nPos = SbiOpenRecord( r, B_SOURCE, 1 );
     293           0 :         r.WriteUniOrByteString( aOUSource, eCharSet );
     294           0 :         SbiCloseRecord( r, nPos );
     295             :     }
     296             :     // Binary data?
     297           0 :     if( pCode && SbiGood( r ) )
     298             :     {
     299           0 :         nPos = SbiOpenRecord( r, B_PCODE, 1 );
     300           0 :         if ( bLegacy )
     301             :         {
     302           0 :             ReleaseLegacyBuffer(); // release any previously held buffer
     303           0 :             PCodeBuffConvertor< sal_uInt32, sal_uInt16 > aNewToLegacy( (sal_uInt8*)pCode, nCodeSize );
     304           0 :             aNewToLegacy.convert();
     305           0 :             pLegacyPCode = (char*)aNewToLegacy.GetBuffer();
     306           0 :             nLegacyCodeSize = aNewToLegacy.GetSize();
     307           0 :             r.Write( pLegacyPCode, nLegacyCodeSize );
     308             :         }
     309             :         else
     310             :         {
     311           0 :             r.Write( pCode, nCodeSize );
     312             :         }
     313           0 :         SbiCloseRecord( r, nPos );
     314             :     }
     315             :     // String-Pool?
     316           0 :     if( nStrings )
     317             :     {
     318           0 :         nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings );
     319             :         // For every String:
     320             :         //  sal_uInt32 Offset of the Strings in the Stringblock
     321             :         short i;
     322             : 
     323           0 :         for( i = 0; i < nStrings && SbiGood( r ); i++ )
     324             :         {
     325           0 :             r.WriteUInt32( pStringOff[ i ] );
     326             :         }
     327             :         // Then the String-Block
     328           0 :         boost::scoped_array<char> pByteStrings(new char[ nStringSize ]);
     329           0 :         for( i = 0; i < nStrings; i++ )
     330             :         {
     331           0 :             sal_uInt16 nOff = (sal_uInt16) pStringOff[ i ];
     332           0 :             OString aStr(OUStringToOString(OUString(pStrings + nOff), eCharSet));
     333           0 :             memcpy( pByteStrings.get() + nOff, aStr.getStr(), (aStr.getLength() + 1) * sizeof( char ) );
     334           0 :         }
     335           0 :         r.WriteUInt32( nStringSize );
     336           0 :         r.Write( pByteStrings.get(), nStringSize );
     337             : 
     338           0 :         pByteStrings.reset();
     339           0 :         SbiCloseRecord( r, nPos );
     340             :     }
     341             :     // Set overall length
     342           0 :     SbiCloseRecord( r, nStart );
     343           0 :     if( !SbiGood( r ) )
     344             :     {
     345           0 :         bError = true;
     346             :     }
     347           0 :     return !bError;
     348             : }
     349             : 
     350             : /**************************************************************************
     351             : *
     352             : *    Routines called by the compiler
     353             : *
     354             : **************************************************************************/
     355             : 
     356         348 : void SbiImage::MakeStrings( short nSize )
     357             : {
     358         348 :     nStrings = 0;
     359         348 :     nStringIdx = 0;
     360         348 :     nStringOff = 0;
     361         348 :     nStringSize = 1024;
     362         348 :     pStrings = new sal_Unicode[ nStringSize ];
     363         348 :     pStringOff = new sal_uInt32[ nSize ];
     364         348 :     if( pStrings && pStringOff )
     365             :     {
     366         348 :         nStrings = nSize;
     367         348 :         memset( pStringOff, 0, nSize * sizeof( sal_uInt32 ) );
     368         348 :         memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) );
     369             :     }
     370             :     else
     371             :     {
     372           0 :         bError = true;
     373             :     }
     374         348 : }
     375             : 
     376             : // Add a string to StringPool. The String buffer is dynamically
     377             : // growing in 1K-Steps
     378       11762 : void SbiImage::AddString( const OUString& r )
     379             : {
     380       11762 :     if( nStringIdx >= nStrings )
     381             :     {
     382           0 :         bError = true;
     383             :     }
     384       11762 :     if( !bError )
     385             :     {
     386       11762 :         sal_Int32  len = r.getLength() + 1;
     387       11762 :         sal_uInt32 needed = nStringOff + len;
     388       11762 :         if( needed > 0xFFFFFF00L )
     389             :         {
     390           0 :             bError = true;  // out of mem!
     391             :         }
     392       11762 :         else if( needed > nStringSize )
     393             :         {
     394          74 :             sal_uInt32 nNewLen = needed + 1024;
     395          74 :             nNewLen &= 0xFFFFFC00;  // trim to 1K border
     396          74 :             sal_Unicode* p = NULL;
     397          74 :             if( (p = new sal_Unicode[ nNewLen ]) != NULL )
     398             :             {
     399          74 :                 memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) );
     400          74 :                 delete[] pStrings;
     401          74 :                 pStrings = p;
     402          74 :                 nStringSize = sal::static_int_cast< sal_uInt16 >(nNewLen);
     403             :             }
     404             :             else
     405             :             {
     406           0 :                 bError = true;
     407             :             }
     408             :         }
     409       11762 :         if( !bError )
     410             :         {
     411       11762 :             pStringOff[ nStringIdx++ ] = nStringOff;
     412       11762 :             memcpy( pStrings + nStringOff, r.getStr(), len * sizeof( sal_Unicode ) );
     413       11762 :             nStringOff = nStringOff + len;
     414             :             // Last String? The update the size of the buffer
     415       11762 :             if( nStringIdx >= nStrings )
     416             :             {
     417         348 :                 nStringSize = nStringOff;
     418             :             }
     419             :         }
     420             :     }
     421       11762 : }
     422             : 
     423             : // Add code block
     424             : // The block was fetched by the compiler from class SbBuffer and
     425             : // is already created with new. Additionally it contains all Integers
     426             : // in Big Endian format, so can be directly read/written.
     427         348 : void SbiImage::AddCode( char* p, sal_uInt32 s )
     428             : {
     429         348 :     pCode = p;
     430         348 :     nCodeSize = s;
     431         348 : }
     432             : 
     433             : // Add user type
     434           2 : void SbiImage::AddType(SbxObject* pObject)
     435             : {
     436           2 :     if( !rTypes.Is() )
     437             :     {
     438           2 :         rTypes = new SbxArray;
     439             :     }
     440           2 :     SbxObject *pCopyObject = new SbxObject(*pObject);
     441           2 :     rTypes->Insert (pCopyObject,rTypes->Count());
     442           2 : }
     443             : 
     444           0 : void SbiImage::AddEnum(SbxObject* pObject) // Register enum type
     445             : {
     446           0 :     if( !rEnums.Is() )
     447             :     {
     448           0 :         rEnums = new SbxArray;
     449             :     }
     450           0 :     rEnums->Insert( pObject, rEnums->Count() );
     451           0 : }
     452             : 
     453             : 
     454             : /**************************************************************************
     455             : *
     456             : *    Accessing the image
     457             : *
     458             : **************************************************************************/
     459             : 
     460             : // Note: IDs start with 1
     461       42536 : OUString SbiImage::GetString( short nId ) const
     462             : {
     463       42536 :     if( nId && nId <= nStrings )
     464             :     {
     465       42536 :         sal_uInt32 nOff = pStringOff[ nId - 1 ];
     466       42536 :         sal_Unicode* pStr = pStrings + nOff;
     467             : 
     468             :         // #i42467: Special treatment for vbNullChar
     469       42536 :         if( *pStr == 0 )
     470             :         {
     471         362 :             sal_uInt32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff;
     472         362 :             sal_uInt32 nLen = nNextOff - nOff - 1;
     473         362 :             if( nLen == 1 )
     474             :             {
     475             :                 // Force length 1 and make char 0 afterwards
     476           0 :                 OUString aNullCharStr( (sal_Unicode)0);
     477           0 :                 return aNullCharStr;
     478             :             }
     479             :         }
     480             :         else
     481             :         {
     482       42174 :             return OUString(pStr);
     483             :         }
     484             :     }
     485         362 :     return OUString();
     486             : }
     487             : 
     488         310 : const SbxObject* SbiImage::FindType (const OUString& aTypeName) const
     489             : {
     490         310 :     return rTypes.Is() ? static_cast<SbxObject*>(rTypes->Find(aTypeName,SbxCLASS_OBJECT)) : NULL;
     491             : }
     492             : 
     493           0 : sal_uInt16 SbiImage::CalcLegacyOffset( sal_Int32 nOffset )
     494             : {
     495           0 :     return SbiCodeGen::calcLegacyOffSet( (sal_uInt8*)pCode, nOffset ) ;
     496             : }
     497             : 
     498           0 : sal_uInt32 SbiImage::CalcNewOffset( sal_Int16 nOffset )
     499             : {
     500           0 :     return SbiCodeGen::calcNewOffSet( (sal_uInt8*)pLegacyPCode, nOffset ) ;
     501             : }
     502             : 
     503         346 : void  SbiImage::ReleaseLegacyBuffer()
     504             : {
     505         346 :     delete[] pLegacyPCode;
     506         346 :     pLegacyPCode = NULL;
     507         346 :     nLegacyCodeSize = 0;
     508         346 : }
     509             : 
     510           0 : bool SbiImage::ExceedsLegacyLimits()
     511             : {
     512           0 :     return ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L );
     513             : }
     514             : 
     515             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10