File: | home/maarten/src/libreoffice/core/basic/source/sbx/sbxexec.cxx |
Warning: | line 328, column 14 Potential leak of memory pointed to by 'refPar.pObj' |
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
| ||||
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: */ |