File: | home/maarten/src/libreoffice/core/basic/source/sbx/sbxexec.cxx |
Warning: | line 378, column 5 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 <basic/sbx.hxx> | |||
21 | #include <basic/sberrors.hxx> | |||
22 | #include <rtl/character.hxx> | |||
23 | #include <rtl/ustrbuf.hxx> | |||
24 | ||||
25 | ||||
26 | static SbxVariableRef Element | |||
27 | ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, | |||
28 | SbxClassType ); | |||
29 | ||||
30 | static const sal_Unicode* SkipWhitespace( const sal_Unicode* p ) | |||
31 | { | |||
32 | while( *p && ( *p == ' ' || *p == '\t' ) ) | |||
33 | p++; | |||
34 | return p; | |||
35 | } | |||
36 | ||||
37 | // Scanning of a symbol. The symbol were inserted in rSym, the return value | |||
38 | // is the new scan position. The symbol is at errors empty. | |||
39 | ||||
40 | static const sal_Unicode* Symbol( const sal_Unicode* p, OUString& rSym ) | |||
41 | { | |||
42 | sal_uInt16 nLen = 0; | |||
43 | // Did we have a nonstandard symbol? | |||
44 | if( *p == '[' ) | |||
45 | { | |||
46 | rSym = ++p; | |||
47 | while( *p && *p != ']' ) | |||
48 | { | |||
49 | p++; | |||
50 | nLen++; | |||
51 | } | |||
52 | p++; | |||
53 | } | |||
54 | else | |||
55 | { | |||
56 | // A symbol had to begin with an alphabetic character or an underline | |||
57 | if( !rtl::isAsciiAlpha( *p ) && *p != '_' ) | |||
58 | { | |||
59 | SbxBase::SetError( ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) ); | |||
60 | } | |||
61 | else | |||
62 | { | |||
63 | rSym = p; | |||
64 | // The it can contain alphabetic characters, numbers or underlines | |||
65 | while( *p && (rtl::isAsciiAlphanumeric( *p ) || *p == '_') ) | |||
66 | { | |||
67 | p++; | |||
68 | nLen++; | |||
69 | } | |||
70 | // Ignore standard BASIC suffixes | |||
71 | if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) ) | |||
72 | { | |||
73 | p++; | |||
74 | } | |||
75 | } | |||
76 | } | |||
77 | rSym = rSym.copy( 0, nLen ); | |||
78 | return p; | |||
79 | } | |||
80 | ||||
81 | // Qualified name. Element.Element... | |||
82 | ||||
83 | static SbxVariableRef QualifiedName | |||
84 | ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, SbxClassType t ) | |||
85 | { | |||
86 | ||||
87 | SbxVariableRef refVar; | |||
88 | const sal_Unicode* p = SkipWhitespace( *ppBuf ); | |||
89 | if( rtl::isAsciiAlpha( *p ) || *p == '_' || *p == '[' ) | |||
90 | { | |||
91 | // Read in the element | |||
92 | refVar = Element( pObj, pGbl, &p, t ); | |||
93 | while( refVar.is() && (*p == '.' || *p == '!') ) | |||
94 | { | |||
95 | // It follows still an objectelement. The current element | |||
96 | // had to be a SBX-Object or had to deliver such an object! | |||
97 | pObj = dynamic_cast<SbxObject*>( refVar.get() ); | |||
98 | if( !pObj ) | |||
99 | // Then it had to deliver an object | |||
100 | pObj = dynamic_cast<SbxObject*>( refVar->GetObject() ); | |||
101 | refVar.clear(); | |||
102 | if( !pObj ) | |||
103 | break; | |||
104 | p++; | |||
105 | // And the next element please | |||
106 | refVar = Element( pObj, pGbl, &p, t ); | |||
107 | } | |||
108 | } | |||
109 | else | |||
110 | SbxBase::SetError( ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) ); | |||
111 | *ppBuf = p; | |||
112 | return refVar; | |||
113 | } | |||
114 | ||||
115 | // Read in of an operand. This could be a number, a string or | |||
116 | // a function (with optional parameters). | |||
117 | ||||
118 | static SbxVariableRef Operand | |||
119 | ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, bool bVar ) | |||
120 | { | |||
121 | SbxVariableRef refVar( new SbxVariable ); | |||
122 | const sal_Unicode* p = SkipWhitespace( *ppBuf ); | |||
123 | if( !bVar && ( rtl::isAsciiDigit( *p ) | |||
124 | || ( *p == '.' && rtl::isAsciiDigit( *( p+1 ) ) ) | |||
125 | || *p == '-' | |||
126 | || *p == '&' ) ) | |||
127 | { | |||
128 | // A number could be scanned in directly! | |||
129 | sal_uInt16 nLen; | |||
130 | if( !refVar->Scan( OUString( p ), &nLen ) ) | |||
131 | { | |||
132 | refVar.clear(); | |||
133 | } | |||
134 | else | |||
135 | { | |||
136 | p += nLen; | |||
137 | } | |||
138 | } | |||
139 | else if( !bVar && *p == '"' ) | |||
140 | { | |||
141 | // A string | |||
142 | OUStringBuffer aString; | |||
143 | p++; | |||
144 | for( ;; ) | |||
145 | { | |||
146 | // This is perhaps an error | |||
147 | if( !*p ) | |||
148 | { | |||
149 | return nullptr; | |||
150 | } | |||
151 | // Double quotes are OK | |||
152 | if( *p == '"' && (*++p) != '"' ) | |||
153 | { | |||
154 | break; | |||
155 | } | |||
156 | aString.append(*p++); | |||
157 | } | |||
158 | refVar->PutString( aString.makeStringAndClear() ); | |||
159 | } | |||
160 | else | |||
161 | { | |||
162 | refVar = QualifiedName( pObj, pGbl, &p, SbxClassType::DontCare ); | |||
163 | } | |||
164 | *ppBuf = p; | |||
165 | return refVar; | |||
166 | } | |||
167 | ||||
168 | // Read in of a simple term. The operands +, -, * and / | |||
169 | // are supported. | |||
170 | ||||
171 | static SbxVariableRef MulDiv( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf ) | |||
172 | { | |||
173 | const sal_Unicode* p = *ppBuf; | |||
174 | SbxVariableRef refVar( Operand( pObj, pGbl, &p, false ) ); | |||
175 | p = SkipWhitespace( p ); | |||
176 | while( refVar.is() && ( *p == '*' || *p == '/' ) ) | |||
177 | { | |||
178 | sal_Unicode cOp = *p++; | |||
179 | SbxVariableRef refVar2( Operand( pObj, pGbl, &p, false ) ); | |||
180 | if( refVar2.is() ) | |||
181 | { | |||
182 | // temporary variable! | |||
183 | SbxVariable* pVar = refVar.get(); | |||
184 | pVar = new SbxVariable( *pVar ); | |||
185 | refVar = pVar; | |||
186 | if( cOp == '*' ) | |||
187 | *refVar *= *refVar2; | |||
188 | else | |||
189 | *refVar /= *refVar2; | |||
190 | } | |||
191 | else | |||
192 | { | |||
193 | refVar.clear(); | |||
194 | break; | |||
195 | } | |||
196 | } | |||
197 | *ppBuf = p; | |||
198 | return refVar; | |||
199 | } | |||
200 | ||||
201 | static SbxVariableRef PlusMinus( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf ) | |||
202 | { | |||
203 | const sal_Unicode* p = *ppBuf; | |||
204 | SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) ); | |||
205 | p = SkipWhitespace( p ); | |||
206 | while( refVar.is() && ( *p == '+' || *p == '-' ) ) | |||
207 | { | |||
208 | sal_Unicode cOp = *p++; | |||
209 | SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) ); | |||
210 | if( refVar2.is() ) | |||
211 | { | |||
212 | // temporary Variable! | |||
213 | SbxVariable* pVar = refVar.get(); | |||
214 | pVar = new SbxVariable( *pVar ); | |||
215 | refVar = pVar; | |||
216 | if( cOp == '+' ) | |||
217 | *refVar += *refVar2; | |||
218 | else | |||
219 | *refVar -= *refVar2; | |||
220 | } | |||
221 | else | |||
222 | { | |||
223 | refVar.clear(); | |||
224 | break; | |||
225 | } | |||
226 | } | |||
227 | *ppBuf = p; | |||
228 | return refVar; | |||
229 | } | |||
230 | ||||
231 | static SbxVariableRef Assign( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf ) | |||
232 | { | |||
233 | const sal_Unicode* p = *ppBuf; | |||
234 | SbxVariableRef refVar( Operand( pObj, pGbl, &p, true ) ); | |||
235 | p = SkipWhitespace( p ); | |||
236 | if( refVar.is() ) | |||
237 | { | |||
238 | if( *p == '=' ) | |||
239 | { | |||
240 | // Assign only onto properties! | |||
241 | if( refVar->GetClass() != SbxClassType::Property ) | |||
242 | { | |||
243 | SbxBase::SetError( ERRCODE_BASIC_BAD_ACTIONErrCode( ErrCodeArea::Sbx, ErrCodeClass::NotSupported, 23) ); | |||
244 | refVar.clear(); | |||
245 | } | |||
246 | else | |||
247 | { | |||
248 | p++; | |||
249 | SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) ); | |||
250 | if( refVar2.is() ) | |||
251 | { | |||
252 | SbxVariable* pVar = refVar.get(); | |||
253 | SbxVariable* pVar2 = refVar2.get(); | |||
254 | *pVar = *pVar2; | |||
255 | pVar->SetParameters( nullptr ); | |||
256 | } | |||
257 | } | |||
258 | } | |||
259 | else | |||
260 | // Simple call: once activating | |||
261 | refVar->Broadcast( SfxHintId::BasicDataWanted ); | |||
262 | } | |||
263 | *ppBuf = p; | |||
264 | return refVar; | |||
265 | } | |||
266 | ||||
267 | // Read in of an element. This is a symbol, optional followed | |||
268 | // by a parameter list. The symbol will be searched in the | |||
269 | // specified object and the parameter list will be attached if necessary. | |||
270 | ||||
271 | static SbxVariableRef Element | |||
272 | ( SbxObject* pObj, SbxObject* pGbl, const sal_Unicode** ppBuf, | |||
273 | SbxClassType t ) | |||
274 | { | |||
275 | OUString aSym; | |||
276 | const sal_Unicode* p = Symbol( *ppBuf, aSym ); | |||
277 | SbxVariableRef refVar; | |||
278 | if( !aSym.isEmpty() ) | |||
279 | { | |||
280 | SbxFlagBits nOld = pObj->GetFlags(); | |||
281 | if( pObj == pGbl ) | |||
282 | { | |||
283 | pObj->SetFlag( SbxFlagBits::GlobalSearch ); | |||
284 | } | |||
285 | refVar = pObj->Find( aSym, t ); | |||
286 | pObj->SetFlags( nOld ); | |||
287 | if( refVar.is() ) | |||
288 | { | |||
289 | refVar->SetParameters( nullptr ); | |||
290 | // Follow still parameter? | |||
291 | p = SkipWhitespace( p ); | |||
292 | if( *p == '(' ) | |||
293 | { | |||
294 | p++; | |||
295 | auto refPar = tools::make_ref<SbxArray>(); | |||
296 | sal_uInt32 nArg = 0; | |||
297 | // We are once relaxed and accept as well | |||
298 | // the line- or command end as delimiter | |||
299 | // Search parameter always global! | |||
300 | while( *p && *p != ')' && *p != ']' ) | |||
301 | { | |||
302 | SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p ); | |||
303 | if( !refArg.is() ) | |||
304 | { | |||
305 | // Error during the parsing | |||
306 | refVar.clear(); break; | |||
307 | } | |||
308 | else | |||
309 | { | |||
310 | // One copies the parameter, so that | |||
311 | // one have the current status (triggers also | |||
312 | // the call per access) | |||
313 | refPar->Put32( new SbxVariable( *refArg ), ++nArg ); | |||
314 | } | |||
315 | p = SkipWhitespace( p ); | |||
316 | if( *p == ',' ) | |||
317 | p++; | |||
318 | } | |||
319 | if( *p == ')' ) | |||
320 | p++; | |||
321 | if( refVar.is() ) | |||
322 | refVar->SetParameters( refPar.get() ); | |||
323 | } | |||
324 | } | |||
325 | else | |||
326 | SbxBase::SetError( ERRCODE_BASIC_NO_METHODErrCode( ErrCodeArea::Sbx, ErrCodeClass::Runtime, 18) ); | |||
327 | } | |||
328 | *ppBuf = p; | |||
329 | return refVar; | |||
330 | } | |||
331 | ||||
332 | // Mainroutine | |||
333 | ||||
334 | SbxVariable* SbxObject::Execute( const OUString& rTxt ) | |||
335 | { | |||
336 | SbxVariableRef pVar; | |||
337 | const sal_Unicode* p = rTxt.getStr(); | |||
338 | for( ;; ) | |||
339 | { | |||
340 | p = SkipWhitespace( p ); | |||
341 | if( !*p ) | |||
342 | { | |||
343 | break; | |||
344 | } | |||
345 | if( *p++ != '[' ) | |||
346 | { | |||
347 | SetError( ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) ); break; | |||
348 | } | |||
349 | pVar = Assign( this, this, &p ); | |||
350 | if( !pVar.is() ) | |||
351 | { | |||
352 | break; | |||
353 | } | |||
354 | p = SkipWhitespace( p ); | |||
355 | if( *p++ != ']' ) | |||
356 | { | |||
357 | SetError( ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) ); break; | |||
358 | } | |||
359 | } | |||
360 | return pVar.get(); | |||
361 | } | |||
362 | ||||
363 | SbxVariable* SbxObject::FindQualified( const OUString& rName, SbxClassType t ) | |||
364 | { | |||
365 | SbxVariableRef pVar; | |||
366 | const sal_Unicode* p = rName.getStr(); | |||
367 | p = SkipWhitespace( p ); | |||
368 | if( !*p ) | |||
| ||||
369 | { | |||
370 | return nullptr; | |||
371 | } | |||
372 | pVar = QualifiedName( this, this, &p, t ); | |||
373 | p = SkipWhitespace( p ); | |||
374 | if( *p ) | |||
375 | { | |||
376 | SetError( ERRCODE_BASIC_SYNTAXErrCode( ErrCodeArea::Sbx, ErrCodeClass::Compiler, 1) ); | |||
377 | } | |||
378 | return pVar.get(); | |||
| ||||
379 | } | |||
380 | ||||
381 | /* 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: */ |