LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / basic / source / classes / image.cxx
blob229dc8058518fe1818b4c48eb878de2b76210132
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/stream.hxx>
21 #include <tools/tenccvt.hxx>
22 #include <osl/thread.h>
23 #include <o3tl/safeint.hxx>
24 #include <sal/log.hxx>
25 #include <basic/sbx.hxx>
26 #include <sb.hxx>
27 #include <sbxprop.hxx>
28 #include <string.h>
29 #include <image.hxx>
30 #include <codegen.hxx>
31 #include <memory>
32 #include <string_view>
34 SbiImage::SbiImage()
35 : bError(false)
36 , nFlags(SbiImageFlags::NONE)
37 , nStringSize(0)
38 , nDimBase(0)
39 , eCharSet(osl_getThreadTextEncoding())
40 , nStringIdx(0)
41 , nStringOff(0)
42 , bInit(false)
43 , bFirstInit(true)
47 SbiImage::~SbiImage()
51 void SbiImage::Clear()
53 mvStringOffsets.clear();
54 pStrings.reset();
55 aCode.clear();
56 aLegacyPCode.clear();
57 nFlags = SbiImageFlags::NONE;
58 nStringSize= 0;
59 eCharSet = osl_getThreadTextEncoding();
60 nDimBase = 0;
61 bError = false;
64 // Open Record
65 static sal_uInt64 SbiOpenRecord( SvStream& r, FileOffset nSignature, sal_uInt16 nElem )
67 sal_uInt64 nPos = r.Tell();
68 r.WriteUInt16( static_cast<sal_uInt16>( nSignature ) )
69 .WriteInt32( 0 ).WriteUInt16( nElem );
70 return nPos;
73 // Close Record
74 static void SbiCloseRecord( SvStream& r, sal_uInt64 nOff )
76 sal_uInt64 nPos = r.Tell();
77 r.Seek( nOff + 2 );
78 r.WriteInt32(nPos - nOff - 8 );
79 r.Seek( nPos );
82 constexpr sal_uInt32 nUnicodeDataMagicNumber = 0x556E6920; // "Uni " BE
84 static bool GetToUnicodePoolData(SvStream& r, sal_uInt64 nLen, sal_uInt64 nNext)
86 const auto nPos = r.Tell();
87 // Check space for legacy data, magic number and Unicode data
88 bool bResult = nPos + nLen + sizeof(sal_uInt32) + nLen * sizeof(sal_Unicode) <= nNext;
89 if (bResult)
91 r.SeekRel(nLen); // Skip legacy data
92 sal_uInt32 nMagic = 0;
93 r.ReadUInt32(nMagic);
94 if (nMagic != nUnicodeDataMagicNumber)
96 r.Seek(nPos); // return
97 bResult = false;
100 return bResult;
103 bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
106 sal_uInt16 nSign, nCount;
107 sal_uInt32 nLen;
109 Clear();
110 // Read Master-Record
111 r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
112 sal_uInt64 nLast = r.Tell() + nLen;
113 bool bBadVer = false;
114 if( nSign == static_cast<sal_uInt16>( FileOffset::Module ) )
116 sal_uInt32 nCharSet; // System charset
117 sal_uInt32 lDimBase;
118 sal_uInt16 nTmpFlags;
119 sal_uInt16 nReserved1;
120 sal_uInt32 nReserved2;
121 sal_uInt32 nReserved3;
122 r.ReadUInt32( nVersion ).ReadUInt32( nCharSet ).ReadUInt32( lDimBase )
123 .ReadUInt16( nTmpFlags ).ReadUInt16( nReserved1 ).ReadUInt32( nReserved2 ).ReadUInt32( nReserved3 );
124 nFlags = static_cast<SbiImageFlags>(nTmpFlags);
125 eCharSet = nCharSet;
126 eCharSet = GetSOLoadTextEncoding( eCharSet );
127 bBadVer = ( nVersion > B_CURVERSION );
128 nDimBase = static_cast<sal_uInt16>(lDimBase);
131 bool bLegacy = ( nVersion < B_EXT_IMG_VERSION );
133 sal_uInt64 nNext;
134 while( ( nNext = r.Tell() ) < nLast )
137 r.ReadUInt16( nSign ).ReadUInt32( nLen ).ReadUInt16( nCount );
138 nNext += nLen + 8;
139 if( r.GetError() == ERRCODE_NONE )
141 switch( static_cast<FileOffset>( nSign ) )
143 case FileOffset::Name:
144 aName = r.ReadUniOrByteString(eCharSet);
145 break;
146 case FileOffset::Comment:
147 aComment = r.ReadUniOrByteString(eCharSet );
148 break;
149 case FileOffset::Source:
151 aOUSource = r.ReadUniOrByteString(eCharSet);
152 break;
154 case FileOffset::ExtSource:
156 //assuming an empty string with just the lead 32bit/16bit len indicator
157 const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
158 const sal_uInt64 nMaxStrings = r.remainingSize() / nMinStringSize;
159 if (nCount > nMaxStrings)
161 SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
162 " max possible entries, but " << nCount << " claimed, truncating");
163 nCount = nMaxStrings;
165 for( sal_uInt16 j = 0; j < nCount; ++j)
167 aOUSource += r.ReadUniOrByteString(eCharSet);
169 break;
171 case FileOffset::PCode:
172 if( bBadVer ) break;
173 aCode.resize(nLen);
174 r.ReadBytes(aCode.data(), aCode.size());
175 if ( bLegacy )
177 aLegacyPCode = std::move(aCode);
179 PCodeBuffConvertor<sal_uInt16, sal_uInt32> aLegacyToNew(aLegacyPCode.data(),
180 aLegacyPCode.size());
181 aLegacyToNew.convert();
182 aCode = aLegacyToNew.GetBuffer();
183 // we don't release the legacy buffer
184 // right now, that's because the module
185 // needs it to fix up the method
186 // nStart members. When that is done
187 // the module can release the buffer
188 // or it can wait until this routine
189 // is called again or when this class // destructs all of which will trigger
190 // release of the buffer.
192 break;
193 case FileOffset::Publics:
194 case FileOffset::PoolDir:
195 case FileOffset::SymPool:
196 case FileOffset::LineRanges:
197 break;
198 case FileOffset::StringPool:
200 // the data layout is: nCount of 32-bit offsets into both legacy 1-byte char stream
201 // and resulting char buffer (1:1 correspondence assumed; 16 of 32 bits used);
202 // 32-bit length N of following 1-byte char stream (16 bits used); N bytes of 1-byte
203 // char stream; then optional magic number and stream of N sal_Unicode characters.
205 if( bBadVer ) break;
206 //assuming an empty string with just the lead 32bit len indicator
207 const sal_uInt64 nMinStringSize = 4;
208 const sal_uInt64 nMaxStrings = r.remainingSize() / nMinStringSize;
209 if (nCount > nMaxStrings)
211 SAL_WARN("basic", "Parsing error: " << nMaxStrings <<
212 " max possible entries, but " << nCount << " claimed, truncating");
213 nCount = nMaxStrings;
215 MakeStrings( nCount );
216 for (size_t i = 0; i < mvStringOffsets.size() && r.good(); i++)
218 sal_uInt32 nOff;
219 r.ReadUInt32( nOff );
220 mvStringOffsets[ i ] = static_cast<sal_uInt16>(nOff);
222 r.ReadUInt32( nLen );
223 if (r.good())
225 pStrings.reset(new sal_Unicode[ nLen ]);
226 nStringSize = static_cast<sal_uInt16>(nLen);
228 if (GetToUnicodePoolData(r, nLen, nNext))
230 OUString s = read_uInt16s_ToOUString(r, nLen);
231 memcpy(pStrings.get(), s.getStr(), s.getLength() * sizeof(sal_Unicode));
233 else
235 std::unique_ptr<char[]> pByteStrings(new char[nLen]);
236 r.ReadBytes(pByteStrings.get(), nLen);
237 for (size_t j = 0; j < mvStringOffsets.size(); j++)
239 sal_uInt16 nOff2 = static_cast<sal_uInt16>(mvStringOffsets[j]);
240 OUString aStr(pByteStrings.get() + nOff2, strlen(pByteStrings.get() + nOff2), eCharSet);
241 memcpy(pStrings.get() + nOff2, aStr.getStr(), (aStr.getLength() + 1) * sizeof(sal_Unicode));
245 break;
247 case FileOffset::UserTypes:
249 //assuming an empty string with just the lead 32bit/16bit len indicator
250 const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
251 const sal_uInt64 nMinRecordSize = nMinStringSize + sizeof(sal_Int16);
252 const sal_uInt64 nMaxRecords = r.remainingSize() / nMinRecordSize;
253 if (nCount > nMaxRecords)
255 SAL_WARN("basic", "Parsing error: " << nMaxRecords <<
256 " max possible entries, but " << nCount << " claimed, truncating");
257 nCount = nMaxRecords;
260 // User defined types; ref.: SbiParser::DefType
261 for (sal_uInt16 i = 0; i < nCount; i++)
263 OUString aTypeName = r.ReadUniOrByteString(eCharSet);
265 sal_uInt16 nTypeMembers;
266 r.ReadUInt16(nTypeMembers);
268 const sal_uInt64 nMaxTypeMembers = r.remainingSize() / 8;
269 if (nTypeMembers > nMaxTypeMembers)
271 SAL_WARN("basic", "Parsing error: " << nMaxTypeMembers <<
272 " max possible entries, but " << nTypeMembers << " claimed, truncating");
273 nTypeMembers = nMaxTypeMembers;
276 SbxObject *pType = new SbxObject(aTypeName);
277 SbxArray *pTypeMembers = pType->GetProperties();
279 for (sal_uInt16 j = 0; j < nTypeMembers; j++)
281 OUString aMemberName = r.ReadUniOrByteString(eCharSet);
283 sal_Int16 aIntMemberType;
284 r.ReadInt16(aIntMemberType);
285 SbxDataType aMemberType = static_cast< SbxDataType > ( aIntMemberType );
287 SbxProperty *pTypeElem = new SbxProperty( aMemberName, aMemberType );
289 sal_uInt32 aIntFlag;
290 r.ReadUInt32(aIntFlag);
291 SbxFlagBits nElemFlags = static_cast< SbxFlagBits > ( aIntFlag );
293 pTypeElem->SetFlags(nElemFlags);
295 sal_Int16 hasObject;
296 r.ReadInt16(hasObject);
298 if (hasObject == 1)
300 if(aMemberType == SbxOBJECT)
302 // nested user defined types
303 // declared before use, so it is ok to reference it by name on load
304 OUString aNestedTypeName = r.ReadUniOrByteString(eCharSet);
305 SbxObject* pNestedTypeObj = static_cast< SbxObject* >( rTypes->Find( aNestedTypeName, SbxClassType::Object ) );
306 if (pNestedTypeObj)
308 SbxObjectRef pCloneObj = cloneTypeObjectImpl( *pNestedTypeObj );
309 pTypeElem->PutObject( pCloneObj.get() );
312 else
314 // an array
315 SbxDimArray* pArray = new SbxDimArray(
316 static_cast<SbxDataType>(aMemberType & 0x0FFF));
318 sal_Int16 isFixedSize;
319 r.ReadInt16(isFixedSize);
320 if (isFixedSize == 1)
321 pArray->setHasFixedSize( true );
323 sal_Int32 nDims;
324 r.ReadInt32(nDims);
325 for (sal_Int32 d = 0; d < nDims; d++)
327 sal_Int32 lBound;
328 sal_Int32 uBound;
329 r.ReadInt32(lBound).ReadInt32(uBound);
330 pArray->unoAddDim(lBound, uBound);
333 const SbxFlagBits nSavFlags = pTypeElem->GetFlags();
334 // need to reset the FIXED flag
335 // when calling PutObject ( because the type will not match Object )
336 pTypeElem->ResetFlag(SbxFlagBits::Fixed);
337 pTypeElem->PutObject( pArray );
338 pTypeElem->SetFlags(nSavFlags);
342 pTypeMembers->Insert(pTypeElem, pTypeMembers->Count());
346 pType->Remove( "Name", SbxClassType::DontCare );
347 pType->Remove( "Parent", SbxClassType::DontCare );
349 AddType(pType);
351 break;
353 case FileOffset::ModEnd:
354 goto done;
355 default:
356 break;
359 else
361 break;
363 r.Seek( nNext );
365 done:
366 r.Seek( nLast );
367 if (!r.good())
369 bError = true;
371 return !bError;
374 bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
376 bool bLegacy = ( nVer < B_EXT_IMG_VERSION );
378 // detect if old code exceeds legacy limits
379 // if so, then disallow save
380 if ( bLegacy && ExceedsLegacyLimits() )
382 SbiImage aEmptyImg;
383 aEmptyImg.aName = aName;
384 aEmptyImg.Save( r, B_LEGACYVERSION );
385 return true;
387 // First of all the header
388 sal_uInt64 nStart = SbiOpenRecord( r, FileOffset::Module, 1 );
389 sal_uInt64 nPos;
391 eCharSet = GetSOStoreTextEncoding( eCharSet );
392 if ( bLegacy )
394 r.WriteInt32( B_LEGACYVERSION );
396 else
398 r.WriteInt32( B_CURVERSION );
400 r .WriteInt32( eCharSet )
401 .WriteInt32( nDimBase )
402 .WriteInt16( static_cast<sal_uInt16>(nFlags) )
403 .WriteInt16( 0 )
404 .WriteInt32( 0 )
405 .WriteInt32( 0 );
407 // Name?
408 if (!aName.isEmpty() && r.good())
410 nPos = SbiOpenRecord( r, FileOffset::Name, 1 );
411 r.WriteUniOrByteString( aName, eCharSet );
412 SbiCloseRecord( r, nPos );
414 // Comment?
415 if (!aComment.isEmpty() && r.good())
417 nPos = SbiOpenRecord( r, FileOffset::Comment, 1 );
418 r.WriteUniOrByteString( aComment, eCharSet );
419 SbiCloseRecord( r, nPos );
421 // Source?
422 if (!aOUSource.isEmpty() && r.good())
424 nPos = SbiOpenRecord( r, FileOffset::Source, 1 );
425 r.WriteUniOrByteString( aOUSource, eCharSet );
426 SbiCloseRecord( r, nPos );
428 // Binary data?
429 if (aCode.size() && r.good())
431 nPos = SbiOpenRecord( r, FileOffset::PCode, 1 );
432 if ( bLegacy )
434 PCodeBuffConvertor<sal_uInt32, sal_uInt16> aNewToLegacy(aCode.data(), aCode.size());
435 aNewToLegacy.convert();
436 aLegacyPCode = aNewToLegacy.GetBuffer();
437 r.WriteBytes(aLegacyPCode.data(), aLegacyPCode.size());
439 else
441 r.WriteBytes(aCode.data(), aCode.size());
443 SbiCloseRecord( r, nPos );
445 // String-Pool?
446 if( !mvStringOffsets.empty() )
448 nPos = SbiOpenRecord( r, FileOffset::StringPool, mvStringOffsets.size() );
449 // For every String:
450 // sal_uInt32 Offset of the Strings in the Stringblock
451 for (size_t i = 0; i < mvStringOffsets.size() && r.good(); i++)
453 r.WriteUInt32( mvStringOffsets[ i ] );
455 // Then the String-Block
456 std::unique_ptr<char[]> pByteStrings(new char[ nStringSize ]);
457 for( size_t i = 0; i < mvStringOffsets.size(); i++ )
459 sal_uInt16 nOff = static_cast<sal_uInt16>(mvStringOffsets[ i ]);
460 OString aStr(OUStringToOString(std::u16string_view(pStrings.get() + nOff), eCharSet));
461 memcpy( pByteStrings.get() + nOff, aStr.getStr(), (aStr.getLength() + 1) * sizeof( char ) );
463 r.WriteUInt32( nStringSize );
464 r.WriteBytes(pByteStrings.get(), nStringSize);
465 pByteStrings.reset();
467 // Now write magic number and store the same data in UTF-16; this is backward compatible:
468 // old readers will not read this data after having read legacy data, and will proceed
469 // straight to the end of the record. So no version restriction here.
470 r.WriteUInt32(nUnicodeDataMagicNumber);
471 write_uInt16s_FromOUString(r, std::u16string_view(pStrings.get(), nStringSize));
473 SbiCloseRecord( r, nPos );
475 // User defined types
476 if ( rTypes.is() )
478 sal_uInt32 nTypes = rTypes->Count();
479 assert(nTypes <= std::numeric_limits<sal_uInt16>::max());
480 if (nTypes > 0 )
482 nPos = SbiOpenRecord( r, FileOffset::UserTypes, sal::static_int_cast<sal_uInt16>(nTypes) );
484 for (sal_uInt32 i = 0; i < nTypes; i++)
486 SbxObject* pType = static_cast<SbxObject*>(rTypes->Get(i));
487 OUString aTypeName = pType->GetClassName();
489 r.WriteUniOrByteString( aTypeName, eCharSet );
491 SbxArray *pTypeMembers = pType->GetProperties();
492 sal_uInt32 nTypeMembers = pTypeMembers->Count();
493 assert(nTypeMembers <= std::numeric_limits<sal_uInt16>::max());
495 r.WriteInt16(sal::static_int_cast<sal_uInt16>(nTypeMembers));
497 for (sal_uInt32 j = 0; j < nTypeMembers; j++)
500 SbxProperty* pTypeElem = static_cast<SbxProperty*>(pTypeMembers->Get(j));
502 const OUString& aElemName = pTypeElem->GetName();
503 r.WriteUniOrByteString( aElemName, eCharSet );
505 SbxDataType dataType = pTypeElem->GetType();
506 r.WriteInt16(dataType);
508 SbxFlagBits nElemFlags = pTypeElem->GetFlags();
509 r.WriteUInt32(static_cast< sal_uInt32 > (nElemFlags) );
511 SbxBase* pElemObject = pTypeElem->GetObject();
513 if (pElemObject)
515 r.WriteInt16(1); // has elem Object
517 if( dataType == SbxOBJECT )
519 // nested user defined types
520 // declared before use, so it is ok to reference it by name on load
521 SbxObject* pNestedType = static_cast< SbxObject* > ( pElemObject );
522 r.WriteUniOrByteString( pNestedType->GetClassName(), eCharSet );
524 else
526 // an array
527 SbxDimArray* pArray = static_cast< SbxDimArray* > ( pElemObject );
529 bool bFixedSize = pArray->hasFixedSize();
530 if (bFixedSize)
531 r.WriteInt16(1);
532 else
533 r.WriteInt16(0);
535 sal_Int32 nDims = pArray->GetDims();
536 r.WriteInt32(nDims);
538 for (sal_Int32 d = 1; d <= nDims; d++)
540 sal_Int32 lBound;
541 sal_Int32 uBound;
542 pArray->GetDim(d, lBound, uBound);
543 r.WriteInt32(lBound).WriteInt32(uBound);
547 else
548 r.WriteInt16(0); // no elem Object
552 SbiCloseRecord( r, nPos );
555 // Set overall length
556 SbiCloseRecord( r, nStart );
557 if (!r.good())
559 bError = true;
561 return !bError;
564 void SbiImage::MakeStrings( short nSize )
566 nStringIdx = 0;
567 nStringOff = 0;
568 nStringSize = 1024;
569 pStrings.reset( new sal_Unicode[ nStringSize ]);
570 mvStringOffsets.resize(nSize);
571 if (nSize != 0) {
572 memset( mvStringOffsets.data(), 0, nSize * sizeof( sal_uInt32 ) );
574 memset( pStrings.get(), 0, nStringSize * sizeof( sal_Unicode ) );
577 // Add a string to StringPool. The String buffer is dynamically
578 // growing in 1K-Steps
579 void SbiImage::AddString( const OUString& r )
581 if( nStringIdx >= short(mvStringOffsets.size()) )
583 bError = true;
585 if( bError )
586 return;
588 sal_Int32 len = r.getLength() + 1;
589 sal_uInt32 needed = nStringOff + len;
590 if( needed > 0xFFFFFF00 )
592 bError = true; // out of mem!
594 else if( needed > nStringSize )
596 sal_uInt32 nNewLen = needed + 1024;
597 nNewLen &= 0xFFFFFC00; // trim to 1K border
598 std::unique_ptr<sal_Unicode[]> p(new sal_Unicode[nNewLen]);
599 memcpy( p.get(), pStrings.get(), nStringSize * sizeof( sal_Unicode ) );
600 pStrings = std::move(p);
601 nStringSize = sal::static_int_cast< sal_uInt16 >(nNewLen);
603 if( !bError )
605 mvStringOffsets[ nStringIdx++ ] = nStringOff;
606 memcpy( pStrings.get() + nStringOff, r.getStr(), len * sizeof( sal_Unicode ) );
607 nStringOff = nStringOff + len;
608 // Last String? The update the size of the buffer
609 if( nStringIdx >= short(mvStringOffsets.size()) )
611 nStringSize = nStringOff;
616 // Add code block
617 // The block was fetched by the compiler from class SbBuffer and
618 // is already created with new. Additionally it contains all Integers
619 // in Big Endian format, so can be directly read/written.
620 void SbiImage::AddCode(std::vector<sal_uInt8>&& v)
622 aCode = std::move(v);
625 // Add user type
626 void SbiImage::AddType(SbxObject const * pObject)
628 if( !rTypes.is() )
630 rTypes = new SbxArray;
632 SbxObject *pCopyObject = new SbxObject(*pObject);
633 rTypes->Insert(pCopyObject, rTypes->Count());
636 void SbiImage::AddEnum(SbxObject* pObject) // Register enum type
638 if( !rEnums.is() )
640 rEnums = new SbxArray;
642 rEnums->Insert(pObject, rEnums->Count());
645 // Note: IDs start with 1
646 OUString SbiImage::GetString( short nId, SbxDataType *eType ) const
648 if( nId && nId <= short(mvStringOffsets.size()) )
650 sal_uInt32 nOff = mvStringOffsets[ nId - 1 ];
651 sal_Unicode* pStr = pStrings.get() + nOff;
653 sal_uInt32 nNextOff = (nId < short(mvStringOffsets.size())) ? mvStringOffsets[ nId ] : nStringSize;
654 sal_uInt32 nLen = nNextOff - nOff - 1;
655 // #i42467: Special treatment for vbNullChar
656 if (*pStr == 0)
658 if( nLen == 1 )
660 return OUString( u'\0');
663 else
665 // tdf#143707 - check if the data type character was added after the string termination
666 // symbol. It was added in basic/source/comp/symtbl.cxx.
667 OUString aOUStr(pStr);
668 if (eType != nullptr)
670 *eType = SbxSTRING;
671 if (o3tl::make_unsigned(aOUStr.getLength()) < nLen)
673 const sal_Unicode pTypeChar = *(pStrings.get() + nOff + aOUStr.getLength() + 1);
674 switch (pTypeChar)
676 // See GetSuffixType in basic/source/comp/scanner.cxx for type characters
677 case '%': *eType = SbxINTEGER; break;
678 case '&': *eType = SbxLONG; break;
679 case '!': *eType = SbxSINGLE; break;
680 case '#': *eType = SbxDOUBLE; break;
681 case '@': *eType = SbxCURRENCY; break;
682 // tdf#142460 - properly handle boolean values in string pool
683 case 'b': *eType = SbxBOOL; break;
687 return aOUStr;
690 return OUString();
693 const SbxObject* SbiImage::FindType (const OUString& aTypeName) const
695 return rTypes.is() ? static_cast<SbxObject*>(rTypes->Find(aTypeName,SbxClassType::Object)) : nullptr;
698 sal_uInt16 SbiImage::CalcLegacyOffset( sal_Int32 nOffset )
700 return SbiCodeGen::calcLegacyOffSet(aCode.data(), nOffset);
703 sal_uInt32 SbiImage::CalcNewOffset( sal_Int16 nOffset )
705 return SbiCodeGen::calcNewOffSet(aLegacyPCode.data(), nOffset);
708 void SbiImage::ReleaseLegacyBuffer()
710 aLegacyPCode.clear();
713 bool SbiImage::ExceedsLegacyLimits()
715 return (nStringSize > 0xFF00) || (CalcLegacyOffset(aCode.size()) > 0xFF00);
718 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */