Bug Summary

File:home/maarten/src/libreoffice/core/include/tools/ref.hxx
Warning:line 56, column 30
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name TableManager.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/writerfilter/source -I /home/maarten/src/libreoffice/core/writerfilter/inc -I /home/maarten/src/libreoffice/core/writerfilter/source -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx

/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx

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 "TableManager.hxx"
21#include <ooxml/resourceids.hxx>
22#include "TagLogger.hxx"
23#include "DomainMapperTableHandler.hxx"
24#include "DomainMapper_Impl.hxx"
25#include "util.hxx"
26
27#include <tools/diagnose_ex.h>
28
29namespace writerfilter::dmapper
30{
31void TableManager::clearData() {}
32
33void TableManager::openCell(const css::uno::Reference<css::text::XTextRange>& rHandle,
34 const TablePropertyMapPtr& pProps)
35{
36#ifdef DBG_UTIL
37 TagLogger::getInstance().startElement("tablemanager.openCell");
38 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
39 TagLogger::getInstance().endElement();
40#endif
41
42 if (!mTableDataStack.empty())
43 {
44 TableData::Pointer_t pTableData = mTableDataStack.top();
45
46 pTableData->addCell(rHandle, pProps);
47 }
48}
49
50bool TableManager::isIgnore() const { return isRowEnd(); }
51
52sal_uInt32 TableManager::getGridBefore(sal_uInt32 nRow)
53{
54 assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail
("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
, 54, __extension__ __PRETTY_FUNCTION__))
;
55 if (nRow >= mTableDataStack.top()->getRowCount())
56 return 0;
57 return mTableDataStack.top()->getRow(nRow)->getGridBefore();
58}
59
60sal_uInt32 TableManager::getCurrentGridBefore()
61{
62 return mTableDataStack.top()->getCurrentRow()->getGridBefore();
63}
64
65void TableManager::setCurrentGridBefore(sal_uInt32 nSkipGrids)
66{
67 mTableDataStack.top()->getCurrentRow()->setGridBefore(nSkipGrids);
68}
69
70sal_uInt32 TableManager::getGridAfter(sal_uInt32 nRow)
71{
72 assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail
("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
, 72, __extension__ __PRETTY_FUNCTION__))
;
73 if (nRow >= mTableDataStack.top()->getRowCount())
74 return 0;
75 return mTableDataStack.top()->getRow(nRow)->getGridAfter();
76}
77
78void TableManager::setCurrentGridAfter(sal_uInt32 nSkipGrids)
79{
80 assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail
("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
, 80, __extension__ __PRETTY_FUNCTION__))
;
81 mTableDataStack.top()->getCurrentRow()->setGridAfter(nSkipGrids);
82}
83
84std::vector<sal_uInt32> TableManager::getCurrentGridSpans()
85{
86 return mTableDataStack.top()->getCurrentRow()->getGridSpans();
87}
88
89void TableManager::setCurrentGridSpan(sal_uInt32 nGridSpan, bool bFirstCell)
90{
91 mTableDataStack.top()->getCurrentRow()->setCurrentGridSpan(nGridSpan, bFirstCell);
92}
93
94sal_uInt32 TableManager::findColumn(const sal_uInt32 nRow, const sal_uInt32 nCell)
95{
96 RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow);
97 if (!pRow || nCell < pRow->getGridBefore()
98 || nCell >= pRow->getCellCount() - pRow->getGridAfter())
99 {
100 return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF);
101 }
102
103 // The gridSpans provide a one-based index, so add up all the spans of the PREVIOUS columns,
104 // and that result will provide the first possible zero-based number for the desired column.
105 sal_uInt32 nColumn = 0;
106 for (sal_uInt32 n = 0; n < nCell; ++n)
107 nColumn += pRow->getGridSpan(n);
108 return nColumn;
109}
110
111sal_uInt32 TableManager::findColumnCell(const sal_uInt32 nRow, const sal_uInt32 nCol)
112{
113 RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow);
114 if (!pRow || nCol < pRow->getGridBefore())
115 return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF);
116
117 sal_uInt32 nCell = 0;
118 sal_uInt32 nGrids = 0;
119 // The gridSpans give us a one-based index, but requested column is zero-based - so keep that in mind.
120 const sal_uInt32 nMaxCell = pRow->getCellCount() - pRow->getGridAfter() - 1;
121 for (const auto& rSpan : pRow->getGridSpans())
122 {
123 nGrids += rSpan;
124 if (nCol < nGrids)
125 return nCell;
126
127 ++nCell;
128 if (nCell > nMaxCell)
129 break;
130 }
131 return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF); // must be in gridAfter or invalid column request
132}
133
134void TableManager::endOfRowAction() {}
135
136void TableManager::endOfCellAction() {}
137
138void TableManager::insertTableProps(const TablePropertyMapPtr& pProps)
139{
140#ifdef DBG_UTIL
141 TagLogger::getInstance().startElement("tablemanager.insertTableProps");
142#endif
143
144 if (getTableProps() && getTableProps() != pProps)
145 getTableProps()->InsertProps(pProps.get());
146 else
147 mState.setTableProps(pProps);
148
149#ifdef DBG_UTIL
150 TagLogger::getInstance().endElement();
151#endif
152}
153
154void TableManager::insertRowProps(const TablePropertyMapPtr& pProps)
155{
156#ifdef DBG_UTIL
157 TagLogger::getInstance().startElement("tablemanager.insertRowProps");
158#endif
159
160 if (getRowProps())
161 getRowProps()->InsertProps(pProps.get());
162 else
163 mState.setRowProps(pProps);
164
165#ifdef DBG_UTIL
166 TagLogger::getInstance().endElement();
167#endif
168}
169
170void TableManager::cellProps(const TablePropertyMapPtr& pProps)
171{
172#ifdef DBG_UTIL
173 TagLogger::getInstance().startElement("tablemanager.cellProps");
174#endif
175
176 if (getCellProps())
177 getCellProps()->InsertProps(pProps.get());
178 else
179 mState.setCellProps(pProps);
180
181#ifdef DBG_UTIL
182 TagLogger::getInstance().endElement();
183#endif
184}
185
186void TableManager::tableExceptionProps(const TablePropertyMapPtr& pProps)
187{
188#ifdef DBG_UTIL
189 TagLogger::getInstance().startElement("tablemanager.tableExceptionProps");
190#endif
191
192 if (getTableExceptionProps())
193 getTableExceptionProps()->InsertProps(pProps.get());
194 else
195 mState.setTableExceptionProps(pProps);
196
197#ifdef DBG_UTIL
198 TagLogger::getInstance().endElement();
199#endif
200}
201
202void TableManager::utext(const sal_uInt8* data, std::size_t len)
203{
204 // optimization: cell/row end characters are the last characters in a run
205
206 if (len > 0)
207 {
208 sal_Unicode nChar = data[(len - 1) * 2] + (data[(len - 1) * 2 + 1] << 8);
209 if (nChar == 0x7)
210 handle0x7();
211 }
212}
213
214void TableManager::text(const sal_uInt8* data, std::size_t len)
215{
216 // optimization: cell/row end characters are the last characters in a run
217 if (len > 0 && data[len - 1] == 0x7)
218 handle0x7();
219}
220
221void TableManager::handle0x7()
222{
223#ifdef DBG_UTIL
224 TagLogger::getInstance().startElement("tablemanager.handle0x7");
225#endif
226
227 if (mnTableDepthNew < 1)
228 mnTableDepthNew = 1;
229
230 if (isInCell())
231 endCell();
232 else
233 endRow();
234
235#ifdef DBG_UTIL
236 TagLogger::getInstance().endElement();
237#endif
238}
239
240bool TableManager::sprm(Sprm& rSprm)
241{
242 bool bRet = true;
243 switch (rSprm.getId())
244 {
245 case NS_ooxml::LN_tblDepth:
246 {
247 Value::Pointer_t pValue = rSprm.getValue();
248
249 cellDepth(pValue->getInt());
250 }
251 break;
252 case NS_ooxml::LN_inTbl:
253 inCell();
254 break;
255 case NS_ooxml::LN_tblCell:
256 endCell();
257 break;
258 case NS_ooxml::LN_tblRow:
259 endRow();
260 break;
261 default:
262 bRet = false;
263 }
264 return bRet;
265}
266
267void TableManager::closeCell(const css::uno::Reference<css::text::XTextRange>& rHandle)
268{
269#ifdef DBG_UTIL
270 TagLogger::getInstance().startElement("tablemanager.closeCell");
271 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
272 TagLogger::getInstance().endElement();
273#endif
274
275 if (!mTableDataStack.empty())
276 {
277 TableData::Pointer_t pTableData = mTableDataStack.top();
278
279 pTableData->endCell(rHandle);
280
281 if (mpTableDataHandler)
282 mpTableDataHandler->getDomainMapperImpl().ClearPreviousParagraph();
283 }
284}
285
286void TableManager::ensureOpenCell(const TablePropertyMapPtr& pProps)
287{
288#ifdef DBG_UTIL
289 TagLogger::getInstance().startElement("tablemanager.ensureOpenCell");
290#endif
291
292 if (!mTableDataStack.empty())
293 {
294 TableData::Pointer_t pTableData = mTableDataStack.top();
295
296 if (pTableData != nullptr)
297 {
298 if (!pTableData->isCellOpen())
299 openCell(getHandle(), pProps);
300 else
301 pTableData->insertCellProperties(pProps);
302 }
303 }
304#ifdef DBG_UTIL
305 TagLogger::getInstance().endElement();
306#endif
307}
308
309void TableManager::endParagraphGroup()
310{
311 sal_Int32 nTableDepthDifference = mnTableDepthNew - mnTableDepth;
312
313 TablePropertyMapPtr pEmptyProps;
314
315 while (nTableDepthDifference > 0)
1
Assuming 'nTableDepthDifference' is <= 0
2
Loop condition is false. Execution continues on line 322
316 {
317 ensureOpenCell(pEmptyProps);
318 startLevel();
319
320 --nTableDepthDifference;
321 }
322 while (nTableDepthDifference < 0)
3
Loop condition is false. Execution continues on line 329
323 {
324 endLevel();
325
326 ++nTableDepthDifference;
327 }
328
329 mnTableDepth = mnTableDepthNew;
330
331 if (mnTableDepth <= 0)
4
Assuming field 'mnTableDepth' is > 0
5
Taking false branch
332 return;
333
334 if (isRowEnd())
6
Assuming the condition is true
7
Taking true branch
335 {
336 endOfRowAction();
337 mTableDataStack.top()->endRow(getRowProps());
8
Calling 'TableData::endRow'
338 mState.resetRowProps();
339 }
340
341 else if (isInCell())
342 {
343 ensureOpenCell(getCellProps());
344
345 if (mState.isCellEnd())
346 {
347 endOfCellAction();
348 closeCell(getHandle());
349 }
350 }
351 mState.resetCellProps();
352}
353
354void TableManager::startParagraphGroup()
355{
356 mState.resetCellSpecifics();
357 mnTableDepthNew = 0;
358}
359
360void TableManager::resolveCurrentTable()
361{
362#ifdef DBG_UTIL
363 TagLogger::getInstance().startElement("tablemanager.resolveCurrentTable");
364#endif
365
366 if (mpTableDataHandler != nullptr)
367 {
368 try
369 {
370 TableData::Pointer_t pTableData = mTableDataStack.top();
371
372 unsigned int nRows = pTableData->getRowCount();
373
374 mpTableDataHandler->startTable(getTableProps());
375
376 for (unsigned int nRow = 0; nRow < nRows; ++nRow)
377 {
378 RowData::Pointer_t pRowData = pTableData->getRow(nRow);
379
380 unsigned int nCells = pRowData->getCellCount();
381
382 mpTableDataHandler->startRow(pRowData->getProperties());
383
384 for (unsigned int nCell = 0; nCell < nCells; ++nCell)
385 {
386 mpTableDataHandler->startCell(pRowData->getCellStart(nCell),
387 pRowData->getCellProperties(nCell));
388
389 mpTableDataHandler->endCell(pRowData->getCellEnd(nCell));
390 }
391
392 mpTableDataHandler->endRow();
393 }
394
395 mpTableDataHandler->endTable(mTableDataStack.size() - 1, m_bTableStartsAtCellStart);
396 }
397 catch (css::uno::Exception const&)
398 {
399 TOOLS_WARN_EXCEPTION("writerfilter", "resolving of current table failed")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "writerfilter")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "resolving of current table failed"
<< " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
":" "399" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "resolving of current table failed" <<
" " << exceptionToString(tools_warn_exception)), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "resolving of current table failed" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
":" "399" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "resolving of current table failed" << " " <<
exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
":" "399" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "resolving of current table failed" <<
" " << exceptionToString(tools_warn_exception)), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "resolving of current table failed" << " " <<
exceptionToString(tools_warn_exception); ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx"
":" "399" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
400 }
401 }
402 mState.resetTableProps();
403 clearData();
404
405#ifdef DBG_UTIL
406 TagLogger::getInstance().endElement();
407#endif
408}
409
410void TableManager::endLevel()
411{
412 if (mpTableDataHandler != nullptr)
413 resolveCurrentTable();
414
415 // Store the unfinished row as it will be used for the next table
416 if (mbKeepUnfinishedRow)
417 mpUnfinishedRow = mTableDataStack.top()->getCurrentRow();
418 mState.endLevel();
419 mTableDataStack.pop();
420
421#ifdef DBG_UTIL
422 TableData::Pointer_t pTableData;
423
424 if (!mTableDataStack.empty())
425 pTableData = mTableDataStack.top();
426
427 TagLogger::getInstance().startElement("tablemanager.endLevel");
428 TagLogger::getInstance().attribute("level", mTableDataStack.size());
429
430 if (pTableData != nullptr)
431 TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no");
432
433 TagLogger::getInstance().endElement();
434#endif
435}
436
437void TableManager::startLevel()
438{
439#ifdef DBG_UTIL
440 TableData::Pointer_t pTableData;
441
442 if (!mTableDataStack.empty())
443 pTableData = mTableDataStack.top();
444
445 TagLogger::getInstance().startElement("tablemanager.startLevel");
446 TagLogger::getInstance().attribute("level", mTableDataStack.size());
447
448 if (pTableData != nullptr)
449 TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no");
450
451 TagLogger::getInstance().endElement();
452#endif
453
454 TableData::Pointer_t pTableData2(new TableData(mTableDataStack.size()));
455
456 // If we have an unfinished row stored here, then push it to the new TableData
457 if (mpUnfinishedRow)
458 {
459 for (unsigned int i = 0; i < mpUnfinishedRow->getCellCount(); ++i)
460 {
461 pTableData2->addCell(mpUnfinishedRow->getCellStart(i),
462 mpUnfinishedRow->getCellProperties(i));
463 pTableData2->endCell(mpUnfinishedRow->getCellEnd(i));
464 pTableData2->getCurrentRow()->setCurrentGridSpan(mpUnfinishedRow->getGridSpan(i));
465 }
466 pTableData2->getCurrentRow()->setGridBefore(mpUnfinishedRow->getGridBefore());
467 pTableData2->getCurrentRow()->setGridAfter(mpUnfinishedRow->getGridAfter());
468 mpUnfinishedRow.clear();
469 }
470
471 mTableDataStack.push(pTableData2);
472 mState.startLevel();
473}
474
475bool TableManager::isInTable()
476{
477 bool bInTable = false;
478 if (!mTableDataStack.empty())
479 bInTable = mTableDataStack.top()->getDepth() > 0;
480 return bInTable;
481}
482
483void TableManager::handle(const css::uno::Reference<css::text::XTextRange>& rHandle)
484{
485#ifdef DBG_UTIL
486 TagLogger::getInstance().startElement("tablemanager.handle");
487 TagLogger::getInstance().chars(XTextRangeToString(rHandle));
488 TagLogger::getInstance().endElement();
489#endif
490
491 setHandle(rHandle);
492}
493
494void TableManager::setHandler(const tools::SvRef<DomainMapperTableHandler>& pTableDataHandler)
495{
496 mpTableDataHandler = pTableDataHandler;
497}
498
499void TableManager::endRow()
500{
501#ifdef DBG_UTIL
502 TagLogger::getInstance().element("tablemanager.endRow");
503#endif
504 TableData::Pointer_t pTableData = mTableDataStack.top();
505
506 // Add borderless w:gridBefore cell(s) to the row
507 sal_uInt32 nGridBefore = getCurrentGridBefore();
508 if (pTableData && nGridBefore > 0 && pTableData->getCurrentRow()->getCellCount() > 0)
509 {
510 const css::uno::Reference<css::text::XTextRange>& xRowStart
511 = pTableData->getCurrentRow()->getCellStart(0);
512 if (xRowStart.is())
513 {
514 try
515 {
516 // valid TextRange for table creation (not a nested table)?
517 xRowStart->getText()->createTextCursorByRange(xRowStart);
518
519 for (unsigned int i = 0; i < nGridBefore; ++i)
520 {
521 css::table::BorderLine2 aBorderLine;
522 aBorderLine.Color = 0;
523 aBorderLine.InnerLineWidth = 0;
524 aBorderLine.OuterLineWidth = 0;
525 TablePropertyMapPtr pCellProperties(new TablePropertyMap);
526 pCellProperties->Insert(PROP_TOP_BORDER, css::uno::makeAny(aBorderLine));
527 pCellProperties->Insert(PROP_LEFT_BORDER, css::uno::makeAny(aBorderLine));
528 pCellProperties->Insert(PROP_BOTTOM_BORDER, css::uno::makeAny(aBorderLine));
529 pCellProperties->Insert(PROP_RIGHT_BORDER, css::uno::makeAny(aBorderLine));
530 pTableData->getCurrentRow()->addCell(xRowStart, pCellProperties,
531 /*bAddBefore=*/true);
532 }
533 }
534 catch (css::uno::Exception const&)
535 {
536 // don't add gridBefore cells in not valid TextRange
537 setCurrentGridBefore(0);
538 setCurrentGridSpan(getCurrentGridSpans().front() + nGridBefore,
539 /*bFirstCell=*/true);
540 }
541 }
542 }
543
544 setRowEnd(true);
545}
546
547void TableManager::endCell()
548{
549#ifdef DBG_UTIL
550 TagLogger::getInstance().element("tablemanager.endCell");
551#endif
552
553 setCellEnd(true);
554}
555
556void TableManager::inCell()
557{
558#ifdef DBG_UTIL
559 TagLogger::getInstance().element("tablemanager.inCell");
560#endif
561 setInCell(true);
562
563 if (mnTableDepthNew < 1)
564 mnTableDepthNew = 1;
565}
566
567void TableManager::cellDepth(sal_uInt32 nDepth)
568{
569#ifdef DBG_UTIL
570 TagLogger::getInstance().startElement("tablemanager.cellDepth");
571 TagLogger::getInstance().attribute("depth", nDepth);
572 TagLogger::getInstance().endElement();
573#endif
574
575 mnTableDepthNew = nDepth;
576}
577
578void TableManager::setTableStartsAtCellStart(bool bTableStartsAtCellStart)
579{
580 m_bTableStartsAtCellStart = bTableStartsAtCellStart;
581}
582
583void TableManager::setCellLastParaAfterAutospacing(bool bIsAfterAutospacing)
584{
585 m_bCellLastParaAfterAutospacing = bIsAfterAutospacing;
586}
587
588TableManager::TableManager()
589 : mnTableDepthNew(0)
590 , mnTableDepth(0)
591 , mbKeepUnfinishedRow(false)
592 , m_bTableStartsAtCellStart(false)
593{
594 setRowEnd(false);
595 setInCell(false);
596 setCellEnd(false);
597 m_bCellLastParaAfterAutospacing = false;
598}
599
600TableManager::~TableManager() = default;
601}
602
603/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableData.hxx

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#ifndef INCLUDED_WRITERFILTER_SOURCE_DMAPPER_TABLEDATA_HXX
21#define INCLUDED_WRITERFILTER_SOURCE_DMAPPER_TABLEDATA_HXX
22
23#include <com/sun/star/text/XTextRange.hpp>
24
25#include "PropertyMap.hxx"
26
27#include <vector>
28
29namespace writerfilter::dmapper
30{
31
32/**
33 Class containing the data to describe a table cell.
34 */
35class CellData final : public virtual SvRefBase
36{
37 /**
38 Handle to start of cell.
39 */
40 css::uno::Reference<css::text::XTextRange> mStart;
41
42 /**
43 Handle to end of cell.
44 */
45 css::uno::Reference<css::text::XTextRange> mEnd;
46
47 /**
48 Pointer to properties of cell.
49 */
50 TablePropertyMapPtr mpProps;
51
52 bool mbOpen;
53
54 sal_uInt32 m_nGridSpan; ///< number of grid columns in the parent table's table grid which this cell defines
55
56public:
57 typedef tools::SvRef<CellData> Pointer_t;
58
59 CellData(css::uno::Reference<css::text::XTextRange> const & start, TablePropertyMapPtr pProps)
60 : mStart(start), mEnd(start), mpProps(pProps), mbOpen(true)
61 , m_nGridSpan(1)
62 {
63 }
64
65 /**
66 Set the end handle of a cell.
67
68 @param end the end handle of the cell
69 */
70 void setEnd(css::uno::Reference<css::text::XTextRange> const & end) { mEnd = end; mbOpen = false; }
71
72 /**
73 Adds properties to the cell.
74
75 @param pProps the properties to add
76 */
77 void insertProperties(TablePropertyMapPtr pProps)
78 {
79 if( mpProps )
80 mpProps->InsertProps(pProps.get());
81 else
82 mpProps = pProps;
83 }
84
85 /**
86 Return start handle of the cell.
87 */
88 const css::uno::Reference<css::text::XTextRange>& getStart() const { return mStart; }
89
90 /**
91 Return end handle of the cell.
92 */
93 const css::uno::Reference<css::text::XTextRange>& getEnd() const { return mEnd; }
94
95 /**
96 Return properties of the cell.
97 */
98 const TablePropertyMapPtr& getProperties() const { return mpProps; }
99
100 bool isOpen() const { return mbOpen; }
101
102 sal_uInt32 getGridSpan() const { return m_nGridSpan; }
103 void setGridSpan( sal_uInt32 nSpan ) { m_nGridSpan = nSpan; }
104};
105
106/**
107 Class to handle data of a table row.
108 */
109class RowData final : public virtual SvRefBase
110{
111 typedef ::std::vector<CellData::Pointer_t> Cells;
112
113 /**
114 the cell data of the row
115 */
116 Cells mCells;
117
118 /**
119 the properties of the row
120 */
121 mutable TablePropertyMapPtr mpProperties;
122
123 sal_uInt32 m_nGridBefore; ///< number of grid columns in the parent table's table grid which must be skipped before the contents of this table row are added to the parent table
124 sal_uInt32 m_nGridAfter; ///< number of grid columns in the parent table's table grid which shall be left after the last cell in the table row
125
126public:
127 typedef tools::SvRef<RowData> Pointer_t;
128
129 RowData()
130 : m_nGridBefore(0)
131 , m_nGridAfter(0)
132 {
133 }
134
135 RowData(const RowData& rRowData)
136 : SvRefBase(), mCells(rRowData.mCells), mpProperties(rRowData.mpProperties)
137 , m_nGridBefore(rRowData.m_nGridBefore)
138 , m_nGridAfter(rRowData.m_nGridAfter)
139 {
140 }
141
142 /**
143 Add a cell to the row.
144
145 @param start the start handle of the cell
146 @param end the end handle of the cell
147 @param pProps the properties of the cell
148 @param bAddBefore true: add an empty cell at beginning of the row for gridBefore
149 */
150 void addCell(const css::uno::Reference<css::text::XTextRange>& start, TablePropertyMapPtr pProps, bool bAddBefore = false)
151 {
152 CellData::Pointer_t pCellData(new CellData(start, pProps));
153 if (bAddBefore)
154 {
155 mCells.insert(mCells.begin(), pCellData);
156 mCells[0]->setEnd(start);
157 }
158 else
159 mCells.push_back(pCellData);
160 }
161
162 void endCell(const css::uno::Reference<css::text::XTextRange>& end)
163 {
164 if (mCells.size() > 0)
165 mCells.back()->setEnd(end);
166 }
167
168 bool isCellOpen() const
169 {
170 return mCells.size() > 0 && mCells.back()->isOpen();
171 }
172
173 /**
174 Add properties to the row.
175
176 @param pProperties the properties to set
177 */
178 void insertProperties(TablePropertyMapPtr pProperties)
179 {
180 if( pProperties )
10
Taking true branch
181 {
182 if( !mpProperties )
11
Taking false branch
183 mpProperties = pProperties;
184 else
185 mpProperties->InsertProps(pProperties.get());
12
Calling '~SvRef'
22
Returning from '~SvRef'
186 }
187 }
188
189 /**
190 Add properties to the last cell of the row.
191 */
192 void insertCellProperties(TablePropertyMapPtr pProps)
193 {
194 if (!mCells.empty())
195 mCells.back()->insertProperties(pProps);
196 }
197
198 /**
199 Return number of cells in the row.
200 */
201 unsigned int getCellCount() const
202 {
203 return mCells.size();
204 }
205
206 /**
207 Return start handle of a cell in the row.
208
209 @param i index of the cell
210 */
211 const css::uno::Reference<css::text::XTextRange>& getCellStart(unsigned int i) const
212 {
213 return mCells[i]->getStart();
214 }
215
216 /**
217 Return end handle of a cell in the row.
218
219 @param i index of the cell
220 */
221 const css::uno::Reference<css::text::XTextRange>& getCellEnd(unsigned int i) const
222 {
223 return mCells[i]->getEnd();
224 }
225
226 /**
227 Return the properties of a cell in the row.
228
229 @param i index of the cell
230 */
231 TablePropertyMapPtr const & getCellProperties(unsigned int i) const
232 {
233 return mCells[i]->getProperties();
234 }
235
236 /**
237 Return properties of the row.
238 */
239 const TablePropertyMapPtr& getProperties() const
240 {
241 return mpProperties;
242 }
243
244 sal_uInt32 getGridBefore() const { return m_nGridBefore; }
245 void setGridBefore(sal_uInt32 nSkipGrids) { m_nGridBefore = nSkipGrids; }
246 sal_uInt32 getGridAfter() const { return m_nGridAfter; }
247 void setGridAfter(sal_uInt32 nSkipGrids) { m_nGridAfter = nSkipGrids; }
248 sal_uInt32 getGridSpan(sal_uInt32 i) { return mCells[i]->getGridSpan(); }
249 std::vector< sal_uInt32 > getGridSpans()
250 {
251 std::vector< sal_uInt32 > nRet;
252 for (auto const& aCell: mCells)
253 nRet.push_back(aCell->getGridSpan());
254 return nRet;
255 }
256 void setCurrentGridSpan(sal_uInt32 nSpan, bool bFirstCell = false)
257 {
258 if ( mCells.size() )
259 {
260 if ( bFirstCell )
261 mCells.front()->setGridSpan(nSpan);
262 else
263 mCells.back()->setGridSpan(nSpan);
264 }
265 }
266};
267
268/**
269 Class that holds the data of a table.
270 */
271class TableData : public virtual SvRefBase
272{
273 typedef RowData::Pointer_t RowPointer_t;
274 typedef ::std::vector<RowPointer_t> Rows;
275
276 /**
277 the data of the rows of the table
278 */
279 Rows mRows;
280
281 /**
282 pointer to the data of the current row (while building up the table data).
283 */
284 RowPointer_t mpRow;
285
286 /**
287 depth of the current table in a hierarchy of tables
288 */
289 unsigned int mnDepth;
290
291 /**
292 initialize mpRow
293 */
294 void newRow() { mpRow = RowPointer_t(new RowData()); }
295
296public:
297 typedef tools::SvRef<TableData> Pointer_t;
298
299 explicit TableData(unsigned int nDepth) : mnDepth(nDepth) { newRow(); }
300
301 /**
302 End the current row.
303
304 Sets properties of the current row and pushes the row to the
305 back of the rows currently contained in the table.
306
307 @param pProperties properties of the row to be ended
308 */
309 void endRow(TablePropertyMapPtr pProperties)
310 {
311 mpRow->insertProperties(pProperties);
9
Calling 'RowData::insertProperties'
23
Returning; memory was released
24
Calling '~SvRef'
312 mRows.push_back(mpRow);
313 newRow();
314 }
315
316 /**
317 Add a cell to the current row.
318
319 @param start start handle of the cell
320 @param end end handle of the cell
321 @param pProps properties of the cell
322 */
323 void addCell(const css::uno::Reference<css::text::XTextRange>& start, TablePropertyMapPtr pProps)
324 {
325 mpRow->addCell(start, pProps);
326 }
327
328 /**
329 End the current cell of the current row.
330
331 @parm end end handle of the cell
332 */
333 void endCell(const css::uno::Reference<css::text::XTextRange>& end)
334 {
335 mpRow->endCell(end);
336 }
337
338 /**
339 Return if the current cell of the current row is open.
340 */
341 bool isCellOpen() const
342 {
343 return mpRow->isCellOpen();
344 }
345
346 /**
347 Insert properties to the current cell of the current row.
348
349 @param pProps the properties to add
350 */
351 void insertCellProperties(TablePropertyMapPtr pProps)
352 {
353 mpRow->insertCellProperties(pProps);
354 }
355
356 /**
357 Return number of rows in the table.
358 */
359 unsigned int getRowCount() const
360 {
361 return mRows.size();
362 }
363
364 /**
365 Return depth of table in surrounding table hierarchy.
366 */
367 unsigned int getDepth() const
368 {
369 return mnDepth;
370 }
371
372 /**
373 Return row data of a certain row.
374
375 @param i index of the row
376 */
377 RowPointer_t const & getRow(unsigned int i) const
378 {
379 return mRows[i];
380 }
381
382 const RowPointer_t& getCurrentRow() const
383 {
384 return mpRow;
385 }
386};
387
388}
389
390
391#endif // INCLUDED_WRITERFILTER_SOURCE_DMAPPER_RESOURCEMODEL_TABLEDATA_HXX
392
393/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/ref.hxx

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
31namespace tools {
32
33/** T must be a class that extends SvRefBase */
34template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final {
35public:
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();
13
Taking true branch
14
Calling 'SvRefBase::ReleaseRef'
21
Returning; memory was released
25
Taking true branch
26
Use of memory after it is freed
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
104private:
105 T * pObj;
106};
107
108/**
109 * This implements similar functionality to std::make_shared.
110 */
111template<typename T, typename... Args>
112SvRef<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 */
120class 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
128protected:
129 virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE;
130
131public:
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__))
;
15
Assuming field 'nRefCount' is >= 1
16
'?' condition is true
157 if( --nRefCount == 0 && !bNoDelete)
17
Assuming the condition is true
18
Assuming field 'bNoDelete' is 0
19
Taking true branch
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;
20
Memory is released
164 }
165 }
166
167 unsigned int GetRefCount() const
168 { return nRefCount; }
169};
170
171template<typename T>
172class SvCompatWeakBase;
173
174/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T.
175*/
176template<typename T>
177class SvCompatWeakHdl final : public SvRefBase
178{
179 friend class SvCompatWeakBase<T>;
180 T* _pObj;
181
182 SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
183
184public:
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*/
192template<typename T>
193class SvCompatWeakBase
194{
195 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
196
197public:
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*/
210template<typename T>
211class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef
212{
213 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
214public:
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: */