Bug Summary

File:home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx
Warning:line 713, column 35
Forming reference to null pointer

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 AccessibleText.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 SC_DLLIMPLEMENTATION -D SC_INFO_OSVERSION="LINUX" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -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/clew/source/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sc/source/core/inc -I /home/maarten/src/libreoffice/core/sc/source/filter/inc -I /home/maarten/src/libreoffice/core/sc/source/ui/inc -I /home/maarten/src/libreoffice/core/sc/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sc/sdi -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/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/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/sc/source/ui/Accessibility/AccessibleText.cxx

/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.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 <scitems.hxx>
21#include <editeng/eeitem.hxx>
22
23#include <memory>
24#include <AccessibleText.hxx>
25#include <AccessibleCell.hxx>
26#include <attrib.hxx>
27#include <tabvwsh.hxx>
28#include <editutil.hxx>
29#include <document.hxx>
30#include <scmod.hxx>
31#include <prevwsh.hxx>
32#include <docsh.hxx>
33#include <prevloc.hxx>
34#include <patattr.hxx>
35#include <inputwin.hxx>
36#include <editeng/unofored.hxx>
37#include <editeng/editview.hxx>
38#include <editeng/unoedhlp.hxx>
39#include <editeng/fhgtitem.hxx>
40#include <editeng/adjustitem.hxx>
41#include <editeng/justifyitem.hxx>
42#include <svx/svdmodel.hxx>
43#include <svx/algitem.hxx>
44#include <vcl/svapp.hxx>
45
46class ScViewForwarder : public SvxViewForwarder
47{
48 ScTabViewShell* mpViewShell;
49 ScSplitPos meSplitPos;
50public:
51 ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
52
53 virtual bool IsValid() const override;
54 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
55 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
56
57 void SetInvalid();
58};
59
60ScViewForwarder::ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
61 :
62 mpViewShell(pViewShell),
63 meSplitPos(eSplitPos)
64{
65}
66
67bool ScViewForwarder::IsValid() const
68{
69 return mpViewShell != nullptr;
70}
71
72Point ScViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
73{
74 if (mpViewShell)
75 {
76 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
77 if (pWindow)
78 return pWindow->LogicToPixel( rPoint, rMapMode );
79 }
80 else
81 {
82 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "82" ": "), "%s", "this ViewForwarder is not valid"); } }
while (false)
;
83 }
84 return Point();
85}
86
87Point ScViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
88{
89 if (mpViewShell)
90 {
91 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
92 if (pWindow)
93 return pWindow->PixelToLogic( rPoint, rMapMode );
94 }
95 else
96 {
97 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "97" ": "), "%s", "this ViewForwarder is not valid"); } }
while (false)
;
98 }
99 return Point();
100}
101
102void ScViewForwarder::SetInvalid()
103{
104 mpViewShell = nullptr;
105}
106
107class ScEditObjectViewForwarder : public SvxViewForwarder
108{
109 VclPtr<OutputDevice> mpWindow;
110 // #i49561# EditView needed for access to its visible area.
111 const EditView* mpEditView;
112public:
113 ScEditObjectViewForwarder( OutputDevice* pWindow,
114 const EditView* _pEditView);
115
116 virtual bool IsValid() const override;
117 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
118 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
119
120 void SetInvalid();
121};
122
123ScEditObjectViewForwarder::ScEditObjectViewForwarder( OutputDevice* pWindow,
124 const EditView* _pEditView )
125 : mpWindow(pWindow)
126 , mpEditView( _pEditView )
127{
128}
129
130bool ScEditObjectViewForwarder::IsValid() const
131{
132 return (mpWindow != nullptr);
133}
134
135Point ScEditObjectViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
136{
137 if (mpWindow)
138 {
139 // #i49561# - consider offset of the visible area
140 // of the EditView before converting point to pixel.
141 Point aPoint( rPoint );
142 if ( mpEditView )
143 {
144 tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
145 aPoint += aEditViewVisArea.TopLeft();
146 }
147 return mpWindow->LogicToPixel( aPoint, rMapMode );
148 }
149 else
150 {
151 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "151" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
152 }
153 return Point();
154}
155
156Point ScEditObjectViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
157{
158 if (mpWindow)
159 {
160 // #i49561# - consider offset of the visible area
161 // of the EditView after converting point to logic.
162 Point aPoint( mpWindow->PixelToLogic( rPoint, rMapMode ) );
163 if ( mpEditView )
164 {
165 tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
166 aPoint -= aEditViewVisArea.TopLeft();
167 }
168 return aPoint;
169 }
170 else
171 {
172 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "172" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
173 }
174 return Point();
175}
176
177void ScEditObjectViewForwarder::SetInvalid()
178{
179 mpWindow = nullptr;
180}
181
182class ScPreviewViewForwarder : public SvxViewForwarder
183{
184protected:
185 ScPreviewShell* mpViewShell;
186public:
187 explicit ScPreviewViewForwarder(ScPreviewShell* pViewShell);
188
189 virtual bool IsValid() const override;
190 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
191 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
192
193 void SetInvalid();
194};
195
196ScPreviewViewForwarder::ScPreviewViewForwarder(ScPreviewShell* pViewShell)
197 : mpViewShell(pViewShell)
198{
199}
200
201bool ScPreviewViewForwarder::IsValid() const
202{
203 return mpViewShell != nullptr;
204}
205
206Point ScPreviewViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
207{
208 if (mpViewShell)
209 {
210 vcl::Window* pWindow = mpViewShell->GetWindow();
211 if (pWindow)
212 {
213 MapMode aMapMode(pWindow->GetMapMode().GetMapUnit());
214 Point aPoint2( OutputDevice::LogicToLogic( rPoint, rMapMode, aMapMode) );
215 return pWindow->LogicToPixel(aPoint2);
216 }
217 }
218 else
219 {
220 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "220" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
221 }
222 return Point();
223}
224
225Point ScPreviewViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
226{
227 if (mpViewShell)
228 {
229 vcl::Window* pWindow = mpViewShell->GetWindow();
230 if (pWindow)
231 {
232 MapMode aMapMode(pWindow->GetMapMode());
233 aMapMode.SetOrigin(Point());
234 Point aPoint1( pWindow->PixelToLogic( rPoint ) );
235 Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
236 MapMode(aMapMode.GetMapUnit()),
237 rMapMode ) );
238 return aPoint2;
239 }
240 }
241 else
242 {
243 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "243" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
244 }
245 return Point();
246}
247
248void ScPreviewViewForwarder::SetInvalid()
249{
250 mpViewShell = nullptr;
251}
252
253namespace {
254
255class ScPreviewHeaderFooterViewForwarder : public ScPreviewViewForwarder
256{
257public:
258 ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell);
259};
260
261}
262
263ScPreviewHeaderFooterViewForwarder::ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell)
264 :
265 ScPreviewViewForwarder(pViewShell)
266{
267}
268
269namespace {
270
271class ScPreviewCellViewForwarder : public ScPreviewViewForwarder
272{
273public:
274 ScPreviewCellViewForwarder(ScPreviewShell* pViewShell);
275};
276
277}
278
279ScPreviewCellViewForwarder::ScPreviewCellViewForwarder(ScPreviewShell* pViewShell)
280 :
281 ScPreviewViewForwarder(pViewShell)
282{
283}
284
285namespace {
286
287class ScPreviewHeaderCellViewForwarder : public ScPreviewViewForwarder
288{
289public:
290 ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell);
291};
292
293}
294
295ScPreviewHeaderCellViewForwarder::ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell)
296 :
297 ScPreviewViewForwarder(pViewShell)
298{
299}
300
301namespace {
302
303class ScPreviewNoteViewForwarder : public ScPreviewViewForwarder
304{
305public:
306 ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell);
307};
308
309}
310
311ScPreviewNoteViewForwarder::ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell)
312 :
313 ScPreviewViewForwarder(pViewShell)
314{
315}
316
317class ScEditViewForwarder : public SvxEditViewForwarder
318{
319 EditView* mpEditView;
320 VclPtr<OutputDevice> mpWindow;
321public:
322 ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin);
323
324 virtual bool IsValid() const override;
325 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
326 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
327 virtual bool GetSelection( ESelection& rSelection ) const override;
328 virtual bool SetSelection( const ESelection& rSelection ) override;
329 virtual bool Copy() override;
330 virtual bool Cut() override;
331 virtual bool Paste() override;
332
333 void SetInvalid();
334};
335
336ScEditViewForwarder::ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin)
337 : mpEditView(pEditView)
338 , mpWindow(pWin)
339{
340}
341
342bool ScEditViewForwarder::IsValid() const
343{
344 return mpWindow && mpEditView;
345}
346
347Point ScEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
348{
349 if (mpWindow)
350 return mpWindow->LogicToPixel( rPoint, rMapMode );
351 else
352 {
353 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "353" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
354 }
355 return Point();
356}
357
358Point ScEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
359{
360 if (mpWindow)
361 return mpWindow->PixelToLogic( rPoint, rMapMode );
362 else
363 {
364 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "364" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
365 }
366 return Point();
367}
368
369bool ScEditViewForwarder::GetSelection( ESelection& rSelection ) const
370{
371 bool bResult(false);
372 if (IsValid())
373 {
374 rSelection = mpEditView->GetSelection();
375 bResult = true;
376 }
377 else
378 {
379 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "379" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
380 }
381 return bResult;
382}
383
384bool ScEditViewForwarder::SetSelection( const ESelection& rSelection )
385{
386 bool bResult(false);
387 if (IsValid())
388 {
389 mpEditView->SetSelection(rSelection);
390 bResult = true;
391 }
392 else
393 {
394 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "394" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
395 }
396 return bResult;
397}
398
399bool ScEditViewForwarder::Copy()
400{
401 bool bResult(false);
402 if (IsValid())
403 {
404 mpEditView->Copy();
405 bResult = true;
406 }
407 else
408 {
409 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "409" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
410 }
411 return bResult;
412}
413
414bool ScEditViewForwarder::Cut()
415{
416 bool bResult(false);
417 if (IsValid())
418 {
419 mpEditView->Cut();
420 bResult = true;
421 }
422 else
423 {
424 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "424" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
425 }
426 return bResult;
427}
428
429bool ScEditViewForwarder::Paste()
430{
431 bool bResult(false);
432 if (IsValid())
433 {
434 mpEditView->Paste();
435 bResult = true;
436 }
437 else
438 {
439 OSL_FAIL("this ViewForwarder is not valid")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
":" "439" ": "), "%s", "this ViewForwarder is not valid"); }
} while (false)
;
440 }
441 return bResult;
442}
443
444void ScEditViewForwarder::SetInvalid()
445{
446 mpWindow = nullptr;
447 mpEditView = nullptr;
448}
449
450// ScAccessibleCellTextData: shared data between sub objects of an accessible cell text object
451
452ScAccessibleCellTextData::ScAccessibleCellTextData(ScTabViewShell* pViewShell,
453 const ScAddress& rP, ScSplitPos eSplitPos, ScAccessibleCell* pAccCell)
454 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
455 mpViewShell(pViewShell),
456 meSplitPos(eSplitPos),
457 mpAccessibleCell( pAccCell )
458{
459}
460
461ScAccessibleCellTextData::~ScAccessibleCellTextData()
462{
463 if (pEditEngine)
464 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
465 mpViewForwarder.reset();
466}
467
468void ScAccessibleCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
469{
470 if ( rHint.GetId() == SfxHintId::Dying )
471 {
472 mpViewShell = nullptr; // invalid now
473 if (mpViewForwarder)
474 mpViewForwarder->SetInvalid();
475 }
476 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
477}
478
479ScAccessibleTextData* ScAccessibleCellTextData::Clone() const
480{
481 return new ScAccessibleCellTextData( mpViewShell, aCellPos, meSplitPos, mpAccessibleCell );
482}
483
484SvxTextForwarder* ScAccessibleCellTextData::GetTextForwarder()
485{
486 ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
487
488 if ( pDocShell && pEditEngine && mpViewShell )
489 {
490 ScDocument& rDoc = pDocShell->GetDocument();
491 long nSizeX, nSizeY;
492 mpViewShell->GetViewData().GetMergeSizePixel(
493 aCellPos.Col(), aCellPos.Row(), nSizeX, nSizeY);
494
495 Size aSize(nSizeX, nSizeY);
496
497 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
498 long nIndent = 0;
499 const SvxHorJustifyItem* pHorJustifyItem = rDoc.GetAttr( aCellPos, ATTR_HOR_JUSTIFY );
500 SvxCellHorJustify eHorJust = pHorJustifyItem ? pHorJustifyItem->GetValue() : SvxCellHorJustify::Standard;
501 if ( eHorJust == SvxCellHorJustify::Left )
502 {
503 const ScIndentItem* pIndentItem = rDoc.GetAttr( aCellPos, ATTR_INDENT );
504 if ( pIndentItem )
505 {
506 nIndent = static_cast< long >( pIndentItem->GetValue() );
507 }
508 }
509
510 const SvxMarginItem* pMarginItem = rDoc.GetAttr( aCellPos, ATTR_MARGIN );
511 ScViewData& rViewData = mpViewShell->GetViewData();
512 double nPPTX = rViewData.GetPPTX();
513 double nPPTY = rViewData.GetPPTY();
514 long nLeftM = ( pMarginItem ? static_cast< long >( ( pMarginItem->GetLeftMargin() + nIndent ) * nPPTX ) : 0 );
515 long nTopM = ( pMarginItem ? static_cast< long >( pMarginItem->GetTopMargin() * nPPTY ) : 0 );
516 long nRightM = ( pMarginItem ? static_cast< long >( pMarginItem->GetRightMargin() * nPPTX ) : 0 );
517 long nBottomM = ( pMarginItem ? static_cast< long >( pMarginItem->GetBottomMargin() * nPPTY ) : 0 );
518 long nWidth = aSize.getWidth() - nLeftM - nRightM;
519 aSize.setWidth( nWidth );
520 aSize.setHeight( aSize.getHeight() - nTopM - nBottomM );
521
522 vcl::Window* pWin = mpViewShell->GetWindowByPos( meSplitPos );
523 if ( pWin )
524 {
525 aSize = pWin->PixelToLogic( aSize, pEditEngine->GetRefMapMode() );
526 }
527
528 /* #i19430# Gnopernicus reads text partly if it sticks out of the cell
529 boundaries. This leads to wrong results in cases where the cell text
530 is rotated, because rotation is not taken into account when calcu-
531 lating the visible part of the text. In these cases we will expand
532 the cell size passed as paper size to the edit engine. The function
533 accessibility::AccessibleStaticTextBase::GetParagraphBoundingBox()
534 (see svx/source/accessibility/AccessibleStaticTextBase.cxx) will
535 return the size of the complete text then, which is used to expand
536 the cell bounding box in ScAccessibleCell::GetBoundingBox()
537 (see sc/source/ui/Accessibility/AccessibleCell.cxx). */
538 const ScRotateValueItem* pItem = rDoc.GetAttr( aCellPos, ATTR_ROTATE_VALUE );
539 if( pItem && (pItem->GetValue() != 0) )
540 {
541 pEditEngine->SetPaperSize( Size( LONG_MAX9223372036854775807L, aSize.getHeight() ) );
542 long nTxtWidth = static_cast< long >( pEditEngine->CalcTextWidth() );
543 aSize.setWidth( std::max( aSize.getWidth(), nTxtWidth + 2 ) );
544 }
545 else
546 {
547 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
548 const ScLineBreakCell* pLineBreakItem = rDoc.GetAttr( aCellPos, ATTR_LINEBREAK );
549 bool bLineBreak = ( pLineBreakItem && pLineBreakItem->GetValue() );
550 if ( !bLineBreak )
551 {
552 long nTxtWidth = static_cast< long >( pEditEngine->CalcTextWidth() );
553 aSize.setWidth( ::std::max( aSize.getWidth(), nTxtWidth ) );
554 }
555 }
556
557 pEditEngine->SetPaperSize( aSize );
558
559 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
560 if ( eHorJust == SvxCellHorJustify::Standard && rDoc.HasValueData( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
561 {
562 pEditEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
563 }
564
565 Size aTextSize;
566 if ( pWin )
567 {
568 aTextSize = pWin->LogicToPixel( Size( pEditEngine->CalcTextWidth(), pEditEngine->GetTextHeight() ), pEditEngine->GetRefMapMode() );
569 }
570 long nTextWidth = aTextSize.Width();
571 long nTextHeight = aTextSize.Height();
572
573 long nOffsetX = nLeftM;
574 long nDiffX = nTextWidth - nWidth;
575 if ( nDiffX > 0 )
576 {
577 switch ( eHorJust )
578 {
579 case SvxCellHorJustify::Right:
580 {
581 nOffsetX -= nDiffX;
582 }
583 break;
584 case SvxCellHorJustify::Center:
585 {
586 nOffsetX -= nDiffX / 2;
587 }
588 break;
589 default:
590 {
591 }
592 break;
593 }
594 }
595
596 long nOffsetY = 0;
597 const SvxVerJustifyItem* pVerJustifyItem = rDoc.GetAttr( aCellPos, ATTR_VER_JUSTIFY );
598 SvxCellVerJustify eVerJust = ( pVerJustifyItem ? pVerJustifyItem->GetValue() : SvxCellVerJustify::Standard );
599 switch ( eVerJust )
600 {
601 case SvxCellVerJustify::Standard:
602 case SvxCellVerJustify::Bottom:
603 {
604 nOffsetY = nSizeY - nBottomM - nTextHeight;
605 }
606 break;
607 case SvxCellVerJustify::Center:
608 {
609 nOffsetY = ( nSizeY - nTopM - nBottomM - nTextHeight ) / 2 + nTopM;
610 }
611 break;
612 default:
613 {
614 nOffsetY = nTopM;
615 }
616 break;
617 }
618
619 if ( mpAccessibleCell )
620 {
621 mpAccessibleCell->SetOffset( Point( nOffsetX, nOffsetY ) );
622 }
623
624 pEditEngine->SetNotifyHdl( LINK(this, ScAccessibleCellTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessibleCellTextData
*>(this), &ScAccessibleCellTextData::LinkStubNotifyHdl
)
);
625 }
626
627 return pForwarder.get();
628}
629
630SvxViewForwarder* ScAccessibleCellTextData::GetViewForwarder()
631{
632 if (!mpViewForwarder)
633 mpViewForwarder.reset(new ScViewForwarder(mpViewShell, meSplitPos));
634 return mpViewForwarder.get();
635}
636
637SvxEditViewForwarder* ScAccessibleCellTextData::GetEditViewForwarder( bool /* bCreate */ )
638{
639 //#102219#; there should no EditViewForwarder be, because the cell is now readonly in this interface
640 return nullptr;
641}
642
643IMPL_LINK(ScAccessibleTextData, NotifyHdl, EENotify&, aNotify, void)void ScAccessibleTextData::LinkStubNotifyHdl(void * instance,
EENotify& data) { return static_cast<ScAccessibleTextData
*>(instance)->NotifyHdl(data); } void ScAccessibleTextData
::NotifyHdl(EENotify& aNotify)
644{
645 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &aNotify );
646
647 if (aHint)
648 GetBroadcaster().Broadcast(*aHint);
649}
650
651ScDocShell* ScAccessibleCellTextData::GetDocShell(ScTabViewShell* pViewShell)
652{
653 ScDocShell* pDocSh = nullptr;
654 if (pViewShell)
655 pDocSh = pViewShell->GetViewData().GetDocShell();
656 return pDocSh;
657}
658
659ScAccessibleEditObjectTextData::ScAccessibleEditObjectTextData(EditView* pEditView, OutputDevice* pWin, bool isClone)
660 :
661 mpEditView(pEditView),
662 mpEditEngine(pEditView ? pEditView->GetEditEngine() : nullptr),
663 mpWindow(pWin)
664{
665 // If the object is cloned, do NOT add notify hdl.
666 mbIsCloned = isClone;
667 if (mpEditEngine && !mbIsCloned)
668 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessibleEditObjectTextData
*>(this), &ScAccessibleEditObjectTextData::LinkStubNotifyHdl
)
);
669}
670
671ScAccessibleEditObjectTextData::~ScAccessibleEditObjectTextData()
672{
673 // If the object is cloned, do NOT set notify hdl.
674 if (mpEditEngine && !mbIsCloned)
675 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
676 mpViewForwarder.reset();
677 mpEditViewForwarder.reset();
678 mpForwarder.reset();
679}
680
681void ScAccessibleEditObjectTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
682{
683 if ( rHint.GetId() == SfxHintId::Dying )
684 {
685 mpWindow = nullptr;
686 mpEditView = nullptr;
687 mpEditEngine = nullptr;
688 mpForwarder.reset();
689 if (mpViewForwarder)
690 mpViewForwarder->SetInvalid();
691 if (mpEditViewForwarder)
692 mpEditViewForwarder->SetInvalid();
693 }
694 ScAccessibleTextData::Notify(rBC, rHint);
695}
696
697ScAccessibleTextData* ScAccessibleEditObjectTextData::Clone() const
698{
699 // Add para to indicate the object is cloned
700 return new ScAccessibleEditObjectTextData(mpEditView, mpWindow, true);
701}
702
703SvxTextForwarder* ScAccessibleEditObjectTextData::GetTextForwarder()
704{
705 if ((!mpForwarder && mpEditView) || (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()))
7
Calling 'unique_ptr::operator bool'
11
Returning from 'unique_ptr::operator bool'
12
Assuming field 'mpEditView' is non-null
706 {
707 if (!mpEditEngine)
13
Assuming field 'mpEditEngine' is null
14
Taking true branch
708 mpEditEngine = mpEditView->GetEditEngine();
15
Value assigned to field 'mpEditEngine'
709 // If the object is cloned, do NOT add notify hdl.
710 if (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()&&!mbIsCloned)
16
Assuming field 'mpEditEngine' is null
711 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessibleEditObjectTextData
*>(this), &ScAccessibleEditObjectTextData::LinkStubNotifyHdl
)
);
712 if(!mpForwarder)
17
Calling 'unique_ptr::operator bool'
20
Returning from 'unique_ptr::operator bool'
21
Taking true branch
713 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
22
Forming reference to null pointer
714 }
715 return mpForwarder.get();
716}
717
718SvxViewForwarder* ScAccessibleEditObjectTextData::GetViewForwarder()
719{
720 if (!mpViewForwarder)
721 {
722 // i#49561 Get right-aligned cell content to be read by screenreader.
723 mpViewForwarder.reset(new ScEditObjectViewForwarder( mpWindow, mpEditView ));
724 }
725 return mpViewForwarder.get();
726}
727
728SvxEditViewForwarder* ScAccessibleEditObjectTextData::GetEditViewForwarder( bool bCreate )
729{
730 if (!mpEditViewForwarder && mpEditView)
731 mpEditViewForwarder.reset(new ScEditViewForwarder(mpEditView, mpWindow));
732 if (bCreate)
733 {
734 if (!mpEditView && mpEditViewForwarder)
735 {
736 mpEditViewForwarder.reset();
737 }
738 }
739 return mpEditViewForwarder.get();
740}
741
742IMPL_LINK(ScAccessibleEditObjectTextData, NotifyHdl, EENotify&, rNotify, void)void ScAccessibleEditObjectTextData::LinkStubNotifyHdl(void *
instance, EENotify& data) { return static_cast<ScAccessibleEditObjectTextData
*>(instance)->NotifyHdl(data); } void ScAccessibleEditObjectTextData
::NotifyHdl(EENotify& rNotify)
743{
744 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &rNotify );
745
746 if (aHint)
747 GetBroadcaster().Broadcast(*aHint);
748}
749
750ScAccessibleEditLineTextData::ScAccessibleEditLineTextData(EditView* pEditView, OutputDevice* pWin)
751 :
752 ScAccessibleEditObjectTextData(pEditView, pWin),
753 mbEditEngineCreated(false)
754{
755 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>( pWin );
756
757 if (pTxtWnd)
758 pTxtWnd->InsertAccessibleTextData( *this );
759}
760
761ScAccessibleEditLineTextData::~ScAccessibleEditLineTextData()
762{
763 ScTextWnd* pTxtWnd = dynamic_cast< ScTextWnd* >(mpWindow.get());
764
765 if (pTxtWnd)
766 {
767 assert(!pTxtWnd->IsDisposed())(static_cast <bool> (!pTxtWnd->IsDisposed()) ? void (
0) : __assert_fail ("!pTxtWnd->IsDisposed()", "/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
, 767, __extension__ __PRETTY_FUNCTION__))
;
768 pTxtWnd->RemoveAccessibleTextData( *this );
769 }
770
771 if (mbEditEngineCreated && mpEditEngine)
772 {
773 delete mpEditEngine;
774 mpEditEngine = nullptr; // don't access in ScAccessibleEditObjectTextData dtor!
775 }
776 else if (pTxtWnd && pTxtWnd->HasEditView() && pTxtWnd->GetEditView()->GetEditEngine())
777 {
778 // the NotifyHdl also has to be removed from the ScTextWnd's EditEngine
779 // (it's set in ScAccessibleEditLineTextData::GetTextForwarder, and mpEditEngine
780 // is reset there)
781 pTxtWnd->GetEditView()->GetEditEngine()->SetNotifyHdl(Link<EENotify&,void>());
782 }
783}
784
785void ScAccessibleEditLineTextData::Dispose()
786{
787 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
788
789 if (pTxtWnd)
790 {
791 assert(!pTxtWnd->IsDisposed())(static_cast <bool> (!pTxtWnd->IsDisposed()) ? void (
0) : __assert_fail ("!pTxtWnd->IsDisposed()", "/home/maarten/src/libreoffice/core/sc/source/ui/Accessibility/AccessibleText.cxx"
, 791, __extension__ __PRETTY_FUNCTION__))
;
792 pTxtWnd->RemoveAccessibleTextData( *this );
793 }
794
795 ResetEditMode();
796 mpWindow = nullptr;
797}
798
799ScAccessibleTextData* ScAccessibleEditLineTextData::Clone() const
800{
801 return new ScAccessibleEditLineTextData(mpEditView, mpWindow);
802}
803
804SvxTextForwarder* ScAccessibleEditLineTextData::GetTextForwarder()
805{
806 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
807
808 if (pTxtWnd)
1
Assuming 'pTxtWnd' is non-null
2
Taking true branch
809 {
810 if (pTxtWnd->HasEditView())
3
Assuming the condition is true
4
Taking true branch
811 {
812 mpEditView = pTxtWnd->GetEditView();
813
814 if (mbEditEngineCreated && mpEditEngine)
5
Assuming field 'mbEditEngineCreated' is false
815 ResetEditMode();
816 mbEditEngineCreated = false;
817
818 mpEditView = pTxtWnd->GetEditView();
819 ScAccessibleEditObjectTextData::GetTextForwarder(); // fill the mpForwarder
6
Calling 'ScAccessibleEditObjectTextData::GetTextForwarder'
820 mpEditEngine = nullptr;
821 }
822 else
823 {
824 mpEditView = nullptr;
825
826 if (mpEditEngine && !mbEditEngineCreated)
827 ResetEditMode();
828 if (!mpEditEngine)
829 {
830 SfxItemPool* pEnginePool = EditEngine::CreatePool();
831 pEnginePool->FreezeIdRanges();
832 mpEditEngine = new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true);
833 mbEditEngineCreated = true;
834 mpEditEngine->EnableUndo( false );
835 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
836 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
837
838 mpEditEngine->SetText(pTxtWnd->GetTextString());
839
840 Size aSize(pTxtWnd->GetSizePixel());
841
842 aSize = pTxtWnd->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
843
844 mpEditEngine->SetPaperSize(aSize);
845
846 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessibleEditObjectTextData
*>(this), &ScAccessibleEditObjectTextData::LinkStubNotifyHdl
)
);
847 }
848 }
849 }
850 return mpForwarder.get();
851}
852
853SvxEditViewForwarder* ScAccessibleEditLineTextData::GetEditViewForwarder( bool bCreate )
854{
855 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
856
857 if (pTxtWnd)
858 {
859 if (!pTxtWnd->HasEditView() && bCreate)
860 {
861 if ( !pTxtWnd->IsInputActive() )
862 {
863 pTxtWnd->StartEditEngine();
864 pTxtWnd->GrabFocus();
865
866 mpEditView = pTxtWnd->GetEditView();
867 }
868 }
869 }
870
871 return ScAccessibleEditObjectTextData::GetEditViewForwarder(bCreate);
872}
873
874void ScAccessibleEditLineTextData::ResetEditMode()
875{
876 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
877
878 if (mbEditEngineCreated && mpEditEngine)
879 delete mpEditEngine;
880 else if (pTxtWnd && pTxtWnd->HasEditView() && pTxtWnd->GetEditView()->GetEditEngine())
881 pTxtWnd->GetEditView()->GetEditEngine()->SetNotifyHdl(Link<EENotify&,void>());
882 mpEditEngine = nullptr;
883
884 mpForwarder.reset();
885 mpEditViewForwarder.reset();
886 mpViewForwarder.reset();
887 mbEditEngineCreated = false;
888}
889
890void ScAccessibleEditLineTextData::TextChanged()
891{
892 if (mbEditEngineCreated && mpEditEngine)
893 {
894 ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
895
896 if (pTxtWnd)
897 mpEditEngine->SetText(pTxtWnd->GetTextString());
898 }
899}
900
901void ScAccessibleEditLineTextData::StartEdit()
902{
903 ResetEditMode();
904 mpEditView = nullptr;
905
906 // send SdrHintKind::BeginEdit
907 SdrHint aHint(SdrHintKind::BeginEdit);
908 GetBroadcaster().Broadcast( aHint );
909}
910
911void ScAccessibleEditLineTextData::EndEdit()
912{
913 // send SdrHintKind::EndEdit
914 SdrHint aHint(SdrHintKind::EndEdit);
915 GetBroadcaster().Broadcast( aHint );
916
917 ResetEditMode();
918 mpEditView = nullptr;
919}
920
921// ScAccessiblePreviewCellTextData: shared data between sub objects of an accessible cell text object
922
923ScAccessiblePreviewCellTextData::ScAccessiblePreviewCellTextData(ScPreviewShell* pViewShell,
924 const ScAddress& rP)
925 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
926 mpViewShell(pViewShell)
927{
928}
929
930ScAccessiblePreviewCellTextData::~ScAccessiblePreviewCellTextData()
931{
932 if (pEditEngine)
933 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
934 mpViewForwarder.reset();
935}
936
937void ScAccessiblePreviewCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
938{
939 if ( rHint.GetId() == SfxHintId::Dying )
940 {
941 mpViewShell = nullptr; // invalid now
942 if (mpViewForwarder)
943 mpViewForwarder->SetInvalid();
944 }
945 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
946}
947
948ScAccessibleTextData* ScAccessiblePreviewCellTextData::Clone() const
949{
950 return new ScAccessiblePreviewCellTextData(mpViewShell, aCellPos);
951}
952
953SvxTextForwarder* ScAccessiblePreviewCellTextData::GetTextForwarder()
954{
955 bool bEditEngineBefore(pEditEngine != nullptr);
956
957 ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
958
959 if (!bEditEngineBefore && pEditEngine)
960 {
961 Size aSize(mpViewShell->GetLocationData().GetCellOutputRect(aCellPos).GetSize());
962 vcl::Window* pWin = mpViewShell->GetWindow();
963 if (pWin)
964 aSize = pWin->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
965 pEditEngine->SetPaperSize(aSize);
966 }
967
968 if (pEditEngine)
969 pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewCellTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessiblePreviewCellTextData
*>(this), &ScAccessiblePreviewCellTextData::LinkStubNotifyHdl
)
);
970
971 return pForwarder.get();
972}
973
974SvxViewForwarder* ScAccessiblePreviewCellTextData::GetViewForwarder()
975{
976 if (!mpViewForwarder)
977 mpViewForwarder.reset(new ScPreviewCellViewForwarder(mpViewShell));
978 return mpViewForwarder.get();
979}
980
981ScDocShell* ScAccessiblePreviewCellTextData::GetDocShell(ScPreviewShell* pViewShell)
982{
983 ScDocShell* pDocSh = nullptr;
984 if (pViewShell)
985 pDocSh = static_cast<ScDocShell*>( pViewShell->GetDocument().GetDocumentShell());
986 return pDocSh;
987}
988
989// ScAccessiblePreviewHeaderCellTextData: shared data between sub objects of an accessible cell text object
990
991ScAccessiblePreviewHeaderCellTextData::ScAccessiblePreviewHeaderCellTextData(ScPreviewShell* pViewShell,
992 const OUString& rText, const ScAddress& rP, bool bColHeader, bool bRowHeader)
993 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
994 mpViewShell(pViewShell),
995 maText(rText),
996 mbColHeader(bColHeader),
997 mbRowHeader(bRowHeader)
998{
999}
1000
1001ScAccessiblePreviewHeaderCellTextData::~ScAccessiblePreviewHeaderCellTextData()
1002{
1003 if (pEditEngine)
1004 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
1005 mpViewForwarder.reset();
1006}
1007
1008void ScAccessiblePreviewHeaderCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1009{
1010 if ( rHint.GetId() == SfxHintId::Dying )
1011 {
1012 mpViewShell = nullptr; // invalid now
1013 if (mpViewForwarder)
1014 mpViewForwarder->SetInvalid();
1015 }
1016 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
1017}
1018
1019ScAccessibleTextData* ScAccessiblePreviewHeaderCellTextData::Clone() const
1020{
1021 return new ScAccessiblePreviewHeaderCellTextData(mpViewShell, maText, aCellPos, mbColHeader, mbRowHeader);
1022}
1023
1024SvxTextForwarder* ScAccessiblePreviewHeaderCellTextData::GetTextForwarder()
1025{
1026 if (!pEditEngine)
1027 {
1028 if ( pDocShell )
1029 {
1030 ScDocument& rDoc = pDocShell->GetDocument();
1031 pEditEngine = rDoc.CreateFieldEditEngine();
1032 }
1033 else
1034 {
1035 SfxItemPool* pEnginePool = EditEngine::CreatePool();
1036 pEnginePool->FreezeIdRanges();
1037 pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );
1038 }
1039 pEditEngine->EnableUndo( false );
1040 if (pDocShell)
1041 pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
1042 else
1043 pEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
1044 pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) );
1045 }
1046
1047 if (bDataValid)
1048 return pForwarder.get();
1049
1050 if (!maText.isEmpty())
1051 {
1052 if ( mpViewShell )
1053 {
1054 Size aOutputSize;
1055 vcl::Window* pWindow = mpViewShell->GetWindow();
1056 if ( pWindow )
1057 aOutputSize = pWindow->GetOutputSizePixel();
1058 tools::Rectangle aVisRect( Point(), aOutputSize );
1059 Size aSize(mpViewShell->GetLocationData().GetHeaderCellOutputRect(aVisRect, aCellPos, mbColHeader).GetSize());
1060 if (pWindow)
1061 aSize = pWindow->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
1062 pEditEngine->SetPaperSize(aSize);
1063 }
1064 pEditEngine->SetTextCurrentDefaults( maText );
1065 }
1066
1067 bDataValid = true;
1068
1069 pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewHeaderCellTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessiblePreviewHeaderCellTextData
*>(this), &ScAccessiblePreviewHeaderCellTextData::LinkStubNotifyHdl
)
);
1070
1071 return pForwarder.get();
1072}
1073
1074SvxViewForwarder* ScAccessiblePreviewHeaderCellTextData::GetViewForwarder()
1075{
1076 if (!mpViewForwarder)
1077 mpViewForwarder.reset(new ScPreviewHeaderCellViewForwarder(mpViewShell));
1078 return mpViewForwarder.get();
1079}
1080
1081ScDocShell* ScAccessiblePreviewHeaderCellTextData::GetDocShell(ScPreviewShell* pViewShell)
1082{
1083 ScDocShell* pDocSh = nullptr;
1084 if (pViewShell)
1085 pDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
1086 return pDocSh;
1087}
1088
1089ScAccessibleHeaderTextData::ScAccessibleHeaderTextData(ScPreviewShell* pViewShell,
1090 const EditTextObject* pEditObj, SvxAdjust eAdjust)
1091 :
1092 mpViewForwarder(nullptr),
1093 mpViewShell(pViewShell),
1094 mpDocSh(nullptr),
1095 mpEditObj(pEditObj),
1096 mbDataValid(false),
1097 meAdjust(eAdjust)
1098{
1099 if (pViewShell)
1100 mpDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
1101 if (mpDocSh)
1102 mpDocSh->GetDocument().AddUnoObject(*this);
1103}
1104
1105ScAccessibleHeaderTextData::~ScAccessibleHeaderTextData()
1106{
1107 SolarMutexGuard aGuard; // needed for EditEngine dtor
1108
1109 if (mpDocSh)
1110 mpDocSh->GetDocument().RemoveUnoObject(*this);
1111 if (mpEditEngine)
1112 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
1113 mpEditEngine.reset();
1114 mpForwarder.reset();
1115}
1116
1117ScAccessibleTextData* ScAccessibleHeaderTextData::Clone() const
1118{
1119 return new ScAccessibleHeaderTextData(mpViewShell, mpEditObj, meAdjust);
1120}
1121
1122void ScAccessibleHeaderTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1123{
1124 if ( rHint.GetId() == SfxHintId::Dying )
1125 {
1126 mpViewShell = nullptr;// invalid now
1127 mpDocSh = nullptr;
1128 if (mpViewForwarder)
1129 mpViewForwarder->SetInvalid();
1130 }
1131}
1132
1133SvxTextForwarder* ScAccessibleHeaderTextData::GetTextForwarder()
1134{
1135 if (!mpEditEngine)
1136 {
1137 SfxItemPool* pEnginePool = EditEngine::CreatePool();
1138 pEnginePool->FreezeIdRanges();
1139 std::unique_ptr<ScHeaderEditEngine> pHdrEngine(new ScHeaderEditEngine( pEnginePool ));
1140
1141 pHdrEngine->EnableUndo( false );
1142 pHdrEngine->SetRefMapMode(MapMode(MapUnit::MapTwip));
1143
1144 // default font must be set, independently of document
1145 // -> use global pool from module
1146
1147 SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
1148 const ScPatternAttr& rPattern = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule
::Calc)) )
->GetPool().GetDefaultItem(ATTR_PATTERN);
1149 rPattern.FillEditItemSet( &aDefaults );
1150 // FillEditItemSet adjusts font height to 1/100th mm,
1151 // but for header/footer twips is needed, as in the PatternAttr:
1152 aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
1153 aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) );
1154 aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
1155 aDefaults.Put( SvxAdjustItem( meAdjust, EE_PARA_JUST ) );
1156 pHdrEngine->SetDefaults( aDefaults );
1157
1158 ScHeaderFieldData aData;
1159 if (mpViewShell)
1160 mpViewShell->FillFieldData(aData);
1161 else
1162 ScHeaderFooterTextObj::FillDummyFieldData( aData );
1163 pHdrEngine->SetData( aData );
1164
1165 mpEditEngine = std::move(pHdrEngine);
1166 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
1167 }
1168
1169 if (mbDataValid)
1170 return mpForwarder.get();
1171
1172 if ( mpViewShell )
1173 {
1174 tools::Rectangle aVisRect;
1175 mpViewShell->GetLocationData().GetHeaderPosition(aVisRect);
1176 Size aSize(aVisRect.GetSize());
1177 vcl::Window* pWin = mpViewShell->GetWindow();
1178 if (pWin)
1179 aSize = pWin->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
1180 mpEditEngine->SetPaperSize(aSize);
1181 }
1182 if (mpEditObj)
1183 mpEditEngine->SetTextCurrentDefaults(*mpEditObj);
1184
1185 mbDataValid = true;
1186 return mpForwarder.get();
1187}
1188
1189SvxViewForwarder* ScAccessibleHeaderTextData::GetViewForwarder()
1190{
1191 if (!mpViewForwarder)
1192 mpViewForwarder = new ScPreviewHeaderFooterViewForwarder(mpViewShell);
1193 return mpViewForwarder;
1194}
1195
1196ScAccessibleNoteTextData::ScAccessibleNoteTextData(ScPreviewShell* pViewShell,
1197 const OUString& sText, const ScAddress& aCellPos, bool bMarkNote)
1198 :
1199 mpViewForwarder(nullptr),
1200 mpViewShell(pViewShell),
1201 mpDocSh(nullptr),
1202 msText(sText),
1203 maCellPos(aCellPos),
1204 mbMarkNote(bMarkNote),
1205 mbDataValid(false)
1206{
1207 if (pViewShell)
1208 mpDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
1209 if (mpDocSh)
1210 mpDocSh->GetDocument().AddUnoObject(*this);
1211}
1212
1213ScAccessibleNoteTextData::~ScAccessibleNoteTextData()
1214{
1215 SolarMutexGuard aGuard; // needed for EditEngine dtor
1216
1217 if (mpDocSh)
1218 mpDocSh->GetDocument().RemoveUnoObject(*this);
1219 if (mpEditEngine)
1220 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
1221 mpEditEngine.reset();
1222 mpForwarder.reset();
1223}
1224
1225ScAccessibleTextData* ScAccessibleNoteTextData::Clone() const
1226{
1227 return new ScAccessibleNoteTextData(mpViewShell, msText, maCellPos, mbMarkNote);
1228}
1229
1230void ScAccessibleNoteTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1231{
1232 if ( rHint.GetId() == SfxHintId::Dying )
1233 {
1234 mpViewShell = nullptr;// invalid now
1235 mpDocSh = nullptr;
1236 if (mpViewForwarder)
1237 mpViewForwarder->SetInvalid();
1238 }
1239}
1240
1241SvxTextForwarder* ScAccessibleNoteTextData::GetTextForwarder()
1242{
1243 if (!mpEditEngine)
1244 {
1245 if ( mpDocSh )
1246 {
1247 ScDocument& rDoc = mpDocSh->GetDocument();
1248 mpEditEngine = rDoc.CreateFieldEditEngine();
1249 }
1250 else
1251 {
1252 SfxItemPool* pEnginePool = EditEngine::CreatePool();
1253 pEnginePool->FreezeIdRanges();
1254 mpEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );
1255 }
1256 mpEditEngine->EnableUndo( false );
1257 if (mpDocSh)
1258 mpEditEngine->SetRefDevice(mpDocSh->GetRefDevice());
1259 else
1260 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
1261 mpForwarder.reset( new SvxEditEngineForwarder(*mpEditEngine) );
1262 }
1263
1264 if (mbDataValid)
1265 return mpForwarder.get();
1266
1267 if (!msText.isEmpty())
1268 {
1269
1270 if ( mpViewShell )
1271 {
1272 Size aOutputSize;
1273 vcl::Window* pWindow = mpViewShell->GetWindow();
1274 if ( pWindow )
1275 aOutputSize = pWindow->GetOutputSizePixel();
1276 tools::Rectangle aVisRect( Point(), aOutputSize );
1277 Size aSize(mpViewShell->GetLocationData().GetNoteInRangeOutputRect(aVisRect, mbMarkNote, maCellPos).GetSize());
1278 if (pWindow)
1279 aSize = pWindow->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
1280 mpEditEngine->SetPaperSize(aSize);
1281 }
1282 mpEditEngine->SetTextCurrentDefaults( msText );
1283 }
1284
1285 mbDataValid = true;
1286
1287 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleNoteTextData, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScAccessibleNoteTextData
*>(this), &ScAccessibleNoteTextData::LinkStubNotifyHdl
)
);
1288
1289 return mpForwarder.get();
1290}
1291
1292SvxViewForwarder* ScAccessibleNoteTextData::GetViewForwarder()
1293{
1294 if (!mpViewForwarder)
1295 mpViewForwarder = new ScPreviewNoteViewForwarder(mpViewShell);
1296 return mpViewForwarder;
1297}
1298
1299// CSV import =================================================================
1300
1301class ScCsvViewForwarder : public SvxViewForwarder
1302{
1303 VclPtr<OutputDevice> mpWindow;
1304
1305public:
1306 explicit ScCsvViewForwarder( OutputDevice* pWindow );
1307
1308 virtual bool IsValid() const override;
1309 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
1310 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
1311
1312 void SetInvalid();
1313};
1314
1315ScCsvViewForwarder::ScCsvViewForwarder( OutputDevice* pWindow ) :
1316 mpWindow( pWindow )
1317{
1318}
1319
1320bool ScCsvViewForwarder::IsValid() const
1321{
1322 return mpWindow != nullptr;
1323}
1324
1325Point ScCsvViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1326{
1327 if( !mpWindow ) return Point();
1328 return mpWindow->LogicToPixel( rPoint, rMapMode );
1329}
1330
1331Point ScCsvViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1332{
1333 if( !mpWindow ) return Point();
1334 return mpWindow->PixelToLogic( rPoint, rMapMode );
1335}
1336
1337void ScCsvViewForwarder::SetInvalid()
1338{
1339 mpWindow = nullptr;
1340}
1341
1342ScAccessibleCsvTextData::ScAccessibleCsvTextData(
1343 OutputDevice* pWindow, EditEngine* pEditEngine,
1344 const OUString& rCellText, const Size& rCellSize ) :
1345 mpWindow( pWindow ),
1346 mpEditEngine( pEditEngine ),
1347 maCellText( rCellText ),
1348 maCellSize( rCellSize )
1349{
1350}
1351
1352ScAccessibleCsvTextData::~ScAccessibleCsvTextData()
1353{
1354}
1355
1356void ScAccessibleCsvTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1357{
1358 if ( rHint.GetId() == SfxHintId::Dying )
1359 {
1360 mpWindow = nullptr;
1361 mpEditEngine = nullptr;
1362 if (mpViewForwarder)
1363 mpViewForwarder->SetInvalid();
1364 }
1365 ScAccessibleTextData::Notify( rBC, rHint );
1366}
1367
1368ScAccessibleTextData* ScAccessibleCsvTextData::Clone() const
1369{
1370 return new ScAccessibleCsvTextData( mpWindow, mpEditEngine, maCellText, maCellSize );
1371}
1372
1373SvxTextForwarder* ScAccessibleCsvTextData::GetTextForwarder()
1374{
1375 if( mpEditEngine )
1376 {
1377 mpEditEngine->SetPaperSize( maCellSize );
1378 mpEditEngine->SetText( maCellText );
1379 if( !mpTextForwarder )
1380 mpTextForwarder.reset( new SvxEditEngineForwarder( *mpEditEngine ) );
1381 }
1382 else
1383 mpTextForwarder.reset();
1384 return mpTextForwarder.get();
1385}
1386
1387SvxViewForwarder* ScAccessibleCsvTextData::GetViewForwarder()
1388{
1389 if( !mpViewForwarder )
1390 mpViewForwarder.reset( new ScCsvViewForwarder( mpWindow ) );
1391 return mpViewForwarder.get();
1392}
1393
1394SvxEditViewForwarder* ScAccessibleCsvTextData::GetEditViewForwarder( bool /* bCreate */ )
1395{
1396 return nullptr;
1397}
1398
1399/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/unique_ptr.h

1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <utility>
37#include <tuple>
38#include <bits/stl_function.h>
39#include <bits/functional_hash.h>
40#if __cplusplus201703L > 201703L
41# include <compare>
42# include <ostream>
43#endif
44
45namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup pointer_abstractions
51 * @{
52 */
53
54#if _GLIBCXX_USE_DEPRECATED1
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 template<typename> class auto_ptr;
58#pragma GCC diagnostic pop
59#endif
60
61 /// Primary template of default_delete, used by unique_ptr for single objects
62 template<typename _Tp>
63 struct default_delete
64 {
65 /// Default constructor
66 constexpr default_delete() noexcept = default;
67
68 /** @brief Converting constructor.
69 *
70 * Allows conversion from a deleter for objects of another type, `_Up`,
71 * only if `_Up*` is convertible to `_Tp*`.
72 */
73 template<typename _Up,
74 typename = _Require<is_convertible<_Up*, _Tp*>>>
75 default_delete(const default_delete<_Up>&) noexcept { }
76
77 /// Calls `delete __ptr`
78 void
79 operator()(_Tp* __ptr) const
80 {
81 static_assert(!is_void<_Tp>::value,
82 "can't delete pointer to incomplete type");
83 static_assert(sizeof(_Tp)>0,
84 "can't delete pointer to incomplete type");
85 delete __ptr;
86 }
87 };
88
89 // _GLIBCXX_RESOLVE_LIB_DEFECTS
90 // DR 740 - omit specialization for array objects with a compile time length
91
92 /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
93 template<typename _Tp>
94 struct default_delete<_Tp[]>
95 {
96 public:
97 /// Default constructor
98 constexpr default_delete() noexcept = default;
99
100 /** @brief Converting constructor.
101 *
102 * Allows conversion from a deleter for arrays of another type, such as
103 * a const-qualified version of `_Tp`.
104 *
105 * Conversions from types derived from `_Tp` are not allowed because
106 * it is undefined to `delete[]` an array of derived types through a
107 * pointer to the base type.
108 */
109 template<typename _Up,
110 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
111 default_delete(const default_delete<_Up[]>&) noexcept { }
112
113 /// Calls `delete[] __ptr`
114 template<typename _Up>
115 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
116 operator()(_Up* __ptr) const
117 {
118 static_assert(sizeof(_Tp)>0,
119 "can't delete pointer to incomplete type");
120 delete [] __ptr;
121 }
122 };
123
124 /// @cond undocumented
125
126 // Manages the pointer and deleter of a unique_ptr
127 template <typename _Tp, typename _Dp>
128 class __uniq_ptr_impl
129 {
130 template <typename _Up, typename _Ep, typename = void>
131 struct _Ptr
132 {
133 using type = _Up*;
134 };
135
136 template <typename _Up, typename _Ep>
137 struct
138 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
139 {
140 using type = typename remove_reference<_Ep>::type::pointer;
141 };
142
143 public:
144 using _DeleterConstraint = enable_if<
145 __and_<__not_<is_pointer<_Dp>>,
146 is_default_constructible<_Dp>>::value>;
147
148 using pointer = typename _Ptr<_Tp, _Dp>::type;
149
150 static_assert( !is_rvalue_reference<_Dp>::value,
151 "unique_ptr's deleter type must be a function object type"
152 " or an lvalue reference type" );
153
154 __uniq_ptr_impl() = default;
155 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
156
157 template<typename _Del>
158 __uniq_ptr_impl(pointer __p, _Del&& __d)
159 : _M_t(__p, std::forward<_Del>(__d)) { }
160
161 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
162 : _M_t(std::move(__u._M_t))
163 { __u._M_ptr() = nullptr; }
164
165 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
166 {
167 reset(__u.release());
168 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
169 return *this;
170 }
171
172 pointer& _M_ptr() { return std::get<0>(_M_t); }
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
174 _Dp& _M_deleter() { return std::get<1>(_M_t); }
175 const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
176
177 void reset(pointer __p) noexcept
178 {
179 const pointer __old_p = _M_ptr();
180 _M_ptr() = __p;
181 if (__old_p)
182 _M_deleter()(__old_p);
183 }
184
185 pointer release() noexcept
186 {
187 pointer __p = _M_ptr();
188 _M_ptr() = nullptr;
189 return __p;
190 }
191
192 void
193 swap(__uniq_ptr_impl& __rhs) noexcept
194 {
195 using std::swap;
196 swap(this->_M_ptr(), __rhs._M_ptr());
197 swap(this->_M_deleter(), __rhs._M_deleter());
198 }
199
200 private:
201 tuple<pointer, _Dp> _M_t;
202 };
203
204 // Defines move construction + assignment as either defaulted or deleted.
205 template <typename _Tp, typename _Dp,
206 bool = is_move_constructible<_Dp>::value,
207 bool = is_move_assignable<_Dp>::value>
208 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
209 {
210 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
211 __uniq_ptr_data(__uniq_ptr_data&&) = default;
212 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
213 };
214
215 template <typename _Tp, typename _Dp>
216 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
217 {
218 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
219 __uniq_ptr_data(__uniq_ptr_data&&) = default;
220 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
221 };
222
223 template <typename _Tp, typename _Dp>
224 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
225 {
226 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
227 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
228 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
229 };
230
231 template <typename _Tp, typename _Dp>
232 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
237 };
238 /// @endcond
239
240 /// 20.7.1.2 unique_ptr for single objects.
241 template <typename _Tp, typename _Dp = default_delete<_Tp>>
242 class unique_ptr
243 {
244 template <typename _Up>
245 using _DeleterConstraint =
246 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
247
248 __uniq_ptr_data<_Tp, _Dp> _M_t;
249
250 public:
251 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
252 using element_type = _Tp;
253 using deleter_type = _Dp;
254
255 private:
256 // helper template for detecting a safe conversion from another
257 // unique_ptr
258 template<typename _Up, typename _Ep>
259 using __safe_conversion_up = __and_<
260 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
261 __not_<is_array<_Up>>
262 >;
263
264 public:
265 // Constructors.
266
267 /// Default constructor, creates a unique_ptr that owns nothing.
268 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
269 constexpr unique_ptr() noexcept
270 : _M_t()
271 { }
272
273 /** Takes ownership of a pointer.
274 *
275 * @param __p A pointer to an object of @c element_type
276 *
277 * The deleter will be value-initialized.
278 */
279 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
280 explicit
281 unique_ptr(pointer __p) noexcept
282 : _M_t(__p)
283 { }
284
285 /** Takes ownership of a pointer.
286 *
287 * @param __p A pointer to an object of @c element_type
288 * @param __d A reference to a deleter.
289 *
290 * The deleter will be initialized with @p __d
291 */
292 template<typename _Del = deleter_type,
293 typename = _Require<is_copy_constructible<_Del>>>
294 unique_ptr(pointer __p, const deleter_type& __d) noexcept
295 : _M_t(__p, __d) { }
296
297 /** Takes ownership of a pointer.
298 *
299 * @param __p A pointer to an object of @c element_type
300 * @param __d An rvalue reference to a (non-reference) deleter.
301 *
302 * The deleter will be initialized with @p std::move(__d)
303 */
304 template<typename _Del = deleter_type,
305 typename = _Require<is_move_constructible<_Del>>>
306 unique_ptr(pointer __p,
307 __enable_if_t<!is_lvalue_reference<_Del>::value,
308 _Del&&> __d) noexcept
309 : _M_t(__p, std::move(__d))
310 { }
311
312 template<typename _Del = deleter_type,
313 typename _DelUnref = typename remove_reference<_Del>::type>
314 unique_ptr(pointer,
315 __enable_if_t<is_lvalue_reference<_Del>::value,
316 _DelUnref&&>) = delete;
317
318 /// Creates a unique_ptr that owns nothing.
319 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
320 constexpr unique_ptr(nullptr_t) noexcept
321 : _M_t()
322 { }
323
324 // Move constructors.
325
326 /// Move constructor.
327 unique_ptr(unique_ptr&&) = default;
328
329 /** @brief Converting constructor from another type
330 *
331 * Requires that the pointer owned by @p __u is convertible to the
332 * type of pointer owned by this object, @p __u does not own an array,
333 * and @p __u has a compatible deleter type.
334 */
335 template<typename _Up, typename _Ep, typename = _Require<
336 __safe_conversion_up<_Up, _Ep>,
337 typename conditional<is_reference<_Dp>::value,
338 is_same<_Ep, _Dp>,
339 is_convertible<_Ep, _Dp>>::type>>
340 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
341 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
342 { }
343
344#if _GLIBCXX_USE_DEPRECATED1
345#pragma GCC diagnostic push
346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
347 /// Converting constructor from @c auto_ptr
348 template<typename _Up, typename = _Require<
349 is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
350 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
351#pragma GCC diagnostic pop
352#endif
353
354 /// Destructor, invokes the deleter if the stored pointer is not null.
355 ~unique_ptr() noexcept
356 {
357 static_assert(__is_invocable<deleter_type&, pointer>::value,
358 "unique_ptr's deleter must be invocable with a pointer");
359 auto& __ptr = _M_t._M_ptr();
360 if (__ptr != nullptr)
361 get_deleter()(std::move(__ptr));
362 __ptr = pointer();
363 }
364
365 // Assignment.
366
367 /** @brief Move assignment operator.
368 *
369 * Invokes the deleter if this object owns a pointer.
370 */
371 unique_ptr& operator=(unique_ptr&&) = default;
372
373 /** @brief Assignment from another type.
374 *
375 * @param __u The object to transfer ownership from, which owns a
376 * convertible pointer to a non-array object.
377 *
378 * Invokes the deleter if this object owns a pointer.
379 */
380 template<typename _Up, typename _Ep>
381 typename enable_if< __and_<
382 __safe_conversion_up<_Up, _Ep>,
383 is_assignable<deleter_type&, _Ep&&>
384 >::value,
385 unique_ptr&>::type
386 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
387 {
388 reset(__u.release());
389 get_deleter() = std::forward<_Ep>(__u.get_deleter());
390 return *this;
391 }
392
393 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
394 unique_ptr&
395 operator=(nullptr_t) noexcept
396 {
397 reset();
398 return *this;
399 }
400
401 // Observers.
402
403 /// Dereference the stored pointer.
404 typename add_lvalue_reference<element_type>::type
405 operator*() const
406 {
407 __glibcxx_assert(get() != pointer());
408 return *get();
409 }
410
411 /// Return the stored pointer.
412 pointer
413 operator->() const noexcept
414 {
415 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
416 return get();
417 }
418
419 /// Return the stored pointer.
420 pointer
421 get() const noexcept
422 { return _M_t._M_ptr(); }
423
424 /// Return a reference to the stored deleter.
425 deleter_type&
426 get_deleter() noexcept
427 { return _M_t._M_deleter(); }
428
429 /// Return a reference to the stored deleter.
430 const deleter_type&
431 get_deleter() const noexcept
432 { return _M_t._M_deleter(); }
433
434 /// Return @c true if the stored pointer is not null.
435 explicit operator bool() const noexcept
436 { return get() == pointer() ? false : true; }
8
Assuming the condition is true
9
'?' condition is true
10
Returning zero, which participates in a condition later
18
'?' condition is true
19
Returning zero, which participates in a condition later
437
438 // Modifiers.
439
440 /// Release ownership of any stored pointer.
441 pointer
442 release() noexcept
443 { return _M_t.release(); }
444
445 /** @brief Replace the stored pointer.
446 *
447 * @param __p The new pointer to store.
448 *
449 * The deleter will be invoked if a pointer is already owned.
450 */
451 void
452 reset(pointer __p = pointer()) noexcept
453 {
454 static_assert(__is_invocable<deleter_type&, pointer>::value,
455 "unique_ptr's deleter must be invocable with a pointer");
456 _M_t.reset(std::move(__p));
457 }
458
459 /// Exchange the pointer and deleter with another object.
460 void
461 swap(unique_ptr& __u) noexcept
462 {
463 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
464 _M_t.swap(__u._M_t);
465 }
466
467 // Disable copy from lvalue.
468 unique_ptr(const unique_ptr&) = delete;
469 unique_ptr& operator=(const unique_ptr&) = delete;
470 };
471
472 /// 20.7.1.3 unique_ptr for array objects with a runtime length
473 // [unique.ptr.runtime]
474 // _GLIBCXX_RESOLVE_LIB_DEFECTS
475 // DR 740 - omit specialization for array objects with a compile time length
476 template<typename _Tp, typename _Dp>
477 class unique_ptr<_Tp[], _Dp>
478 {
479 template <typename _Up>
480 using _DeleterConstraint =
481 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
482
483 __uniq_ptr_data<_Tp, _Dp> _M_t;
484
485 template<typename _Up>
486 using __remove_cv = typename remove_cv<_Up>::type;
487
488 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
489 template<typename _Up>
490 using __is_derived_Tp
491 = __and_< is_base_of<_Tp, _Up>,
492 __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
493
494 public:
495 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
496 using element_type = _Tp;
497 using deleter_type = _Dp;
498
499 // helper template for detecting a safe conversion from another
500 // unique_ptr
501 template<typename _Up, typename _Ep,
502 typename _UPtr = unique_ptr<_Up, _Ep>,
503 typename _UP_pointer = typename _UPtr::pointer,
504 typename _UP_element_type = typename _UPtr::element_type>
505 using __safe_conversion_up = __and_<
506 is_array<_Up>,
507 is_same<pointer, element_type*>,
508 is_same<_UP_pointer, _UP_element_type*>,
509 is_convertible<_UP_element_type(*)[], element_type(*)[]>
510 >;
511
512 // helper template for detecting a safe conversion from a raw pointer
513 template<typename _Up>
514 using __safe_conversion_raw = __and_<
515 __or_<__or_<is_same<_Up, pointer>,
516 is_same<_Up, nullptr_t>>,
517 __and_<is_pointer<_Up>,
518 is_same<pointer, element_type*>,
519 is_convertible<
520 typename remove_pointer<_Up>::type(*)[],
521 element_type(*)[]>
522 >
523 >
524 >;
525
526 // Constructors.
527
528 /// Default constructor, creates a unique_ptr that owns nothing.
529 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
530 constexpr unique_ptr() noexcept
531 : _M_t()
532 { }
533
534 /** Takes ownership of a pointer.
535 *
536 * @param __p A pointer to an array of a type safely convertible
537 * to an array of @c element_type
538 *
539 * The deleter will be value-initialized.
540 */
541 template<typename _Up,
542 typename _Vp = _Dp,
543 typename = _DeleterConstraint<_Vp>,
544 typename = typename enable_if<
545 __safe_conversion_raw<_Up>::value, bool>::type>
546 explicit
547 unique_ptr(_Up __p) noexcept
548 : _M_t(__p)
549 { }
550
551 /** Takes ownership of a pointer.
552 *
553 * @param __p A pointer to an array of a type safely convertible
554 * to an array of @c element_type
555 * @param __d A reference to a deleter.
556 *
557 * The deleter will be initialized with @p __d
558 */
559 template<typename _Up, typename _Del = deleter_type,
560 typename = _Require<__safe_conversion_raw<_Up>,
561 is_copy_constructible<_Del>>>
562 unique_ptr(_Up __p, const deleter_type& __d) noexcept
563 : _M_t(__p, __d) { }
564
565 /** Takes ownership of a pointer.
566 *
567 * @param __p A pointer to an array of a type safely convertible
568 * to an array of @c element_type
569 * @param __d A reference to a deleter.
570 *
571 * The deleter will be initialized with @p std::move(__d)
572 */
573 template<typename _Up, typename _Del = deleter_type,
574 typename = _Require<__safe_conversion_raw<_Up>,
575 is_move_constructible<_Del>>>
576 unique_ptr(_Up __p,
577 __enable_if_t<!is_lvalue_reference<_Del>::value,
578 _Del&&> __d) noexcept
579 : _M_t(std::move(__p), std::move(__d))
580 { }
581
582 template<typename _Up, typename _Del = deleter_type,
583 typename _DelUnref = typename remove_reference<_Del>::type,
584 typename = _Require<__safe_conversion_raw<_Up>>>
585 unique_ptr(_Up,
586 __enable_if_t<is_lvalue_reference<_Del>::value,
587 _DelUnref&&>) = delete;
588
589 /// Move constructor.
590 unique_ptr(unique_ptr&&) = default;
591
592 /// Creates a unique_ptr that owns nothing.
593 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
594 constexpr unique_ptr(nullptr_t) noexcept
595 : _M_t()
596 { }
597
598 template<typename _Up, typename _Ep, typename = _Require<
599 __safe_conversion_up<_Up, _Ep>,
600 typename conditional<is_reference<_Dp>::value,
601 is_same<_Ep, _Dp>,
602 is_convertible<_Ep, _Dp>>::type>>
603 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
604 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
605 { }
606
607 /// Destructor, invokes the deleter if the stored pointer is not null.
608 ~unique_ptr()
609 {
610 auto& __ptr = _M_t._M_ptr();
611 if (__ptr != nullptr)
612 get_deleter()(__ptr);
613 __ptr = pointer();
614 }
615
616 // Assignment.
617
618 /** @brief Move assignment operator.
619 *
620 * Invokes the deleter if this object owns a pointer.
621 */
622 unique_ptr&
623 operator=(unique_ptr&&) = default;
624
625 /** @brief Assignment from another type.
626 *
627 * @param __u The object to transfer ownership from, which owns a
628 * convertible pointer to an array object.
629 *
630 * Invokes the deleter if this object owns a pointer.
631 */
632 template<typename _Up, typename _Ep>
633 typename
634 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
635 is_assignable<deleter_type&, _Ep&&>
636 >::value,
637 unique_ptr&>::type
638 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
639 {
640 reset(__u.release());
641 get_deleter() = std::forward<_Ep>(__u.get_deleter());
642 return *this;
643 }
644
645 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
646 unique_ptr&
647 operator=(nullptr_t) noexcept
648 {
649 reset();
650 return *this;
651 }
652
653 // Observers.
654
655 /// Access an element of owned array.
656 typename std::add_lvalue_reference<element_type>::type
657 operator[](size_t __i) const
658 {
659 __glibcxx_assert(get() != pointer());
660 return get()[__i];
661 }
662
663 /// Return the stored pointer.
664 pointer
665 get() const noexcept
666 { return _M_t._M_ptr(); }
667
668 /// Return a reference to the stored deleter.
669 deleter_type&
670 get_deleter() noexcept
671 { return _M_t._M_deleter(); }
672
673 /// Return a reference to the stored deleter.
674 const deleter_type&
675 get_deleter() const noexcept
676 { return _M_t._M_deleter(); }
677
678 /// Return @c true if the stored pointer is not null.
679 explicit operator bool() const noexcept
680 { return get() == pointer() ? false : true; }
681
682 // Modifiers.
683
684 /// Release ownership of any stored pointer.
685 pointer
686 release() noexcept
687 { return _M_t.release(); }
688
689 /** @brief Replace the stored pointer.
690 *
691 * @param __p The new pointer to store.
692 *
693 * The deleter will be invoked if a pointer is already owned.
694 */
695 template <typename _Up,
696 typename = _Require<
697 __or_<is_same<_Up, pointer>,
698 __and_<is_same<pointer, element_type*>,
699 is_pointer<_Up>,
700 is_convertible<
701 typename remove_pointer<_Up>::type(*)[],
702 element_type(*)[]
703 >
704 >
705 >
706 >>
707 void
708 reset(_Up __p) noexcept
709 { _M_t.reset(std::move(__p)); }
710
711 void reset(nullptr_t = nullptr) noexcept
712 { reset(pointer()); }
713
714 /// Exchange the pointer and deleter with another object.
715 void
716 swap(unique_ptr& __u) noexcept
717 {
718 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
719 _M_t.swap(__u._M_t);
720 }
721
722 // Disable copy from lvalue.
723 unique_ptr(const unique_ptr&) = delete;
724 unique_ptr& operator=(const unique_ptr&) = delete;
725 };
726
727 /// @relates unique_ptr @{
728
729 /// Swap overload for unique_ptr
730 template<typename _Tp, typename _Dp>
731 inline
732#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
733 // Constrained free swap overload, see p0185r1
734 typename enable_if<__is_swappable<_Dp>::value>::type
735#else
736 void
737#endif
738 swap(unique_ptr<_Tp, _Dp>& __x,
739 unique_ptr<_Tp, _Dp>& __y) noexcept
740 { __x.swap(__y); }
741
742#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
743 template<typename _Tp, typename _Dp>
744 typename enable_if<!__is_swappable<_Dp>::value>::type
745 swap(unique_ptr<_Tp, _Dp>&,
746 unique_ptr<_Tp, _Dp>&) = delete;
747#endif
748
749 /// Equality operator for unique_ptr objects, compares the owned pointers
750 template<typename _Tp, typename _Dp,
751 typename _Up, typename _Ep>
752 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
753 operator==(const unique_ptr<_Tp, _Dp>& __x,
754 const unique_ptr<_Up, _Ep>& __y)
755 { return __x.get() == __y.get(); }
756
757 /// unique_ptr comparison with nullptr
758 template<typename _Tp, typename _Dp>
759 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
760 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
761 { return !__x; }
762
763#ifndef __cpp_lib_three_way_comparison
764 /// unique_ptr comparison with nullptr
765 template<typename _Tp, typename _Dp>
766 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
767 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
768 { return !__x; }
769
770 /// Inequality operator for unique_ptr objects, compares the owned pointers
771 template<typename _Tp, typename _Dp,
772 typename _Up, typename _Ep>
773 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
774 operator!=(const unique_ptr<_Tp, _Dp>& __x,
775 const unique_ptr<_Up, _Ep>& __y)
776 { return __x.get() != __y.get(); }
777
778 /// unique_ptr comparison with nullptr
779 template<typename _Tp, typename _Dp>
780 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
781 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
782 { return (bool)__x; }
783
784 /// unique_ptr comparison with nullptr
785 template<typename _Tp, typename _Dp>
786 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
787 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
788 { return (bool)__x; }
789#endif // three way comparison
790
791 /// Relational operator for unique_ptr objects, compares the owned pointers
792 template<typename _Tp, typename _Dp,
793 typename _Up, typename _Ep>
794 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
795 operator<(const unique_ptr<_Tp, _Dp>& __x,
796 const unique_ptr<_Up, _Ep>& __y)
797 {
798 typedef typename
799 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
800 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
801 return std::less<_CT>()(__x.get(), __y.get());
802 }
803
804 /// unique_ptr comparison with nullptr
805 template<typename _Tp, typename _Dp>
806 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
807 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
808 {
809 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
810 nullptr);
811 }
812
813 /// unique_ptr comparison with nullptr
814 template<typename _Tp, typename _Dp>
815 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
816 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
817 {
818 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
819 __x.get());
820 }
821
822 /// Relational operator for unique_ptr objects, compares the owned pointers
823 template<typename _Tp, typename _Dp,
824 typename _Up, typename _Ep>
825 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
826 operator<=(const unique_ptr<_Tp, _Dp>& __x,
827 const unique_ptr<_Up, _Ep>& __y)
828 { return !(__y < __x); }
829
830 /// unique_ptr comparison with nullptr
831 template<typename _Tp, typename _Dp>
832 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
833 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
834 { return !(nullptr < __x); }
835
836 /// unique_ptr comparison with nullptr
837 template<typename _Tp, typename _Dp>
838 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
839 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
840 { return !(__x < nullptr); }
841
842 /// Relational operator for unique_ptr objects, compares the owned pointers
843 template<typename _Tp, typename _Dp,
844 typename _Up, typename _Ep>
845 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
846 operator>(const unique_ptr<_Tp, _Dp>& __x,
847 const unique_ptr<_Up, _Ep>& __y)
848 { return (__y < __x); }
849
850 /// unique_ptr comparison with nullptr
851 template<typename _Tp, typename _Dp>
852 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
853 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
854 {
855 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
856 __x.get());
857 }
858
859 /// unique_ptr comparison with nullptr
860 template<typename _Tp, typename _Dp>
861 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
862 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
863 {
864 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
865 nullptr);
866 }
867
868 /// Relational operator for unique_ptr objects, compares the owned pointers
869 template<typename _Tp, typename _Dp,
870 typename _Up, typename _Ep>
871 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
872 operator>=(const unique_ptr<_Tp, _Dp>& __x,
873 const unique_ptr<_Up, _Ep>& __y)
874 { return !(__x < __y); }
875
876 /// unique_ptr comparison with nullptr
877 template<typename _Tp, typename _Dp>
878 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
879 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
880 { return !(__x < nullptr); }
881
882 /// unique_ptr comparison with nullptr
883 template<typename _Tp, typename _Dp>
884 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
885 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
886 { return !(nullptr < __x); }
887
888#ifdef __cpp_lib_three_way_comparison
889 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
890 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
891 typename unique_ptr<_Up, _Ep>::pointer>
892 inline
893 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
894 typename unique_ptr<_Up, _Ep>::pointer>
895 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
896 const unique_ptr<_Up, _Ep>& __y)
897 { return compare_three_way()(__x.get(), __y.get()); }
898
899 template<typename _Tp, typename _Dp>
900 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
901 inline
902 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
903 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
904 {
905 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
906 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
907 }
908#endif
909 // @} relates unique_ptr
910
911 /// @cond undocumented
912 template<typename _Up, typename _Ptr = typename _Up::pointer,
913 bool = __poison_hash<_Ptr>::__enable_hash_call>
914 struct __uniq_ptr_hash
915#if ! _GLIBCXX_INLINE_VERSION0
916 : private __poison_hash<_Ptr>
917#endif
918 {
919 size_t
920 operator()(const _Up& __u) const
921 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
922 { return hash<_Ptr>()(__u.get()); }
923 };
924
925 template<typename _Up, typename _Ptr>
926 struct __uniq_ptr_hash<_Up, _Ptr, false>
927 : private __poison_hash<_Ptr>
928 { };
929 /// @endcond
930
931 /// std::hash specialization for unique_ptr.
932 template<typename _Tp, typename _Dp>
933 struct hash<unique_ptr<_Tp, _Dp>>
934 : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
935 public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
936 { };
937
938#if __cplusplus201703L >= 201402L
939 /// @relates unique_ptr @{
940#define __cpp_lib_make_unique201304 201304
941
942 /// @cond undocumented
943
944 template<typename _Tp>
945 struct _MakeUniq
946 { typedef unique_ptr<_Tp> __single_object; };
947
948 template<typename _Tp>
949 struct _MakeUniq<_Tp[]>
950 { typedef unique_ptr<_Tp[]> __array; };
951
952 template<typename _Tp, size_t _Bound>
953 struct _MakeUniq<_Tp[_Bound]>
954 { struct __invalid_type { }; };
955
956 /// @endcond
957
958 /// std::make_unique for single objects
959 template<typename _Tp, typename... _Args>
960 inline typename _MakeUniq<_Tp>::__single_object
961 make_unique(_Args&&... __args)
962 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
963
964 /// std::make_unique for arrays of unknown bound
965 template<typename _Tp>
966 inline typename _MakeUniq<_Tp>::__array
967 make_unique(size_t __num)
968 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
969
970 /// Disable std::make_unique for arrays of known bound
971 template<typename _Tp, typename... _Args>
972 inline typename _MakeUniq<_Tp>::__invalid_type
973 make_unique(_Args&&...) = delete;
974 // @} relates unique_ptr
975#endif // C++14
976
977#if __cplusplus201703L > 201703L && __cpp_concepts
978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
979 // 2948. unique_ptr does not define operator<< for stream output
980 /// Stream output operator for unique_ptr
981 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
982 inline basic_ostream<_CharT, _Traits>&
983 operator<<(basic_ostream<_CharT, _Traits>& __os,
984 const unique_ptr<_Tp, _Dp>& __p)
985 requires requires { __os << __p.get(); }
986 {
987 __os << __p.get();
988 return __os;
989 }
990#endif // C++20
991
992 // @} group pointer_abstractions
993
994#if __cplusplus201703L >= 201703L
995 namespace __detail::__variant
996 {
997 template<typename> struct _Never_valueless_alt; // see <variant>
998
999 // Provide the strong exception-safety guarantee when emplacing a
1000 // unique_ptr into a variant.
1001 template<typename _Tp, typename _Del>
1002 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1003 : std::true_type
1004 { };
1005 } // namespace __detail::__variant
1006#endif // C++17
1007
1008_GLIBCXX_END_NAMESPACE_VERSION
1009} // namespace
1010
1011#endif /* _UNIQUE_PTR_H */