File: | home/maarten/src/libreoffice/core/include/tools/ref.hxx |
Warning: | line 56, column 30 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 <scitems.hxx> | ||||
21 | #include <svl/intitem.hxx> | ||||
22 | #include <svl/zforlist.hxx> | ||||
23 | #include <float.h> | ||||
24 | |||||
25 | #include <chartarr.hxx> | ||||
26 | #include <cellvalue.hxx> | ||||
27 | #include <document.hxx> | ||||
28 | #include <rechead.hxx> | ||||
29 | #include <globstr.hrc> | ||||
30 | #include <scresid.hxx> | ||||
31 | #include <formulacell.hxx> | ||||
32 | #include <docoptio.hxx> | ||||
33 | |||||
34 | #include <formula/errorcodes.hxx> | ||||
35 | |||||
36 | #include <memory> | ||||
37 | #include <vector> | ||||
38 | |||||
39 | using ::std::vector; | ||||
40 | |||||
41 | ScMemChart::ScMemChart(SCCOL nCols, SCROW nRows) | ||||
42 | { | ||||
43 | nRowCnt = nRows; | ||||
44 | nColCnt = nCols; | ||||
45 | pData.reset( new double[nColCnt * nRowCnt] ); | ||||
46 | |||||
47 | memset( pData.get(), 0.0, nColCnt * nRowCnt ); | ||||
48 | |||||
49 | pColText.reset( new OUString[nColCnt] ); | ||||
50 | pRowText.reset( new OUString[nRowCnt] ); | ||||
51 | } | ||||
52 | |||||
53 | ScMemChart::~ScMemChart() | ||||
54 | { | ||||
55 | } | ||||
56 | |||||
57 | ScChartArray::ScChartArray( | ||||
58 | ScDocument& rDoc, const ScRangeListRef& rRangeList ) : | ||||
59 | rDocument( rDoc ), | ||||
60 | aPositioner(rDoc, rRangeList) {} | ||||
61 | |||||
62 | std::unique_ptr<ScMemChart> ScChartArray::CreateMemChart() | ||||
63 | { | ||||
64 | ScRangeListRef aRangeListRef(GetRangeList()); | ||||
65 | size_t nCount = aRangeListRef->size(); | ||||
66 | if ( nCount > 1 ) | ||||
| |||||
67 | return CreateMemChartMulti(); | ||||
68 | else if ( nCount == 1 ) | ||||
69 | { | ||||
70 | const ScRange & rR = aRangeListRef->front(); | ||||
71 | if ( rR.aStart.Tab() != rR.aEnd.Tab() ) | ||||
72 | return CreateMemChartMulti(); | ||||
73 | else | ||||
74 | return CreateMemChartSingle(); | ||||
75 | } | ||||
76 | else | ||||
77 | return CreateMemChartMulti(); // Can handle 0 range better than Single | ||||
78 | } | ||||
79 | |||||
80 | namespace { | ||||
81 | |||||
82 | double getCellValue( ScDocument& rDoc, const ScAddress& rPos, double fDefault, bool bCalcAsShown ) | ||||
83 | { | ||||
84 | double fRet = fDefault; | ||||
85 | |||||
86 | ScRefCellValue aCell(rDoc, rPos); | ||||
87 | switch (aCell.meType) | ||||
88 | { | ||||
89 | case CELLTYPE_VALUE: | ||||
90 | { | ||||
91 | fRet = aCell.getValue(); | ||||
92 | if (bCalcAsShown && fRet != 0.0) | ||||
93 | { | ||||
94 | sal_uInt32 nFormat = rDoc.GetNumberFormat(rPos); | ||||
95 | fRet = rDoc.RoundValueAsShown(fRet, nFormat); | ||||
96 | } | ||||
97 | } | ||||
98 | break; | ||||
99 | case CELLTYPE_FORMULA: | ||||
100 | { | ||||
101 | ScFormulaCell* pFCell = aCell.mpFormula; | ||||
102 | if (pFCell && pFCell->GetErrCode() == FormulaError::NONE && pFCell->IsValue()) | ||||
103 | fRet = pFCell->GetValue(); | ||||
104 | } | ||||
105 | break; | ||||
106 | default: | ||||
107 | ; | ||||
108 | } | ||||
109 | return fRet; | ||||
110 | } | ||||
111 | |||||
112 | } | ||||
113 | |||||
114 | std::unique_ptr<ScMemChart> ScChartArray::CreateMemChartSingle() | ||||
115 | { | ||||
116 | SCSIZE nCol; | ||||
117 | SCSIZE nRow; | ||||
118 | |||||
119 | // real size (without hidden rows/columns) | ||||
120 | |||||
121 | SCCOL nColAdd = HasRowHeaders() ? 1 : 0; | ||||
122 | SCROW nRowAdd = HasColHeaders() ? 1 : 0; | ||||
123 | |||||
124 | SCCOL nCol1; | ||||
125 | SCROW nRow1; | ||||
126 | SCTAB nTab1; | ||||
127 | SCCOL nCol2; | ||||
128 | SCROW nRow2; | ||||
129 | SCTAB nTab2; | ||||
130 | ScRangeListRef aRangeListRef(GetRangeList()); | ||||
131 | aRangeListRef->front().GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); | ||||
132 | |||||
133 | SCCOL nStrCol = nCol1; // remember for labeling | ||||
134 | SCROW nStrRow = nRow1; | ||||
135 | // Skip hidden columns. | ||||
136 | // TODO: make use of last column value once implemented. | ||||
137 | SCCOL nLastCol = -1; | ||||
138 | while (rDocument.ColHidden(nCol1, nTab1, nullptr, &nLastCol)) | ||||
139 | ++nCol1; | ||||
140 | |||||
141 | // Skip hidden rows. | ||||
142 | SCROW nLastRow = -1; | ||||
143 | if (rDocument.RowHidden(nRow1, nTab1, nullptr, &nLastRow)) | ||||
144 | nRow1 = nLastRow + 1; | ||||
145 | |||||
146 | // if everything is hidden then the label remains at the beginning | ||||
147 | if ( nCol1 <= nCol2 ) | ||||
148 | { | ||||
149 | nStrCol = nCol1; | ||||
150 | nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nColAdd ); | ||||
151 | } | ||||
152 | if ( nRow1 <= nRow2 ) | ||||
153 | { | ||||
154 | nStrRow = nRow1; | ||||
155 | nRow1 = sal::static_int_cast<SCROW>( nRow1 + nRowAdd ); | ||||
156 | } | ||||
157 | |||||
158 | SCSIZE nTotalCols = ( nCol1
| ||||
159 | vector<SCCOL> aCols; | ||||
160 | aCols.reserve(nTotalCols); | ||||
161 | for (SCSIZE i=0; i<nTotalCols; i++) | ||||
162 | { | ||||
163 | SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i); | ||||
164 | if (!rDocument.ColHidden(nThisCol, nTab1, nullptr, &nLastCol)) | ||||
165 | aCols.push_back(nThisCol); | ||||
166 | } | ||||
167 | SCSIZE nColCount = aCols.size(); | ||||
168 | |||||
169 | SCSIZE nTotalRows = ( nRow1
| ||||
170 | vector<SCROW> aRows; | ||||
171 | aRows.reserve(nTotalRows); | ||||
172 | if (nRow1
| ||||
173 | { | ||||
174 | // Get all visible rows between nRow1 and nRow2. | ||||
175 | SCROW nThisRow = nRow1; | ||||
176 | while (nThisRow <= nRow2) | ||||
177 | { | ||||
178 | if (rDocument.RowHidden(nThisRow, nTab1, nullptr, &nLastRow)) | ||||
179 | nThisRow = nLastRow; | ||||
180 | else | ||||
181 | aRows.push_back(nThisRow); | ||||
182 | ++nThisRow; | ||||
183 | } | ||||
184 | } | ||||
185 | SCSIZE nRowCount = aRows.size(); | ||||
186 | |||||
187 | // May happen at least with more than 32k rows. | ||||
188 | if (nColCount > SHRT_MAX32767 || nRowCount > SHRT_MAX32767) | ||||
189 | { | ||||
190 | nColCount = 0; | ||||
191 | nRowCount = 0; | ||||
192 | } | ||||
193 | |||||
194 | bool bValidData = true; | ||||
195 | if ( !nColCount ) | ||||
196 | { | ||||
197 | bValidData = false; | ||||
198 | nColCount = 1; | ||||
199 | aCols.push_back(nStrCol); | ||||
200 | } | ||||
201 | if ( !nRowCount ) | ||||
202 | { | ||||
203 | bValidData = false; | ||||
204 | nRowCount = 1; | ||||
205 | aRows.push_back(nStrRow); | ||||
206 | } | ||||
207 | |||||
208 | // Data | ||||
209 | std::unique_ptr<ScMemChart> pMemChart(new ScMemChart( nColCount, nRowCount )); | ||||
210 | |||||
211 | if ( bValidData
| ||||
212 | { | ||||
213 | bool bCalcAsShown = rDocument.GetDocOptions().IsCalcAsShown(); | ||||
214 | for (nCol=0; nCol
| ||||
215 | { | ||||
216 | for (nRow=0; nRow
| ||||
217 | { | ||||
218 | // DBL_MIN is a Hack for Chart to recognize empty cells. | ||||
219 | ScAddress aPos(aCols[nCol], aRows[nRow], nTab1); | ||||
220 | double nVal = getCellValue(rDocument, aPos, DBL_MIN2.2250738585072014e-308, bCalcAsShown); | ||||
221 | pMemChart->SetData(nCol, nRow, nVal); | ||||
222 | } | ||||
223 | } | ||||
224 | } | ||||
225 | else | ||||
226 | { | ||||
227 | // Flag marking data as invalid? | ||||
228 | for (nCol=0; nCol<nColCount; nCol++) | ||||
229 | for (nRow=0; nRow<nRowCount; nRow++) | ||||
230 | pMemChart->SetData( nCol, nRow, DBL_MIN2.2250738585072014e-308 ); | ||||
231 | } | ||||
232 | |||||
233 | // Column Header | ||||
234 | |||||
235 | for (nCol=0; nCol<nColCount; nCol++) | ||||
236 | { | ||||
237 | OUString aString; | ||||
238 | if (HasColHeaders()) | ||||
239 | aString = rDocument.GetString(aCols[nCol], nStrRow, nTab1); | ||||
240 | if (aString.isEmpty()) | ||||
241 | { | ||||
242 | OUStringBuffer aBuf; | ||||
243 | aBuf.append(ScResId(STR_COLUMNreinterpret_cast<char const *>("STR_COLUMN" "\004" u8"Column" ))); | ||||
244 | aBuf.append(' '); | ||||
245 | |||||
246 | ScAddress aPos( aCols[ nCol ], 0, 0 ); | ||||
247 | aBuf.append(aPos.Format(ScRefFlags::COL_VALID)); | ||||
248 | |||||
249 | aString = aBuf.makeStringAndClear(); | ||||
250 | } | ||||
251 | pMemChart->SetColText( nCol, aString); | ||||
252 | } | ||||
253 | |||||
254 | // Row Header | ||||
255 | |||||
256 | for (nRow=0; nRow<nRowCount; nRow++) | ||||
257 | { | ||||
258 | OUString aString; | ||||
259 | if (HasRowHeaders()) | ||||
260 | { | ||||
261 | aString = rDocument.GetString(nStrCol, aRows[nRow], nTab1); | ||||
262 | } | ||||
263 | if (aString.isEmpty()) | ||||
264 | { | ||||
265 | OUStringBuffer aBuf; | ||||
266 | aBuf.append(ScResId(STR_ROWreinterpret_cast<char const *>("STR_ROW" "\004" u8"Row" ))); | ||||
267 | aBuf.append(' '); | ||||
268 | aBuf.append(static_cast<sal_Int32>(aRows[nRow]+1)); | ||||
269 | aString = aBuf.makeStringAndClear(); | ||||
270 | } | ||||
271 | pMemChart->SetRowText( nRow, aString); | ||||
272 | } | ||||
273 | |||||
274 | return pMemChart; | ||||
275 | } | ||||
276 | |||||
277 | std::unique_ptr<ScMemChart> ScChartArray::CreateMemChartMulti() | ||||
278 | { | ||||
279 | SCSIZE nColCount = GetPositionMap()->GetColCount(); | ||||
280 | SCSIZE nRowCount = GetPositionMap()->GetRowCount(); | ||||
281 | |||||
282 | // May happen at least with more than 32k rows. | ||||
283 | if (nColCount > SHRT_MAX32767 || nRowCount > SHRT_MAX32767) | ||||
284 | { | ||||
285 | nColCount = 0; | ||||
286 | nRowCount = 0; | ||||
287 | } | ||||
288 | |||||
289 | bool bValidData = true; | ||||
290 | if ( !nColCount ) | ||||
291 | { | ||||
292 | bValidData = false; | ||||
293 | nColCount = 1; | ||||
294 | } | ||||
295 | if ( !nRowCount ) | ||||
296 | { | ||||
297 | bValidData = false; | ||||
298 | nRowCount = 1; | ||||
299 | } | ||||
300 | |||||
301 | // Data | ||||
302 | std::unique_ptr<ScMemChart> pMemChart(new ScMemChart( nColCount, nRowCount )); | ||||
303 | |||||
304 | SCSIZE nCol = 0; | ||||
305 | SCSIZE nRow = 0; | ||||
306 | bool bCalcAsShown = rDocument.GetDocOptions().IsCalcAsShown(); | ||||
307 | sal_uLong nIndex = 0; | ||||
308 | if (bValidData) | ||||
309 | { | ||||
310 | for ( nCol = 0; nCol < nColCount; nCol++ ) | ||||
311 | { | ||||
312 | for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ ) | ||||
313 | { | ||||
314 | double nVal = DBL_MIN2.2250738585072014e-308; // Hack for Chart to recognize empty cells | ||||
315 | const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex ); | ||||
316 | if (pPos) | ||||
317 | // otherwise: Gap | ||||
318 | nVal = getCellValue(rDocument, *pPos, DBL_MIN2.2250738585072014e-308, bCalcAsShown); | ||||
319 | |||||
320 | pMemChart->SetData(nCol, nRow, nVal); | ||||
321 | } | ||||
322 | } | ||||
323 | } | ||||
324 | else | ||||
325 | { | ||||
326 | for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ ) | ||||
327 | { | ||||
328 | double nVal = DBL_MIN2.2250738585072014e-308; // Hack for Chart to recognize empty cells | ||||
329 | const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex ); | ||||
330 | if (pPos) | ||||
331 | // otherwise: Gap | ||||
332 | nVal = getCellValue(rDocument, *pPos, DBL_MIN2.2250738585072014e-308, bCalcAsShown); | ||||
333 | |||||
334 | pMemChart->SetData(nCol, nRow, nVal); | ||||
335 | } | ||||
336 | } | ||||
337 | |||||
338 | //TODO: Label when gaps | ||||
339 | |||||
340 | // Column header | ||||
341 | |||||
342 | SCCOL nPosCol = 0; | ||||
343 | for ( nCol = 0; nCol < nColCount; nCol++ ) | ||||
344 | { | ||||
345 | OUString aString; | ||||
346 | const ScAddress* pPos = GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL>(nCol) ); | ||||
347 | if ( HasColHeaders() && pPos ) | ||||
348 | aString = rDocument.GetString(pPos->Col(), pPos->Row(), pPos->Tab()); | ||||
349 | |||||
350 | if (aString.isEmpty()) | ||||
351 | { | ||||
352 | OUStringBuffer aBuf(ScResId(STR_COLUMNreinterpret_cast<char const *>("STR_COLUMN" "\004" u8"Column" ))); | ||||
353 | aBuf.append(' '); | ||||
354 | if ( pPos ) | ||||
355 | nPosCol = pPos->Col() + 1; | ||||
356 | else | ||||
357 | nPosCol++; | ||||
358 | ScAddress aPos( nPosCol - 1, 0, 0 ); | ||||
359 | aBuf.append(aPos.Format(ScRefFlags::COL_VALID)); | ||||
360 | aString = aBuf.makeStringAndClear(); | ||||
361 | } | ||||
362 | pMemChart->SetColText( nCol, aString); | ||||
363 | } | ||||
364 | |||||
365 | // Row header | ||||
366 | |||||
367 | SCROW nPosRow = 0; | ||||
368 | for ( nRow = 0; nRow < nRowCount; nRow++ ) | ||||
369 | { | ||||
370 | OUString aString; | ||||
371 | const ScAddress* pPos = GetPositionMap()->GetRowHeaderPosition( nRow ); | ||||
372 | if ( HasRowHeaders() && pPos ) | ||||
373 | aString = rDocument.GetString(pPos->Col(), pPos->Row(), pPos->Tab()); | ||||
374 | |||||
375 | if (aString.isEmpty()) | ||||
376 | { | ||||
377 | if ( pPos ) | ||||
378 | nPosRow = pPos->Row() + 1; | ||||
379 | else | ||||
380 | nPosRow++; | ||||
381 | aString = ScResId(STR_ROWreinterpret_cast<char const *>("STR_ROW" "\004" u8"Row" )) + " " + OUString::number(static_cast<sal_Int32>(nPosRow)); | ||||
382 | } | ||||
383 | pMemChart->SetRowText( nRow, aString); | ||||
384 | } | ||||
385 | |||||
386 | return pMemChart; | ||||
387 | } | ||||
388 | |||||
389 | /* 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: */ |