File: | home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx |
Warning: | line 560, column 11 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <config_features.h> | ||||||||
21 | |||||||||
22 | #include <tools/stream.hxx> | ||||||||
23 | #include <svl/SfxBroadcaster.hxx> | ||||||||
24 | |||||||||
25 | #include <basic/sbx.hxx> | ||||||||
26 | #include <runtime.hxx> | ||||||||
27 | #include "sbxres.hxx" | ||||||||
28 | #include "sbxconv.hxx" | ||||||||
29 | #include <sbunoobj.hxx> | ||||||||
30 | #include <rtl/character.hxx> | ||||||||
31 | #include <sal/log.hxx> | ||||||||
32 | |||||||||
33 | #include <com/sun/star/uno/XInterface.hpp> | ||||||||
34 | using namespace com::sun::star::uno; | ||||||||
35 | |||||||||
36 | // SbxVariable | ||||||||
37 | |||||||||
38 | |||||||||
39 | // SbxVariableImpl | ||||||||
40 | |||||||||
41 | class SbxVariableImpl | ||||||||
42 | { | ||||||||
43 | friend class SbxVariable; | ||||||||
44 | OUString m_aDeclareClassName; | ||||||||
45 | Reference< XInterface > m_xComListener; | ||||||||
46 | StarBASIC* m_pComListenerParentBasic; | ||||||||
47 | |||||||||
48 | SbxVariableImpl() | ||||||||
49 | : m_pComListenerParentBasic( nullptr ) | ||||||||
50 | {} | ||||||||
51 | }; | ||||||||
52 | |||||||||
53 | |||||||||
54 | // Constructors | ||||||||
55 | |||||||||
56 | SbxVariable::SbxVariable() : SbxValue() | ||||||||
57 | { | ||||||||
58 | pParent = nullptr; | ||||||||
59 | nUserData = 0; | ||||||||
60 | nHash = 0; | ||||||||
61 | } | ||||||||
62 | |||||||||
63 | SbxVariable::SbxVariable( const SbxVariable& r ) | ||||||||
64 | : SvRefBase( r ), | ||||||||
65 | SbxValue( r ), | ||||||||
66 | mpPar( r.mpPar ), | ||||||||
67 | pInfo( r.pInfo ) | ||||||||
68 | { | ||||||||
69 | if( r.mpImpl != nullptr ) | ||||||||
70 | { | ||||||||
71 | mpImpl.reset( new SbxVariableImpl( *r.mpImpl ) ); | ||||||||
72 | #if HAVE_FEATURE_SCRIPTING1 | ||||||||
73 | if( mpImpl->m_xComListener.is() ) | ||||||||
74 | { | ||||||||
75 | registerComListenerVariableForBasic( this, mpImpl->m_pComListenerParentBasic ); | ||||||||
76 | } | ||||||||
77 | #endif | ||||||||
78 | } | ||||||||
79 | if( r.CanRead() ) | ||||||||
80 | { | ||||||||
81 | pParent = r.pParent; | ||||||||
82 | nUserData = r.nUserData; | ||||||||
83 | maName = r.maName; | ||||||||
84 | nHash = r.nHash; | ||||||||
85 | } | ||||||||
86 | else | ||||||||
87 | { | ||||||||
88 | pParent = nullptr; | ||||||||
89 | nUserData = 0; | ||||||||
90 | nHash = 0; | ||||||||
91 | } | ||||||||
92 | } | ||||||||
93 | |||||||||
94 | SbxEnsureParentVariable::SbxEnsureParentVariable(const SbxVariable& r) | ||||||||
95 | : SbxVariable(r) | ||||||||
96 | , xParent(const_cast<SbxVariable&>(r).GetParent()) | ||||||||
97 | { | ||||||||
98 | assert(GetParent() == xParent.get())(static_cast <bool> (GetParent() == xParent.get()) ? void (0) : __assert_fail ("GetParent() == xParent.get()", "/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" , 98, __extension__ __PRETTY_FUNCTION__)); | ||||||||
99 | } | ||||||||
100 | |||||||||
101 | void SbxEnsureParentVariable::SetParent(SbxObject* p) | ||||||||
102 | { | ||||||||
103 | assert(GetParent() == xParent.get())(static_cast <bool> (GetParent() == xParent.get()) ? void (0) : __assert_fail ("GetParent() == xParent.get()", "/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" , 103, __extension__ __PRETTY_FUNCTION__)); | ||||||||
104 | SbxVariable::SetParent(p); | ||||||||
105 | xParent = SbxObjectRef(p); | ||||||||
106 | assert(GetParent() == xParent.get())(static_cast <bool> (GetParent() == xParent.get()) ? void (0) : __assert_fail ("GetParent() == xParent.get()", "/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" , 106, __extension__ __PRETTY_FUNCTION__)); | ||||||||
107 | } | ||||||||
108 | |||||||||
109 | SbxVariable::SbxVariable( SbxDataType t ) : SbxValue( t ) | ||||||||
110 | { | ||||||||
111 | pParent = nullptr; | ||||||||
112 | nUserData = 0; | ||||||||
113 | nHash = 0; | ||||||||
114 | } | ||||||||
115 | |||||||||
116 | SbxVariable::~SbxVariable() | ||||||||
117 | { | ||||||||
118 | #if HAVE_FEATURE_SCRIPTING1 | ||||||||
119 | if( IsSet( SbxFlagBits::DimAsNew )) | ||||||||
120 | { | ||||||||
121 | removeDimAsNewRecoverItem( this ); | ||||||||
122 | } | ||||||||
123 | #endif | ||||||||
124 | mpBroadcaster.reset(); | ||||||||
125 | } | ||||||||
126 | |||||||||
127 | // Broadcasting | ||||||||
128 | |||||||||
129 | SfxBroadcaster& SbxVariable::GetBroadcaster() | ||||||||
130 | { | ||||||||
131 | if( !mpBroadcaster ) | ||||||||
132 | { | ||||||||
133 | mpBroadcaster.reset( new SfxBroadcaster ); | ||||||||
134 | } | ||||||||
135 | return *mpBroadcaster; | ||||||||
136 | } | ||||||||
137 | |||||||||
138 | SbxArray* SbxVariable::GetParameters() const | ||||||||
139 | { | ||||||||
140 | return mpPar.get(); | ||||||||
141 | } | ||||||||
142 | |||||||||
143 | |||||||||
144 | // Perhaps some day one could cut the parameter 0. | ||||||||
145 | // Then the copying will be dropped... | ||||||||
146 | |||||||||
147 | void SbxVariable::Broadcast( SfxHintId nHintId ) | ||||||||
148 | { | ||||||||
149 | if( !mpBroadcaster || IsSet( SbxFlagBits::NoBroadcast ) ) | ||||||||
150 | return; | ||||||||
151 | |||||||||
152 | // Because the method could be called from outside, check the | ||||||||
153 | // rights here again | ||||||||
154 | if( nHintId
| ||||||||
155 | { | ||||||||
156 | if( !CanRead() ) | ||||||||
157 | { | ||||||||
158 | return; | ||||||||
159 | } | ||||||||
160 | } | ||||||||
161 | if( nHintId
| ||||||||
162 | { | ||||||||
163 | if( !CanWrite() ) | ||||||||
164 | { | ||||||||
165 | return; | ||||||||
166 | } | ||||||||
167 | } | ||||||||
168 | |||||||||
169 | //fdo#86843 Add a ref during the following block to guard against | ||||||||
170 | //getting deleted before completing this method | ||||||||
171 | SbxVariableRef aBroadcastGuard(this); | ||||||||
172 | |||||||||
173 | // Avoid further broadcasting | ||||||||
174 | std::unique_ptr<SfxBroadcaster> pSave = std::move(mpBroadcaster); | ||||||||
175 | SbxFlagBits nSaveFlags = GetFlags(); | ||||||||
176 | SetFlag( SbxFlagBits::ReadWrite ); | ||||||||
177 | if( mpPar.is() ) | ||||||||
178 | { | ||||||||
179 | // Register this as element 0, but don't change over the parent! | ||||||||
180 | mpPar->GetRef32( 0 ) = this; | ||||||||
181 | } | ||||||||
182 | pSave->Broadcast( SbxHint( nHintId, this ) ); | ||||||||
183 | mpBroadcaster = std::move(pSave); | ||||||||
184 | SetFlags( nSaveFlags ); | ||||||||
185 | } | ||||||||
186 | |||||||||
187 | SbxInfo* SbxVariable::GetInfo() | ||||||||
188 | { | ||||||||
189 | if( !pInfo.is() ) | ||||||||
190 | { | ||||||||
191 | Broadcast( SfxHintId::BasicInfoWanted ); | ||||||||
192 | if( pInfo.is() ) | ||||||||
193 | { | ||||||||
194 | SetModified( true ); | ||||||||
195 | } | ||||||||
196 | } | ||||||||
197 | return pInfo.get(); | ||||||||
198 | } | ||||||||
199 | |||||||||
200 | void SbxVariable::SetInfo( SbxInfo* p ) | ||||||||
201 | { | ||||||||
202 | pInfo = p; | ||||||||
203 | } | ||||||||
204 | |||||||||
205 | void SbxVariable::SetParameters( SbxArray* p ) | ||||||||
206 | { | ||||||||
207 | mpPar = p; | ||||||||
208 | } | ||||||||
209 | |||||||||
210 | |||||||||
211 | // Name of the variables | ||||||||
212 | |||||||||
213 | void SbxVariable::SetName( const OUString& rName ) | ||||||||
214 | { | ||||||||
215 | maName = rName; | ||||||||
216 | nHash = MakeHashCode( rName ); | ||||||||
217 | } | ||||||||
218 | |||||||||
219 | const OUString& SbxVariable::GetName( SbxNameType t ) const | ||||||||
220 | { | ||||||||
221 | static const char cSuffixes[] = " %&!#@ $"; | ||||||||
222 | if( t == SbxNameType::NONE ) | ||||||||
223 | { | ||||||||
224 | return maName; | ||||||||
225 | } | ||||||||
226 | // Request parameter-information (not for objects) | ||||||||
227 | const_cast<SbxVariable*>(this)->GetInfo(); | ||||||||
228 | // Append nothing, if it is a simple property (no empty brackets) | ||||||||
229 | if (!pInfo.is() || (pInfo->m_Params.empty() && GetClass() == SbxClassType::Property)) | ||||||||
230 | { | ||||||||
231 | return maName; | ||||||||
232 | } | ||||||||
233 | sal_Unicode cType = ' '; | ||||||||
234 | OUStringBuffer aTmp( maName ); | ||||||||
235 | // short type? Then fetch it, possible this is 0. | ||||||||
236 | SbxDataType et = GetType(); | ||||||||
237 | if( t == SbxNameType::ShortTypes ) | ||||||||
238 | { | ||||||||
239 | if( et <= SbxSTRING ) | ||||||||
240 | { | ||||||||
241 | cType = cSuffixes[ et ]; | ||||||||
242 | } | ||||||||
243 | if( cType != ' ' ) | ||||||||
244 | { | ||||||||
245 | aTmp.append(cType); | ||||||||
246 | } | ||||||||
247 | } | ||||||||
248 | aTmp.append("("); | ||||||||
249 | |||||||||
250 | for (SbxParams::const_iterator iter = pInfo->m_Params.begin(); iter != pInfo->m_Params.end(); ++iter) | ||||||||
251 | { | ||||||||
252 | auto const& i = *iter; | ||||||||
253 | int nt = i->eType & 0x0FFF; | ||||||||
254 | if (iter != pInfo->m_Params.begin()) | ||||||||
255 | { | ||||||||
256 | aTmp.append(","); | ||||||||
257 | } | ||||||||
258 | if( i->nFlags & SbxFlagBits::Optional ) | ||||||||
259 | { | ||||||||
260 | aTmp.append( GetSbxRes( StringId::Optional ) ); | ||||||||
261 | } | ||||||||
262 | if( i->eType & SbxBYREF ) | ||||||||
263 | { | ||||||||
264 | aTmp.append( GetSbxRes( StringId::ByRef ) ); | ||||||||
265 | } | ||||||||
266 | aTmp.append( i->aName ); | ||||||||
267 | cType = ' '; | ||||||||
268 | // short type? Then fetch it, possible this is 0. | ||||||||
269 | if( t == SbxNameType::ShortTypes ) | ||||||||
270 | { | ||||||||
271 | if( nt <= SbxSTRING ) | ||||||||
272 | { | ||||||||
273 | cType = cSuffixes[ nt ]; | ||||||||
274 | } | ||||||||
275 | } | ||||||||
276 | if( cType != ' ' ) | ||||||||
277 | { | ||||||||
278 | aTmp.append(cType); | ||||||||
279 | if( i->eType & SbxARRAY ) | ||||||||
280 | { | ||||||||
281 | aTmp.append("()"); | ||||||||
282 | } | ||||||||
283 | } | ||||||||
284 | else | ||||||||
285 | { | ||||||||
286 | if( i->eType & SbxARRAY ) | ||||||||
287 | { | ||||||||
288 | aTmp.append("()"); | ||||||||
289 | } | ||||||||
290 | // long type? | ||||||||
291 | aTmp.append(GetSbxRes( StringId::As )); | ||||||||
292 | if( nt < 32 ) | ||||||||
293 | { | ||||||||
294 | aTmp.append(GetSbxRes( static_cast<StringId>( static_cast<int>( StringId::Types ) + nt ) )); | ||||||||
295 | } | ||||||||
296 | else | ||||||||
297 | { | ||||||||
298 | aTmp.append(GetSbxRes( StringId::Any )); | ||||||||
299 | } | ||||||||
300 | } | ||||||||
301 | } | ||||||||
302 | aTmp.append(")"); | ||||||||
303 | const_cast<SbxVariable*>(this)->aToolString = aTmp.makeStringAndClear(); | ||||||||
304 | return aToolString; | ||||||||
305 | } | ||||||||
306 | |||||||||
307 | // Create a simple hashcode: the first six characters are evaluated. | ||||||||
308 | |||||||||
309 | sal_uInt16 SbxVariable::MakeHashCode( const OUString& rName ) | ||||||||
310 | { | ||||||||
311 | sal_uInt16 n = 0; | ||||||||
312 | sal_Int32 nLen = rName.getLength(); | ||||||||
313 | if( nLen > 6 ) | ||||||||
314 | { | ||||||||
315 | nLen = 6; | ||||||||
316 | } | ||||||||
317 | for( sal_Int32 i=0; i<nLen; ++i ) | ||||||||
318 | { | ||||||||
319 | sal_uInt8 c = static_cast<sal_uInt8>(rName[i]); | ||||||||
320 | // If we have a comment sign break!! | ||||||||
321 | if( c >= 0x80 ) | ||||||||
322 | { | ||||||||
323 | return 0; | ||||||||
324 | } | ||||||||
325 | n = sal::static_int_cast< sal_uInt16 >( ( n << 3 ) + rtl::toAsciiUpperCase( c ) ); | ||||||||
326 | } | ||||||||
327 | return n; | ||||||||
328 | } | ||||||||
329 | |||||||||
330 | // Operators | ||||||||
331 | |||||||||
332 | SbxVariable& SbxVariable::operator=( const SbxVariable& r ) | ||||||||
333 | { | ||||||||
334 | if (this != &r) | ||||||||
335 | { | ||||||||
336 | SbxValue::operator=( r ); | ||||||||
337 | mpImpl.reset(); | ||||||||
338 | if( r.mpImpl != nullptr ) | ||||||||
339 | { | ||||||||
340 | mpImpl.reset( new SbxVariableImpl( *r.mpImpl ) ); | ||||||||
341 | #if HAVE_FEATURE_SCRIPTING1 | ||||||||
342 | if( mpImpl->m_xComListener.is() ) | ||||||||
343 | { | ||||||||
344 | registerComListenerVariableForBasic( this, mpImpl->m_pComListenerParentBasic ); | ||||||||
345 | } | ||||||||
346 | #endif | ||||||||
347 | } | ||||||||
348 | } | ||||||||
349 | return *this; | ||||||||
350 | } | ||||||||
351 | |||||||||
352 | // Conversion | ||||||||
353 | |||||||||
354 | SbxDataType SbxVariable::GetType() const | ||||||||
355 | { | ||||||||
356 | if( aData.eType == SbxOBJECT ) | ||||||||
357 | { | ||||||||
358 | return aData.pObj ? aData.pObj->GetType() : SbxOBJECT; | ||||||||
359 | } | ||||||||
360 | else if( aData.eType == SbxVARIANT ) | ||||||||
361 | { | ||||||||
362 | return aData.pObj ? aData.pObj->GetType() : SbxVARIANT; | ||||||||
363 | } | ||||||||
364 | else | ||||||||
365 | { | ||||||||
366 | return aData.eType; | ||||||||
367 | } | ||||||||
368 | } | ||||||||
369 | |||||||||
370 | SbxClassType SbxVariable::GetClass() const | ||||||||
371 | { | ||||||||
372 | return SbxClassType::Variable; | ||||||||
373 | } | ||||||||
374 | |||||||||
375 | void SbxVariable::SetModified( bool b ) | ||||||||
376 | { | ||||||||
377 | if( IsSet( SbxFlagBits::NoModify ) ) | ||||||||
378 | { | ||||||||
379 | return; | ||||||||
380 | } | ||||||||
381 | SbxBase::SetModified( b ); | ||||||||
382 | if( pParent && pParent != this ) //??? HotFix: Recursion out here MM | ||||||||
383 | { | ||||||||
384 | pParent->SetModified( b ); | ||||||||
385 | } | ||||||||
386 | } | ||||||||
387 | |||||||||
388 | void SbxVariable::SetParent( SbxObject* p ) | ||||||||
389 | { | ||||||||
390 | #ifdef DBG_UTIL | ||||||||
391 | // Will the parent of a SbxObject be set? | ||||||||
392 | if (p && dynamic_cast<SbxObject*>(this)) | ||||||||
393 | { | ||||||||
394 | // then this had to be a child of the new parent | ||||||||
395 | bool bFound = false; | ||||||||
396 | SbxArray *pChildren = p->GetObjects(); | ||||||||
397 | if ( pChildren ) | ||||||||
398 | { | ||||||||
399 | for ( sal_uInt32 nIdx = 0; !bFound && nIdx < pChildren->Count32(); ++nIdx ) | ||||||||
400 | { | ||||||||
401 | bFound = ( this == pChildren->Get32(nIdx) ); | ||||||||
402 | } | ||||||||
403 | } | ||||||||
404 | SAL_INFO_IF(do { if (true && (!bFound)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "basic.sbx")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName () << "])") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||||
405 | !bFound, "basic.sbx",do { if (true && (!bFound)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "basic.sbx")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName () << "])") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||||
406 | "dangling: [" << GetName() << "].SetParent([" << p->GetName()do { if (true && (!bFound)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "basic.sbx")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName () << "])") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false) | ||||||||
407 | << "])")do { if (true && (!bFound)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_INFO, "basic.sbx")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName () << "])") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "dangling: [" << GetName() << "].SetParent([" << p->GetName() << "])"; ::sal::detail::log( ( ::SAL_DETAIL_LOG_LEVEL_INFO), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "407" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||||
408 | } | ||||||||
409 | #endif | ||||||||
410 | |||||||||
411 | pParent = p; | ||||||||
412 | } | ||||||||
413 | |||||||||
414 | SbxVariableImpl* SbxVariable::getImpl() | ||||||||
415 | { | ||||||||
416 | if(!mpImpl) | ||||||||
417 | { | ||||||||
418 | mpImpl.reset(new SbxVariableImpl); | ||||||||
419 | } | ||||||||
420 | return mpImpl.get(); | ||||||||
421 | } | ||||||||
422 | |||||||||
423 | const OUString& SbxVariable::GetDeclareClassName() | ||||||||
424 | { | ||||||||
425 | SbxVariableImpl* pImpl = getImpl(); | ||||||||
426 | return pImpl->m_aDeclareClassName; | ||||||||
427 | } | ||||||||
428 | |||||||||
429 | void SbxVariable::SetDeclareClassName( const OUString& rDeclareClassName ) | ||||||||
430 | { | ||||||||
431 | SbxVariableImpl* pImpl = getImpl(); | ||||||||
432 | pImpl->m_aDeclareClassName = rDeclareClassName; | ||||||||
433 | } | ||||||||
434 | |||||||||
435 | void SbxVariable::SetComListener( const css::uno::Reference< css::uno::XInterface >& xComListener, | ||||||||
436 | StarBASIC* pParentBasic ) | ||||||||
437 | { | ||||||||
438 | SbxVariableImpl* pImpl = getImpl(); | ||||||||
439 | pImpl->m_xComListener = xComListener; | ||||||||
440 | pImpl->m_pComListenerParentBasic = pParentBasic; | ||||||||
441 | #if HAVE_FEATURE_SCRIPTING1 | ||||||||
442 | registerComListenerVariableForBasic( this, pParentBasic ); | ||||||||
443 | #endif | ||||||||
444 | } | ||||||||
445 | |||||||||
446 | void SbxVariable::ClearComListener() | ||||||||
447 | { | ||||||||
448 | SbxVariableImpl* pImpl = getImpl(); | ||||||||
449 | pImpl->m_xComListener.clear(); | ||||||||
450 | } | ||||||||
451 | |||||||||
452 | |||||||||
453 | // Loading/Saving | ||||||||
454 | |||||||||
455 | bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer ) | ||||||||
456 | { | ||||||||
457 | sal_uInt8 cMark; | ||||||||
458 | rStrm.ReadUChar( cMark ); | ||||||||
459 | if( cMark == 0xFF ) | ||||||||
| |||||||||
460 | { | ||||||||
461 | if( !SbxValue::LoadData( rStrm, nVer ) ) | ||||||||
462 | { | ||||||||
463 | return false; | ||||||||
464 | } | ||||||||
465 | maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, | ||||||||
466 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
467 | sal_uInt32 nTemp; | ||||||||
468 | rStrm.ReadUInt32( nTemp ); | ||||||||
469 | nUserData = nTemp; | ||||||||
470 | } | ||||||||
471 | else | ||||||||
472 | { | ||||||||
473 | sal_uInt16 nType; | ||||||||
474 | rStrm.SeekRel( -1 ); | ||||||||
475 | rStrm.ReadUInt16( nType ); | ||||||||
476 | maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, | ||||||||
477 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
478 | sal_uInt32 nTemp; | ||||||||
479 | rStrm.ReadUInt32( nTemp ); | ||||||||
480 | nUserData = nTemp; | ||||||||
481 | // correction: old methods have instead of SbxNULL now SbxEMPTY | ||||||||
482 | if( nType == SbxNULL && GetClass() == SbxClassType::Method ) | ||||||||
483 | { | ||||||||
484 | nType = SbxEMPTY; | ||||||||
485 | } | ||||||||
486 | SbxValues aTmp; | ||||||||
487 | OUString aTmpString; | ||||||||
488 | OUString aVal; | ||||||||
489 | aTmp.eType = aData.eType = static_cast<SbxDataType>(nType); | ||||||||
490 | aTmp.pOUString = &aVal; | ||||||||
491 | switch( nType ) | ||||||||
492 | { | ||||||||
493 | case SbxBOOL: | ||||||||
494 | case SbxERROR: | ||||||||
495 | case SbxINTEGER: | ||||||||
496 | rStrm.ReadInt16( aTmp.nInteger ); break; | ||||||||
497 | case SbxLONG: | ||||||||
498 | rStrm.ReadInt32( aTmp.nLong ); break; | ||||||||
499 | case SbxSINGLE: | ||||||||
500 | { | ||||||||
501 | // Floats as ASCII | ||||||||
502 | aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString( | ||||||||
503 | rStrm, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
504 | double d; | ||||||||
505 | SbxDataType t; | ||||||||
506 | if( ImpScan( aTmpString, d, t, nullptr, true ) != ERRCODE_NONEErrCode(0) || t == SbxDOUBLE ) | ||||||||
507 | { | ||||||||
508 | aTmp.nSingle = 0; | ||||||||
509 | return false; | ||||||||
510 | } | ||||||||
511 | aTmp.nSingle = static_cast<float>(d); | ||||||||
512 | break; | ||||||||
513 | } | ||||||||
514 | case SbxDATE: | ||||||||
515 | case SbxDOUBLE: | ||||||||
516 | { | ||||||||
517 | // Floats as ASCII | ||||||||
518 | aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, | ||||||||
519 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
520 | SbxDataType t; | ||||||||
521 | if( ImpScan( aTmpString, aTmp.nDouble, t, nullptr, true ) != ERRCODE_NONEErrCode(0) ) | ||||||||
522 | { | ||||||||
523 | aTmp.nDouble = 0; | ||||||||
524 | return false; | ||||||||
525 | } | ||||||||
526 | break; | ||||||||
527 | } | ||||||||
528 | case SbxSTRING: | ||||||||
529 | aVal = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, | ||||||||
530 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
531 | break; | ||||||||
532 | case SbxEMPTY: | ||||||||
533 | case SbxNULL: | ||||||||
534 | break; | ||||||||
535 | default: | ||||||||
536 | aData.eType = SbxNULL; | ||||||||
537 | SAL_WARN( "basic.sbx", "Loaded a non-supported data type" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "basic.sbx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Loaded a non-supported data type" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic.sbx" ), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "537" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Loaded a non-supported data type"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Loaded a non-supported data type"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "537" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Loaded a non-supported data type") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "537" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Loaded a non-supported data type"), 0 ); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "Loaded a non-supported data type"; ::sal::detail:: log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic.sbx"), ("/home/maarten/src/libreoffice/core/basic/source/sbx/sbxvar.cxx" ":" "537" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||||
538 | return false; | ||||||||
539 | } | ||||||||
540 | // putt value | ||||||||
541 | if( nType
| ||||||||
542 | { | ||||||||
543 | return false; | ||||||||
544 | } | ||||||||
545 | } | ||||||||
546 | rStrm.ReadUChar( cMark ); | ||||||||
547 | // cMark is also a version number! | ||||||||
548 | // 1: initial version | ||||||||
549 | // 2: with nUserData | ||||||||
550 | if( cMark ) | ||||||||
551 | { | ||||||||
552 | if( cMark > 2 ) | ||||||||
553 | { | ||||||||
554 | return false; | ||||||||
555 | } | ||||||||
556 | pInfo = new SbxInfo; | ||||||||
557 | pInfo->LoadData( rStrm, static_cast<sal_uInt16>(cMark) ); | ||||||||
558 | } | ||||||||
559 | Broadcast( SfxHintId::BasicDataChanged ); | ||||||||
560 | nHash = MakeHashCode( maName ); | ||||||||
| |||||||||
561 | SetModified( true ); | ||||||||
562 | return true; | ||||||||
563 | } | ||||||||
564 | |||||||||
565 | bool SbxVariable::StoreData( SvStream& rStrm ) const | ||||||||
566 | { | ||||||||
567 | rStrm.WriteUChar( 0xFF ); // Marker | ||||||||
568 | bool bValStore; | ||||||||
569 | if( dynamic_cast<const SbxMethod *>(this) != nullptr ) | ||||||||
570 | { | ||||||||
571 | // #50200 Avoid that objects , which during the runtime | ||||||||
572 | // as return-value are saved in the method as a value were saved | ||||||||
573 | SbxVariable* pThis = const_cast<SbxVariable*>(this); | ||||||||
574 | SbxFlagBits nSaveFlags = GetFlags(); | ||||||||
575 | pThis->SetFlag( SbxFlagBits::Write ); | ||||||||
576 | pThis->SbxValue::Clear(); | ||||||||
577 | pThis->SetFlags( nSaveFlags ); | ||||||||
578 | |||||||||
579 | // So that the method will not be executed in any case! | ||||||||
580 | // CAST, to avoid const! | ||||||||
581 | pThis->SetFlag( SbxFlagBits::NoBroadcast ); | ||||||||
582 | bValStore = SbxValue::StoreData( rStrm ); | ||||||||
583 | pThis->ResetFlag( SbxFlagBits::NoBroadcast ); | ||||||||
584 | } | ||||||||
585 | else | ||||||||
586 | { | ||||||||
587 | bValStore = SbxValue::StoreData( rStrm ); | ||||||||
588 | } | ||||||||
589 | if( !bValStore ) | ||||||||
590 | { | ||||||||
591 | return false; | ||||||||
592 | } | ||||||||
593 | write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, maName, | ||||||||
594 | RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))); | ||||||||
595 | rStrm.WriteUInt32( nUserData ); | ||||||||
596 | if( pInfo.is() ) | ||||||||
597 | { | ||||||||
598 | rStrm.WriteUChar( 2 ); // Version 2: with UserData! | ||||||||
599 | pInfo->StoreData( rStrm ); | ||||||||
600 | } | ||||||||
601 | else | ||||||||
602 | { | ||||||||
603 | rStrm.WriteUChar( 0 ); | ||||||||
604 | } | ||||||||
605 | return true; | ||||||||
606 | } | ||||||||
607 | |||||||||
608 | // SbxInfo | ||||||||
609 | |||||||||
610 | SbxInfo::SbxInfo() | ||||||||
611 | : aHelpFile(), nHelpId(0) | ||||||||
612 | {} | ||||||||
613 | |||||||||
614 | SbxInfo::SbxInfo( const OUString& r, sal_uInt32 n ) | ||||||||
615 | : aHelpFile( r ), nHelpId( n ) | ||||||||
616 | {} | ||||||||
617 | |||||||||
618 | void SbxVariable::Dump( SvStream& rStrm, bool bFill ) | ||||||||
619 | { | ||||||||
620 | OString aBNameStr(OUStringToOString(GetName( SbxNameType::ShortTypes ), RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)))); | ||||||||
621 | rStrm.WriteCharPtr( "Variable( " ) | ||||||||
622 | .WriteOString( OString::number(reinterpret_cast<sal_Int64>(this)) ).WriteCharPtr( "==" ) | ||||||||
623 | .WriteOString( aBNameStr ); | ||||||||
624 | OString aBParentNameStr(OUStringToOString(GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)))); | ||||||||
625 | if ( GetParent() ) | ||||||||
626 | { | ||||||||
627 | rStrm.WriteCharPtr( " in parent '" ).WriteOString( aBParentNameStr ).WriteCharPtr( "'" ); | ||||||||
628 | } | ||||||||
629 | else | ||||||||
630 | { | ||||||||
631 | rStrm.WriteCharPtr( " no parent" ); | ||||||||
632 | } | ||||||||
633 | rStrm.WriteCharPtr( " ) " ); | ||||||||
634 | |||||||||
635 | // output also the object at object-vars | ||||||||
636 | if ( GetValues_Impl().eType == SbxOBJECT && | ||||||||
637 | GetValues_Impl().pObj && | ||||||||
638 | GetValues_Impl().pObj != this && | ||||||||
639 | GetValues_Impl().pObj != GetParent() ) | ||||||||
640 | { | ||||||||
641 | rStrm.WriteCharPtr( " contains " ); | ||||||||
642 | static_cast<SbxObject*>(GetValues_Impl().pObj)->Dump( rStrm, bFill ); | ||||||||
643 | } | ||||||||
644 | else | ||||||||
645 | { | ||||||||
646 | rStrm << endl; | ||||||||
647 | } | ||||||||
648 | } | ||||||||
649 | |||||||||
650 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |