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 "BorderHandler.hxx" | |||
21 | #include "CellColorHandler.hxx" | |||
22 | #include "CellMarginHandler.hxx" | |||
23 | #include "ConversionHelper.hxx" | |||
24 | #include "MeasureHandler.hxx" | |||
25 | #include "TrackChangesHandler.hxx" | |||
26 | #include "TablePropertiesHandler.hxx" | |||
27 | #include "TagLogger.hxx" | |||
28 | #include "TDefTableHandler.hxx" | |||
29 | #include "DomainMapperTableManager.hxx" | |||
30 | ||||
31 | #include <ooxml/resourceids.hxx> | |||
32 | ||||
33 | #include <com/sun/star/text/VertOrientation.hpp> | |||
34 | #include <oox/token/tokens.hxx> | |||
35 | ||||
36 | using namespace com::sun::star; | |||
37 | using namespace oox; | |||
38 | ||||
39 | namespace writerfilter::dmapper { | |||
40 | ||||
41 | TablePropertiesHandler::TablePropertiesHandler() : | |||
42 | m_pCurrentInteropGrabBag(nullptr), | |||
43 | m_pTableManager( nullptr ) | |||
44 | { | |||
45 | } | |||
46 | ||||
47 | bool TablePropertiesHandler::sprm(Sprm & rSprm) | |||
48 | { | |||
49 | #ifdef DBG_UTIL | |||
50 | TagLogger::getInstance().startElement("TablePropertiesHandler.sprm"); | |||
51 | TagLogger::getInstance().attribute("sprm", rSprm.toString()); | |||
52 | #endif | |||
53 | ||||
54 | bool bRet = true; | |||
55 | sal_uInt32 nSprmId = rSprm.getId(); | |||
56 | Value::Pointer_t pValue = rSprm.getValue(); | |||
57 | sal_Int32 nIntValue = (pValue ? pValue->getInt() : 0); | |||
| ||||
58 | switch( nSprmId ) | |||
59 | { | |||
60 | case NS_ooxml::LN_CT_TrPrBase_jc: | |||
61 | case NS_ooxml::LN_CT_TblPrBase_jc: | |||
62 | { | |||
63 | sal_Int16 nOrient = ConversionHelper::convertTableJustification( nIntValue ); | |||
64 | TablePropertyMapPtr pTableMap( new TablePropertyMap ); | |||
65 | pTableMap->setValue( TablePropertyMap::HORI_ORIENT, nOrient ); | |||
66 | insertTableProps( pTableMap ); | |||
67 | } | |||
68 | break; | |||
69 | case NS_ooxml::LN_CT_TrPrBase_trHeight: | |||
70 | { | |||
71 | //contains unit and value | |||
72 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
73 | if( pProperties ) | |||
74 | { //contains attributes x2902 (LN_unit) and x17e2 (LN_trleft) | |||
75 | MeasureHandlerPtr pMeasureHandler( new MeasureHandler ); | |||
76 | pProperties->resolve(*pMeasureHandler); | |||
77 | TablePropertyMapPtr pPropMap( new TablePropertyMap ); | |||
78 | ||||
79 | pPropMap->Insert( PROP_SIZE_TYPE, uno::makeAny( pMeasureHandler->GetRowHeightSizeType() ), false); | |||
80 | pPropMap->Insert( PROP_HEIGHT, uno::makeAny(pMeasureHandler->getMeasureValue() )); | |||
81 | ||||
82 | insertRowProps(pPropMap); | |||
83 | } | |||
84 | } | |||
85 | break; | |||
86 | case NS_ooxml::LN_CT_TrPr_ins: | |||
87 | case NS_ooxml::LN_CT_TrPr_del: | |||
88 | { | |||
89 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
90 | if( pProperties ) | |||
91 | { | |||
92 | sal_Int32 nToken = sal_Int32(); | |||
93 | switch( nSprmId ) | |||
94 | { | |||
95 | case NS_ooxml::LN_CT_TrPr_ins: | |||
96 | nToken = XML_tableRowInsert; | |||
97 | break; | |||
98 | case NS_ooxml::LN_CT_TrPr_del: | |||
99 | nToken = XML_tableRowDelete; | |||
100 | break; | |||
101 | } | |||
102 | auto pTrackChangesHandler = std::make_shared<TrackChangesHandler>( nToken ); | |||
103 | pProperties->resolve(*pTrackChangesHandler); | |||
104 | TablePropertyMapPtr pPropMap( new TablePropertyMap ); | |||
105 | ||||
106 | // Add the 'track changes' properties to the 'table row' via UNO. | |||
107 | // This way - in the SW core - when it receives this - it will create a new 'Table Redline' object for that row | |||
108 | uno::Sequence<beans::PropertyValue> aTableRedlineProperties = pTrackChangesHandler->getRedlineProperties(); | |||
109 | pPropMap->Insert( PROP_TABLE_REDLINE_PARAMS , uno::makeAny( aTableRedlineProperties )); | |||
110 | insertRowProps(pPropMap); | |||
111 | } | |||
112 | } | |||
113 | break; | |||
114 | case NS_ooxml::LN_CT_TcPrBase_cellIns: | |||
115 | case NS_ooxml::LN_CT_TcPrBase_cellDel: | |||
116 | { | |||
117 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
118 | if( pProperties ) | |||
119 | { | |||
120 | sal_Int32 nToken; | |||
121 | switch( nSprmId ) | |||
122 | { | |||
123 | case NS_ooxml::LN_CT_TcPrBase_cellIns: | |||
124 | nToken = XML_tableCellInsert; | |||
125 | break; | |||
126 | case NS_ooxml::LN_CT_TcPrBase_cellDel: | |||
127 | nToken = XML_tableCellDelete; | |||
128 | break; | |||
129 | default: | |||
130 | throw lang::IllegalArgumentException("illegal redline token type", nullptr, 0); | |||
131 | break; | |||
132 | } | |||
133 | auto pTrackChangesHandler = std::make_shared<TrackChangesHandler>( nToken ); | |||
134 | pProperties->resolve(*pTrackChangesHandler); | |||
135 | TablePropertyMapPtr pPropMap( new TablePropertyMap ); | |||
136 | ||||
137 | // Add the 'track changes' properties to the 'table row' via UNO. | |||
138 | // This way - in the SW core - when it receives this - it will create a new 'Table Redline' object for that row | |||
139 | uno::Sequence<beans::PropertyValue> aTableRedlineProperties = pTrackChangesHandler->getRedlineProperties(); | |||
140 | pPropMap->Insert( PROP_TABLE_REDLINE_PARAMS , uno::makeAny( aTableRedlineProperties )); | |||
141 | cellProps(pPropMap); | |||
142 | } | |||
143 | } | |||
144 | break; | |||
145 | case NS_ooxml::LN_CT_TrPrBase_cantSplit: | |||
146 | { | |||
147 | //row can't break across pages if nIntValue == 1 | |||
148 | TablePropertyMapPtr pPropMap( new TablePropertyMap ); | |||
149 | pPropMap->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny( nIntValue != 1 ) ); | |||
150 | insertRowProps(pPropMap); | |||
151 | } | |||
152 | break; | |||
153 | case NS_ooxml::LN_CT_TcPrBase_vAlign: | |||
154 | { | |||
155 | sal_Int16 nVertOrient = text::VertOrientation::NONE; | |||
156 | switch( nIntValue ) | |||
157 | { | |||
158 | case NS_ooxml::LN_Value_ST_VerticalJc_center: nVertOrient = text::VertOrientation::CENTER; break; | |||
159 | case NS_ooxml::LN_Value_ST_VerticalJc_bottom: nVertOrient = text::VertOrientation::BOTTOM; break; | |||
160 | default:; | |||
161 | } | |||
162 | TablePropertyMapPtr pCellPropMap( new TablePropertyMap() ); | |||
163 | pCellPropMap->Insert( PROP_VERT_ORIENT, uno::makeAny( nVertOrient ) ); | |||
164 | //todo: in ooxml import the value of m_ncell is wrong | |||
165 | cellProps( pCellPropMap ); | |||
166 | if (m_pCurrentInteropGrabBag) | |||
167 | { | |||
168 | OUString aVertOrient; | |||
169 | switch( nIntValue ) | |||
170 | { | |||
171 | case NS_ooxml::LN_Value_ST_VerticalJc_top: aVertOrient = "top"; break; | |||
172 | case NS_ooxml::LN_Value_ST_VerticalJc_center: aVertOrient = "center"; break; | |||
173 | case NS_ooxml::LN_Value_ST_VerticalJc_both: aVertOrient = "both"; break; | |||
174 | case NS_ooxml::LN_Value_ST_VerticalJc_bottom: aVertOrient = "bottom"; break; | |||
175 | } | |||
176 | if (!aVertOrient.isEmpty()) | |||
177 | { | |||
178 | beans::PropertyValue aValue; | |||
179 | aValue.Name = "vAlign"; | |||
180 | aValue.Value <<= aVertOrient; | |||
181 | m_pCurrentInteropGrabBag->push_back(aValue); | |||
182 | } | |||
183 | } | |||
184 | } | |||
185 | break; | |||
186 | case NS_ooxml::LN_CT_TblPrBase_tblBorders: //table borders, might be defined in table style | |||
187 | { | |||
188 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
189 | if( pProperties ) | |||
190 | { | |||
191 | auto pBorderHandler = std::make_shared<BorderHandler>(true); | |||
192 | if (m_pCurrentInteropGrabBag) | |||
193 | pBorderHandler->enableInteropGrabBag("tblBorders"); | |||
194 | pProperties->resolve(*pBorderHandler); | |||
195 | if (m_pCurrentInteropGrabBag) | |||
196 | m_pCurrentInteropGrabBag->push_back(pBorderHandler->getInteropGrabBag()); | |||
197 | TablePropertyMapPtr pTablePropMap( new TablePropertyMap ); | |||
198 | pTablePropMap->InsertProps(pBorderHandler->getProperties()); | |||
199 | ||||
200 | #ifdef DBG_UTIL | |||
201 | pTablePropMap->dumpXml(); | |||
202 | #endif | |||
203 | insertTableProps( pTablePropMap ); | |||
204 | } | |||
205 | } | |||
206 | break; | |||
207 | case NS_ooxml::LN_CT_TblPrBase_tblLayout: | |||
208 | { | |||
209 | DomainMapperTableManager* pManager = dynamic_cast<DomainMapperTableManager*>(m_pTableManager); | |||
210 | if (pManager) | |||
211 | pManager->SetLayoutType(static_cast<sal_uInt32>(nIntValue)); | |||
212 | } | |||
213 | break; | |||
214 | case NS_ooxml::LN_CT_TblPrEx_tblBorders: | |||
215 | { | |||
216 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
217 | if( pProperties) | |||
218 | { | |||
219 | auto pBorderHandler = std::make_shared<BorderHandler>(true); | |||
220 | pProperties->resolve(*pBorderHandler); | |||
221 | TablePropertyMapPtr pTablePropMap( new TablePropertyMap ); | |||
222 | pTablePropMap->InsertProps(pBorderHandler->getProperties()); | |||
223 | ||||
224 | #ifdef DBG_UTIL | |||
225 | pTablePropMap->dumpXml(); | |||
226 | #endif | |||
227 | tableExceptionProps( pTablePropMap ); | |||
228 | } | |||
229 | } | |||
230 | break; | |||
231 | case NS_ooxml::LN_CT_TcPrBase_tcBorders ://cell borders | |||
232 | //contains CT_TcBorders_left, right, top, bottom | |||
233 | { | |||
234 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
235 | if( pProperties ) | |||
236 | { | |||
237 | //in OOXML there's one set of borders at each cell (if there is any) | |||
238 | tools::SvRef< TDefTableHandler > pTDefTableHandler( new TDefTableHandler()); | |||
239 | if (m_pCurrentInteropGrabBag) | |||
240 | pTDefTableHandler->enableInteropGrabBag("tcBorders"); | |||
241 | pProperties->resolve( *pTDefTableHandler ); | |||
242 | if (m_pCurrentInteropGrabBag) | |||
243 | m_pCurrentInteropGrabBag->push_back(pTDefTableHandler->getInteropGrabBag()); | |||
244 | TablePropertyMapPtr pCellPropMap( new TablePropertyMap ); | |||
245 | pTDefTableHandler->fillCellProperties( pCellPropMap ); | |||
246 | cellProps( pCellPropMap ); | |||
247 | } | |||
248 | } | |||
249 | break; | |||
250 | case NS_ooxml::LN_CT_TcPrBase_tcMar: | |||
251 | ||||
252 | { | |||
253 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
254 | if (pProperties) | |||
255 | { | |||
256 | auto pCellMarginHandler = std::make_shared<CellMarginHandler>(); | |||
257 | if (m_pCurrentInteropGrabBag) | |||
258 | pCellMarginHandler->enableInteropGrabBag("tcMar"); | |||
259 | pProperties->resolve(*pCellMarginHandler); | |||
260 | if (m_pCurrentInteropGrabBag) | |||
261 | m_pCurrentInteropGrabBag->push_back(pCellMarginHandler->getInteropGrabBag()); | |||
262 | TablePropertyMapPtr pCellProperties(new TablePropertyMap); | |||
263 | if (pCellMarginHandler->m_bTopMarginValid) | |||
264 | pCellProperties->Insert(PROP_TOP_BORDER_DISTANCE, uno::makeAny(pCellMarginHandler->m_nTopMargin)); | |||
265 | if (pCellMarginHandler->m_bLeftMarginValid) | |||
266 | pCellProperties->Insert(PROP_LEFT_BORDER_DISTANCE, uno::makeAny(pCellMarginHandler->m_nLeftMargin)); | |||
267 | if (pCellMarginHandler->m_bBottomMarginValid) | |||
268 | pCellProperties->Insert(PROP_BOTTOM_BORDER_DISTANCE, uno::makeAny(pCellMarginHandler->m_nBottomMargin)); | |||
269 | if (pCellMarginHandler->m_bRightMarginValid) | |||
270 | pCellProperties->Insert(PROP_RIGHT_BORDER_DISTANCE, uno::makeAny(pCellMarginHandler->m_nRightMargin)); | |||
271 | cellProps(pCellProperties); | |||
272 | } | |||
273 | } | |||
274 | break; | |||
275 | /* // tdf#123189 skip to keep MSO interoperability | |||
276 | case NS_ooxml::LN_CT_TblPrBase_shd: | |||
277 | { | |||
278 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
279 | if( pProperties.get()) | |||
280 | { | |||
281 | std::shared_ptr<CellColorHandler> pCellColorHandler( new CellColorHandler); | |||
282 | pProperties->resolve( *pCellColorHandler ); | |||
283 | TablePropertyMapPtr pTablePropMap( new TablePropertyMap ); | |||
284 | insertTableProps( pCellColorHandler->getProperties() ); | |||
285 | } | |||
286 | } | |||
287 | */ | |||
288 | break; | |||
289 | case NS_ooxml::LN_CT_TcPrBase_shd: | |||
290 | { | |||
291 | // each color sprm contains as much colors as cells are in a row | |||
292 | //LN_CT_TcPrBase_shd: cell shading contains: LN_CT_Shd_val, LN_CT_Shd_fill, LN_CT_Shd_color | |||
293 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
294 | if( pProperties ) | |||
295 | { | |||
296 | auto pCellColorHandler = std::make_shared<CellColorHandler>(); | |||
297 | pCellColorHandler->enableInteropGrabBag("shd"); //enable to store shd unsupported props in grab bag | |||
298 | pProperties->resolve( *pCellColorHandler ); | |||
299 | TablePropertyMapPtr pPropertyMap = pCellColorHandler->getProperties(); | |||
300 | beans::PropertyValue aGrabBag = pCellColorHandler->getInteropGrabBag(); | |||
301 | if (m_pCurrentInteropGrabBag) | |||
302 | m_pCurrentInteropGrabBag->push_back(aGrabBag); | |||
303 | pPropertyMap->Insert( PROP_CELL_INTEROP_GRAB_BAG, aGrabBag.Value ); | |||
304 | cellProps( pPropertyMap ); | |||
305 | } | |||
306 | } | |||
307 | break; | |||
308 | //OOXML table properties | |||
309 | case NS_ooxml::LN_CT_TblPrBase_tblCellMar: //cell margins | |||
310 | { | |||
311 | //contains LN_CT_TblCellMar_top, LN_CT_TblCellMar_left, LN_CT_TblCellMar_bottom, LN_CT_TblCellMar_right | |||
312 | // LN_CT_TblCellMar_start, LN_CT_TblCellMar_end | |||
313 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
314 | if( pProperties ) | |||
315 | { | |||
316 | auto pCellMarginHandler = std::make_shared<CellMarginHandler>(); | |||
317 | if (m_pCurrentInteropGrabBag) | |||
318 | pCellMarginHandler->enableInteropGrabBag("tblCellMar"); | |||
319 | pProperties->resolve( *pCellMarginHandler ); | |||
320 | if (m_pCurrentInteropGrabBag) | |||
321 | m_pCurrentInteropGrabBag->push_back(pCellMarginHandler->getInteropGrabBag()); | |||
322 | TablePropertyMapPtr pMarginProps( new TablePropertyMap ); | |||
323 | if( pCellMarginHandler->m_bTopMarginValid ) | |||
324 | pMarginProps->setValue( TablePropertyMap::CELL_MAR_TOP, pCellMarginHandler->m_nTopMargin ); | |||
325 | if( pCellMarginHandler->m_bBottomMarginValid ) | |||
326 | pMarginProps->setValue( TablePropertyMap::CELL_MAR_BOTTOM, pCellMarginHandler->m_nBottomMargin ); | |||
327 | if( pCellMarginHandler->m_bLeftMarginValid ) | |||
328 | pMarginProps->setValue( TablePropertyMap::CELL_MAR_LEFT, pCellMarginHandler->m_nLeftMargin ); | |||
329 | if( pCellMarginHandler->m_bRightMarginValid ) | |||
330 | pMarginProps->setValue( TablePropertyMap::CELL_MAR_RIGHT, pCellMarginHandler->m_nRightMargin ); | |||
331 | insertTableProps(pMarginProps); | |||
332 | } | |||
333 | } | |||
334 | break; | |||
335 | case NS_ooxml::LN_CT_TblPrBase_tblInd: | |||
336 | { | |||
337 | writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); | |||
338 | if (pProperties) | |||
339 | { | |||
340 | MeasureHandlerPtr pHandler(new MeasureHandler); | |||
341 | if (m_pCurrentInteropGrabBag) | |||
342 | pHandler->enableInteropGrabBag("tblInd"); | |||
343 | pProperties->resolve( *pHandler ); | |||
344 | if (m_pCurrentInteropGrabBag) | |||
345 | m_pCurrentInteropGrabBag->push_back(pHandler->getInteropGrabBag()); | |||
346 | TablePropertyMapPtr pTblIndMap(new TablePropertyMap); | |||
347 | sal_uInt32 nTblInd = pHandler->getMeasureValue(); | |||
348 | pTblIndMap->setValue( TablePropertyMap::LEFT_MARGIN, nTblInd); | |||
349 | insertTableProps(pTblIndMap); | |||
350 | } | |||
351 | } | |||
352 | break; | |||
353 | case NS_ooxml::LN_CT_TcPrBase_hideMark: | |||
354 | if (nIntValue) | |||
355 | { | |||
356 | TablePropertyMapPtr pPropMap(new TablePropertyMap()); | |||
357 | pPropMap->Insert(PROP_CELL_HIDE_MARK, uno::makeAny(nIntValue)); | |||
358 | cellProps(pPropMap); | |||
359 | } | |||
360 | break; | |||
361 | default: | |||
362 | // Not handled here, give the next handler a chance. | |||
363 | bRet = false; | |||
364 | // However, these logically belong here, so save the value if necessary. | |||
365 | switch (nSprmId) | |||
366 | { | |||
367 | case NS_ooxml::LN_CT_TblPrBase_tblStyleRowBandSize: | |||
368 | case NS_ooxml::LN_CT_TblPrBase_tblStyleColBandSize: | |||
369 | if (m_pCurrentInteropGrabBag) | |||
370 | { | |||
371 | beans::PropertyValue aValue; | |||
372 | aValue.Name = (nSprmId == NS_ooxml::LN_CT_TblPrBase_tblStyleRowBandSize ? OUStringLiteral(u"tblStyleRowBandSize") : OUStringLiteral(u"tblStyleColBandSize")); | |||
373 | aValue.Value <<= nIntValue; | |||
374 | m_pCurrentInteropGrabBag->push_back(aValue); | |||
375 | } | |||
376 | break; | |||
377 | } | |||
378 | break; | |||
379 | } | |||
380 | ||||
381 | #ifdef DBG_UTIL | |||
382 | TagLogger::getInstance().endElement(); | |||
383 | #endif | |||
384 | ||||
385 | return bRet; | |||
386 | } | |||
387 | ||||
388 | void TablePropertiesHandler::SetInteropGrabBag(std::vector<beans::PropertyValue>& rValue) | |||
389 | { | |||
390 | m_pCurrentInteropGrabBag = &rValue; | |||
391 | } | |||
392 | } | |||
393 | ||||
394 | /* 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: */ |