Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx
Warning:line 484, column 25
Called C++ object pointer is null

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 svdxcgv.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 SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -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/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -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/SdiTarget/svx/sdi -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/svx/source/svdraw/svdxcgv.cxx

/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.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 <vector>
21#include <unordered_set>
22#include <editeng/editdata.hxx>
23#include <rtl/strbuf.hxx>
24#include <svx/xfillit0.hxx>
25#include <svx/xlineit0.hxx>
26#include <svx/svdxcgv.hxx>
27#include <svx/svdoutl.hxx>
28#include <svx/svdundo.hxx>
29#include <svx/svdograf.hxx>
30#include <svx/svdoole2.hxx>
31#include <svx/svdorect.hxx>
32#include <svx/svdopage.hxx>
33#include <svx/svdpage.hxx>
34#include <svx/svdpagv.hxx>
35#include <svx/svdtrans.hxx>
36#include <svx/strings.hrc>
37#include <svx/dialmgr.hxx>
38#include <tools/bigint.hxx>
39#include <clonelist.hxx>
40#include <vcl/virdev.hxx>
41#include <svl/style.hxx>
42#include <fmobj.hxx>
43#include <vcl/vectorgraphicdata.hxx>
44#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
45#include <drawinglayer/geometry/viewinformation2d.hxx>
46#include <svx/sdr/contact/viewcontact.hxx>
47#include <sdr/contact/objectcontactofobjlistpainter.hxx>
48#include <svx/sdr/contact/displayinfo.hxx>
49#include <svx/svdotable.hxx>
50#include <sal/log.hxx>
51
52using namespace com::sun::star;
53
54SdrExchangeView::SdrExchangeView(
55 SdrModel& rSdrModel,
56 OutputDevice* pOut)
57: SdrObjEditView(rSdrModel, pOut)
58{
59}
60
61bool SdrExchangeView::ImpLimitToWorkArea(Point& rPt) const
62{
63 bool bRet(false);
64
65 if(!maMaxWorkArea.IsEmpty())
66 {
67 if(rPt.X()<maMaxWorkArea.Left())
68 {
69 rPt.setX( maMaxWorkArea.Left() );
70 bRet = true;
71 }
72
73 if(rPt.X()>maMaxWorkArea.Right())
74 {
75 rPt.setX( maMaxWorkArea.Right() );
76 bRet = true;
77 }
78
79 if(rPt.Y()<maMaxWorkArea.Top())
80 {
81 rPt.setY( maMaxWorkArea.Top() );
82 bRet = true;
83 }
84
85 if(rPt.Y()>maMaxWorkArea.Bottom())
86 {
87 rPt.setY( maMaxWorkArea.Bottom() );
88 bRet = true;
89 }
90 }
91 return bRet;
92}
93
94void SdrExchangeView::ImpGetPasteObjList(Point& /*rPos*/, SdrObjList*& rpLst)
95{
96 if (rpLst==nullptr)
97 {
98 SdrPageView* pPV = GetSdrPageView();
99
100 if (pPV!=nullptr) {
101 rpLst=pPV->GetObjList();
102 }
103 }
104}
105
106bool SdrExchangeView::ImpGetPasteLayer(const SdrObjList* pObjList, SdrLayerID& rLayer) const
107{
108 bool bRet=false;
109 rLayer=SdrLayerID(0);
110 if (pObjList!=nullptr) {
111 const SdrPage* pPg=pObjList->getSdrPageFromSdrObjList();
112 if (pPg!=nullptr) {
113 rLayer=pPg->GetLayerAdmin().GetLayerID(maActualLayer);
114 if (rLayer==SDRLAYER_NOTFOUND) rLayer=SdrLayerID(0);
115 SdrPageView* pPV = GetSdrPageView();
116 if (pPV!=nullptr) {
117 bRet=!pPV->GetLockedLayers().IsSet(rLayer) && pPV->GetVisibleLayers().IsSet(rLayer);
118 }
119 }
120 }
121 return bRet;
122}
123
124bool SdrExchangeView::Paste(const OUString& rStr, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
125{
126 if (rStr.isEmpty())
127 return false;
128
129 Point aPos(rPos);
130 ImpGetPasteObjList(aPos,pLst);
131 ImpLimitToWorkArea( aPos );
132 if (pLst==nullptr) return false;
133 SdrLayerID nLayer;
134 if (!ImpGetPasteLayer(pLst,nLayer)) return false;
135 bool bUnmark = (nOptions & (SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
136 if (bUnmark) UnmarkAllObj();
137 tools::Rectangle aTextRect(0,0,500,500);
138 SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
139 if (pPage!=nullptr) {
140 aTextRect.SetSize(pPage->GetSize());
141 }
142 SdrRectObj* pObj = new SdrRectObj(
143 getSdrModelFromSdrView(),
144 OBJ_TEXT,
145 aTextRect);
146
147 pObj->SetLayer(nLayer);
148 pObj->NbcSetText(rStr); // SetText before SetAttr, else SetAttr doesn't work!
149 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
150
151 pObj->SetMergedItemSet(maDefaultAttr);
152
153 SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
154 aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
155 aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
156
157 pObj->SetMergedItemSet(aTempAttr);
158
159 pObj->FitFrameToTextSize();
160 Size aSiz(pObj->GetLogicRect().GetSize());
161 MapUnit eMap=mpModel->GetScaleUnit();
162 Fraction aMap=mpModel->GetScaleFraction();
163 ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
164 return true;
165}
166
167bool SdrExchangeView::Paste(SvStream& rInput, EETextFormat eFormat, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
168{
169 Point aPos(rPos);
170 ImpGetPasteObjList(aPos,pLst);
171 ImpLimitToWorkArea( aPos );
172 if (pLst==nullptr) return false;
173 SdrLayerID nLayer;
174 if (!ImpGetPasteLayer(pLst,nLayer)) return false;
175 bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
176 if (bUnmark) UnmarkAllObj();
177 tools::Rectangle aTextRect(0,0,500,500);
178 SdrPage* pPage=pLst->getSdrPageFromSdrObjList();
179 if (pPage!=nullptr) {
180 aTextRect.SetSize(pPage->GetSize());
181 }
182 SdrRectObj* pObj = new SdrRectObj(
183 getSdrModelFromSdrView(),
184 OBJ_TEXT,
185 aTextRect);
186
187 pObj->SetLayer(nLayer);
188 if (mpDefaultStyleSheet!=nullptr) pObj->NbcSetStyleSheet(mpDefaultStyleSheet, false);
189
190 pObj->SetMergedItemSet(maDefaultAttr);
191
192 SfxItemSet aTempAttr(mpModel->GetItemPool()); // no fill, no line
193 aTempAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
194 aTempAttr.Put(XFillStyleItem(drawing::FillStyle_NONE));
195
196 pObj->SetMergedItemSet(aTempAttr);
197
198 pObj->NbcSetText(rInput,OUString(),eFormat);
199 pObj->FitFrameToTextSize();
200 Size aSiz(pObj->GetLogicRect().GetSize());
201 MapUnit eMap=mpModel->GetScaleUnit();
202 Fraction aMap=mpModel->GetScaleFraction();
203 ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
204
205 // b4967543
206 if(pObj->GetOutlinerParaObject())
207 {
208 SdrOutliner& rOutliner = pObj->getSdrModelFromSdrObject().GetHitTestOutliner();
209 rOutliner.SetText(*pObj->GetOutlinerParaObject());
210
211 if(1 == rOutliner.GetParagraphCount())
212 {
213 SfxStyleSheet* pCandidate = rOutliner.GetStyleSheet(0);
214
215 if(pCandidate)
216 {
217 if(pObj->getSdrModelFromSdrObject().GetStyleSheetPool() == pCandidate->GetPool())
218 {
219 pObj->NbcSetStyleSheet(pCandidate, true);
220 }
221 }
222 }
223 }
224
225 return true;
226}
227
228bool SdrExchangeView::Paste(
229 const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
230{
231 const SdrModel* pSrcMod=&rMod;
232 if (pSrcMod==mpModel)
233 return false; // this can't work, right?
234
235 const bool bUndo = IsUndoEnabled();
236
237 if( bUndo )
238 BegUndo(SvxResId(STR_ExchangePastereinterpret_cast<char const *>("STR_ExchangePaste" "\004"
u8"Insert object(s)")
));
239
240 if( mxSelectionController.is() && mxSelectionController->PasteObjModel( rMod ) )
241 {
242 if( bUndo )
243 EndUndo();
244 return true;
245 }
246
247 Point aPos(rPos);
248 ImpGetPasteObjList(aPos,pLst);
249 SdrPageView* pMarkPV=nullptr;
250 SdrPageView* pPV = GetSdrPageView();
251
252 if(pPV && pPV->GetObjList() == pLst )
253 pMarkPV=pPV;
254
255 ImpLimitToWorkArea( aPos );
256 if (pLst==nullptr)
257 return false;
258
259 bool bUnmark=(nOptions&(SdrInsertFlags::DONTMARK|SdrInsertFlags::ADDMARK))==SdrInsertFlags::NONE && !IsTextEdit();
260 if (bUnmark)
261 UnmarkAllObj();
262
263 // Rescale, if the Model uses a different MapUnit.
264 // Calculate the necessary factors first.
265 MapUnit eSrcUnit=pSrcMod->GetScaleUnit();
266 MapUnit eDstUnit=mpModel->GetScaleUnit();
267 bool bResize=eSrcUnit!=eDstUnit;
268 Fraction aXResize,aYResize;
269 Point aPt0;
270 if (bResize)
271 {
272 FrPair aResize(GetMapFactor(eSrcUnit,eDstUnit));
273 aXResize=aResize.X();
274 aYResize=aResize.Y();
275 }
276 SdrObjList* pDstLst=pLst;
277 sal_uInt16 nPg,nPgCount=pSrcMod->GetPageCount();
278 for (nPg=0; nPg<nPgCount; nPg++)
279 {
280 const SdrPage* pSrcPg=pSrcMod->GetPage(nPg);
281
282 // Use SnapRect, not BoundRect here
283 tools::Rectangle aR=pSrcPg->GetAllObjSnapRect();
284
285 if (bResize)
286 ResizeRect(aR,aPt0,aXResize,aYResize);
287 Point aDist(aPos-aR.Center());
288 Size aSiz(aDist.X(),aDist.Y());
289 size_t nCloneErrCnt = 0;
290 const size_t nObjCount = pSrcPg->GetObjCount();
291 bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
292
293 // #i13033#
294 // New mechanism to re-create the connections of cloned connectors
295 CloneList aCloneList;
296 std::unordered_set<rtl::OUString> aNameSet;
297 for (size_t nOb=0; nOb<nObjCount; ++nOb)
298 {
299 const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
300
301 SdrObject* pNewObj(pSrcOb->CloneSdrObject(*mpModel));
302
303 if (pNewObj!=nullptr)
304 {
305 if(bResize)
306 {
307 pNewObj->getSdrModelFromSdrObject().SetPasteResize(true);
308 pNewObj->NbcResize(aPt0,aXResize,aYResize);
309 pNewObj->getSdrModelFromSdrObject().SetPasteResize(false);
310 }
311
312 // #i39861#
313 pNewObj->NbcMove(aSiz);
314
315 const SdrPage* pPg = pDstLst->getSdrPageFromSdrObjList();
316
317 if(pPg)
318 {
319 // #i72535#
320 const SdrLayerAdmin& rAd = pPg->GetLayerAdmin();
321 SdrLayerID nLayer(0);
322
323 if(dynamic_cast<const FmFormObj*>( pNewObj) != nullptr)
324 {
325 // for FormControls, force to form layer
326 nLayer = rAd.GetLayerID(rAd.GetControlLayerName());
327 }
328 else
329 {
330 nLayer = rAd.GetLayerID(maActualLayer);
331 }
332
333 if(SDRLAYER_NOTFOUND == nLayer)
334 {
335 nLayer = SdrLayerID(0);
336 }
337
338 pNewObj->SetLayer(nLayer);
339 }
340
341 pDstLst->InsertObjectThenMakeNameUnique(pNewObj, aNameSet);
342
343 if( bUndo )
344 AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pNewObj));
345
346 if (bMark) {
347 // Don't already set Markhandles!
348 // That is instead being done by ModelHasChanged in MarkView.
349 MarkObj(pNewObj,pMarkPV,false,true);
350 }
351
352 // #i13033#
353 aCloneList.AddPair(pSrcOb, pNewObj);
354 }
355 else
356 {
357 nCloneErrCnt++;
358 }
359 }
360
361 // #i13033#
362 // New mechanism to re-create the connections of cloned connectors
363 aCloneList.CopyConnections();
364
365 if(0 != nCloneErrCnt)
366 {
367#ifdef DBG_UTIL
368 OStringBuffer aStr("SdrExchangeView::Paste(): Error when cloning ");
369
370 if(nCloneErrCnt == 1)
371 {
372 aStr.append("a drawing object.");
373 }
374 else
375 {
376 aStr.append(static_cast<sal_Int32>(nCloneErrCnt));
377 aStr.append(" drawing objects.");
378 }
379
380 aStr.append(" Not copying object connectors.");
381
382 OSL_FAIL(aStr.getStr())do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "382" ": "), "%s", aStr.getStr()); } } while (false)
;
383#endif
384 }
385 }
386
387 if( bUndo )
388 EndUndo();
389
390 return true;
391}
392
393void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Point& rCenter, const Size& rSiz, const MapMode& rMap, SdrInsertFlags nOptions)
394{
395 BigInt nSizX(rSiz.Width());
396 BigInt nSizY(rSiz.Height());
397 MapUnit eSrcMU=rMap.GetMapUnit();
398 MapUnit eDstMU=mpModel->GetScaleUnit();
399 FrPair aMapFact(GetMapFactor(eSrcMU,eDstMU));
400 Fraction aDstFr(mpModel->GetScaleFraction());
401 nSizX *= double(aMapFact.X() * rMap.GetScaleX() * aDstFr);
402 nSizX *= aDstFr.GetDenominator();
403 nSizY *= double(aMapFact.Y() * rMap.GetScaleY());
404 nSizY /= aDstFr.GetNumerator();
405 long xs=nSizX;
406 long ys=nSizY;
407 Point aPos(rCenter.X()-xs/2,rCenter.Y()-ys/2);
408 tools::Rectangle aR(aPos.X(),aPos.Y(),aPos.X()+xs,aPos.Y()+ys);
409 pObj->SetLogicRect(aR);
410 rLst.InsertObject(pObj, SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
411
412 if( IsUndoEnabled() )
413 AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pObj));
414
415 SdrPageView* pMarkPV=nullptr;
416 SdrPageView* pPV = GetSdrPageView();
417
418 if(pPV && pPV->GetObjList()==&rLst)
419 pMarkPV=pPV;
420
421 bool bMark = pMarkPV!=nullptr && !IsTextEdit() && (nOptions&SdrInsertFlags::DONTMARK)==SdrInsertFlags::NONE;
422 if (bMark)
423 { // select object the first PageView we found
424 MarkObj(pObj,pMarkPV);
425 }
426}
427
428BitmapEx SdrExchangeView::GetMarkedObjBitmapEx(bool bNoVDevIfOneBmpMarked) const
429{
430 BitmapEx aBmp;
431
432 if( AreObjectsMarked() )
1
Calling 'SdrMarkView::AreObjectsMarked'
4
Returning from 'SdrMarkView::AreObjectsMarked'
5
Taking true branch
433 {
434 if(1 == GetMarkedObjectCount())
6
Assuming the condition is false
7
Taking false branch
435 {
436 if(bNoVDevIfOneBmpMarked)
437 {
438 SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
439 SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>( pGrafObjTmp );
440
441 if( pGrafObj && ( pGrafObj->GetGraphicType() == GraphicType::Bitmap ) )
442 {
443 aBmp = pGrafObj->GetTransformedGraphic().GetBitmapEx();
444 }
445 }
446 else
447 {
448 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(GetMarkedObjectByIndex(0));
449
450 if(pSdrGrafObj && pSdrGrafObj->isEmbeddedVectorGraphicData())
451 {
452 aBmp = pSdrGrafObj->GetGraphic().getVectorGraphicData()->getReplacement();
453 }
454 }
455 }
456
457 if( !aBmp )
8
Calling 'BitmapEx::operator!'
21
Returning from 'BitmapEx::operator!'
22
Taking true branch
458 {
459 // choose conversion directly using primitives to bitmap to avoid
460 // rendering errors with tiled bitmap fills (these will be tiled in a
461 // in-between metafile, but tend to show 'gaps' since the target is *no*
462 // bitmap rendering)
463 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
464 const sal_uInt32 nCount(aSdrObjects.size());
465
466 if(nCount)
23
Assuming 'nCount' is not equal to 0
24
Taking true branch
467 {
468 // collect sub-primitives as group objects, thus no expensive append
469 // to existing sequence is needed
470 drawinglayer::primitive2d::Primitive2DContainer xPrimitives(nCount);
471
472 for(sal_uInt32 a(0); a
24.1
'a' is < 'nCount'
24.1
'a' is < 'nCount'
24.1
'a' is < 'nCount'
24.1
'a' is < 'nCount'
24.1
'a' is < 'nCount'
24.1
'a' is < 'nCount'
< nCount; a++)
25
Loop condition is true. Entering loop body
473 {
474 SdrObject* pCandidate = aSdrObjects[a];
26
'pCandidate' initialized here
475 SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pCandidate);
476
477 if(pSdrGrafObj)
27
Assuming 'pSdrGrafObj' is null
28
Taking false branch
478 {
479 // #122753# To ensure existence of graphic content, force swap in
480 pSdrGrafObj->ForceSwapIn();
481 }
482
483 xPrimitives[a] = new drawinglayer::primitive2d::GroupPrimitive2D(
484 pCandidate->GetViewContact().getViewIndependentPrimitive2DContainer());
29
Called C++ object pointer is null
485 }
486
487 // get logic range
488 const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
489 const basegfx::B2DRange aRange(xPrimitives.getB2DRange(aViewInformation2D));
490
491 if(!aRange.isEmpty())
492 {
493 // if we have geometry and it has a range, convert to BitmapEx using
494 // common tooling
495 aBmp = convertPrimitive2DSequenceToBitmapEx(
496 xPrimitives,
497 aRange);
498 }
499 }
500 }
501 }
502
503 return aBmp;
504}
505
506
507GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) const
508{
509 GDIMetaFile aMtf;
510
511 if( AreObjectsMarked() )
512 {
513 tools::Rectangle aBound( GetMarkedObjBoundRect() );
514 Size aBoundSize( aBound.GetWidth(), aBound.GetHeight() );
515 MapMode aMap( mpModel->GetScaleUnit(), Point(), mpModel->GetScaleFraction(), mpModel->GetScaleFraction() );
516
517 if( bNoVDevIfOneMtfMarked )
518 {
519 SdrObject* pGrafObjTmp = GetMarkedObjectByIndex( 0 );
520 SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() ==1 ) ? dynamic_cast<SdrGrafObj*>( pGrafObjTmp ) : nullptr;
521
522 if( pGrafObj )
523 {
524 Graphic aGraphic( pGrafObj->GetTransformedGraphic() );
525
526 // #119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
527 aMtf = aGraphic.GetGDIMetaFile();
528 }
529 }
530
531 if( !aMtf.GetActionSize() )
532 {
533 ScopedVclPtrInstance< VirtualDevice > pOut;
534 const Size aDummySize(2, 2);
535
536 pOut->SetOutputSizePixel(aDummySize);
537 pOut->EnableOutput(false);
538 pOut->SetMapMode(aMap);
539 aMtf.Clear();
540 aMtf.Record(pOut);
541
542 DrawMarkedObj(*pOut);
543
544 aMtf.Stop();
545 aMtf.WindStart();
546
547 // moving the result is more reliable then setting a relative MapMode at the VDev (used
548 // before), also see #i99268# in GetObjGraphic() below. Some draw actions at
549 // the OutDev are simply not handled correctly when a MapMode is set at the
550 // target device, e.g. MetaFloatTransparentAction. Even the Move for this action
551 // was missing the manipulation of the embedded Metafile
552 aMtf.Move(-aBound.Left(), -aBound.Top());
553
554 aMtf.SetPrefMapMode( aMap );
555
556 // removed PrefSize extension. It is principally wrong to set a reduced size at
557 // the created MetaFile. The mentioned errors occur at output time since the integer
558 // MapModes from VCL lead to errors. It is now corrected in the VCLRenderer for
559 // primitives (and may later be done in breaking up a MetaFile to primitives)
560 aMtf.SetPrefSize(aBoundSize);
561 }
562 }
563
564 return aMtf;
565}
566
567
568Graphic SdrExchangeView::GetAllMarkedGraphic() const
569{
570 Graphic aRet;
571
572 if( AreObjectsMarked() )
573 {
574 if( ( 1 == GetMarkedObjectCount() ) && GetSdrMarkByIndex( 0 ) )
575 aRet = SdrExchangeView::GetObjGraphic(*GetMarkedObjectByIndex(0));
576 else
577 aRet = GetMarkedObjMetaFile();
578 }
579
580 return aRet;
581}
582
583
584Graphic SdrExchangeView::GetObjGraphic(const SdrObject& rSdrObject)
585{
586 Graphic aRet;
587
588 // try to get a graphic from the object first
589 const SdrGrafObj* pSdrGrafObj(dynamic_cast< const SdrGrafObj* >(&rSdrObject));
590 const SdrOle2Obj* pSdrOle2Obj(dynamic_cast< const SdrOle2Obj* >(&rSdrObject));
591
592 if(pSdrGrafObj)
593 {
594 if(pSdrGrafObj->isEmbeddedVectorGraphicData())
595 {
596 // get Metafile for Svg content
597 aRet = pSdrGrafObj->getMetafileFromEmbeddedVectorGraphicData();
598 }
599 else
600 {
601 // Make behaviour coherent with metafile
602 // recording below (which of course also takes
603 // view-transformed objects)
604 aRet = pSdrGrafObj->GetTransformedGraphic();
605 }
606 }
607 else if(pSdrOle2Obj)
608 {
609 if(pSdrOle2Obj->GetGraphic())
610 {
611 aRet = *pSdrOle2Obj->GetGraphic();
612 }
613 }
614
615 // if graphic could not be retrieved => go the hard way and create a MetaFile
616 if((GraphicType::NONE == aRet.GetType()) || (GraphicType::Default == aRet.GetType()))
617 {
618 ScopedVclPtrInstance< VirtualDevice > pOut;
619 GDIMetaFile aMtf;
620 const tools::Rectangle aBoundRect(rSdrObject.GetCurrentBoundRect());
621 const MapMode aMap(rSdrObject.getSdrModelFromSdrObject().GetScaleUnit(),
622 Point(),
623 rSdrObject.getSdrModelFromSdrObject().GetScaleFraction(),
624 rSdrObject.getSdrModelFromSdrObject().GetScaleFraction());
625
626 pOut->EnableOutput(false);
627 pOut->SetMapMode(aMap);
628 aMtf.Record(pOut);
629 rSdrObject.SingleObjectPainter(*pOut);
630 aMtf.Stop();
631 aMtf.WindStart();
632
633 // #i99268# replace the original offset from using XOutDev's SetOffset
634 // NOT (as tried with #i92760#) with another MapMode which gets recorded
635 // by the Metafile itself (what always leads to problems), but by
636 // moving the result directly
637 aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
638 aMtf.SetPrefMapMode(aMap);
639 aMtf.SetPrefSize(aBoundRect.GetSize());
640
641 if(aMtf.GetActionSize())
642 {
643 aRet = aMtf;
644 }
645 }
646
647 return aRet;
648}
649
650
651::std::vector< SdrObject* > SdrExchangeView::GetMarkedObjects() const
652{
653 SortMarkedObjects();
654 ::std::vector< SdrObject* > aRetval;
655
656 ::std::vector< ::std::vector< SdrMark* > > aObjVectors( 2 );
657 ::std::vector< SdrMark* >& rObjVector1 = aObjVectors[ 0 ];
658 ::std::vector< SdrMark* >& rObjVector2 = aObjVectors[ 1 ];
659 const SdrLayerAdmin& rLayerAdmin = mpModel->GetLayerAdmin();
660 const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName() );
661
662 for( size_t n = 0, nCount = GetMarkedObjectCount(); n < nCount; ++n )
663 {
664 SdrMark* pMark = GetSdrMarkByIndex( n );
665
666 // paint objects on control layer on top of all other objects
667 if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() )
668 rObjVector2.push_back( pMark );
669 else
670 rObjVector1.push_back( pMark );
671 }
672
673 for(const std::vector<SdrMark*> & rObjVector : aObjVectors)
674 {
675 for(SdrMark* pMark : rObjVector)
676 {
677 aRetval.push_back(pMark->GetMarkedSdrObj());
678 }
679 }
680
681 return aRetval;
682}
683
684
685void SdrExchangeView::DrawMarkedObj(OutputDevice& rOut) const
686{
687 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
688
689 if(!aSdrObjects.empty())
690 {
691 sdr::contact::ObjectContactOfObjListPainter aPainter(rOut, aSdrObjects, aSdrObjects[0]->getSdrPageFromSdrObject());
692 sdr::contact::DisplayInfo aDisplayInfo;
693
694 // do processing
695 aPainter.ProcessDisplay(aDisplayInfo);
696 }
697}
698
699std::unique_ptr<SdrModel> SdrExchangeView::CreateMarkedObjModel() const
700{
701 // Sorting the MarkList here might be problematic in the future, so
702 // use a copy.
703 SortMarkedObjects();
704 std::unique_ptr<SdrModel> pNewModel(mpModel->AllocModel());
705 SdrPage* pNewPage(pNewModel->AllocPage(false));
706 pNewModel->InsertPage(pNewPage);
707 ::std::vector< SdrObject* > aSdrObjects(GetMarkedObjects());
708
709 // #i13033#
710 // New mechanism to re-create the connections of cloned connectors
711 CloneList aCloneList;
712
713 for(SdrObject* pObj : aSdrObjects)
714 {
715 SdrObject* pNewObj(nullptr);
716
717 if(nullptr != dynamic_cast< const SdrPageObj* >(pObj))
718 {
719 // convert SdrPageObj's to a graphic representation, because
720 // virtual connection to referenced page gets lost in new model
721 pNewObj = new SdrGrafObj(
722 *pNewModel,
723 GetObjGraphic(*pObj),
724 pObj->GetLogicRect());
725 }
726 else if(nullptr != dynamic_cast< const sdr::table::SdrTableObj* >(pObj))
727 {
728 // check if we have a valid selection *different* from whole table
729 // being selected
730 if(mxSelectionController.is())
731 {
732 pNewObj = mxSelectionController->GetMarkedSdrObjClone(*pNewModel);
733 }
734 }
735
736 if(nullptr == pNewObj)
737 {
738 // not cloned yet
739 if(pObj->GetObjIdentifier() == OBJ_OLE2 && nullptr == mpModel->GetPersist())
740 {
741 // tdf#125520 - former fix was wrong, the SdrModel
742 // has to have a GetPersist() already, see task.
743 // We can still warn here when this is not the case
744 SAL_WARN( "svx", "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svx")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"
), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"),
("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"
), ("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "OLE gets cloned Persist, EmbeddedObjectContainer will not be copied"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx"),
("/home/maarten/src/libreoffice/core/svx/source/svdraw/svdxcgv.cxx"
":" "744" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
745 }
746
747 // use default way
748 pNewObj = pObj->CloneSdrObject(*pNewModel);
749 }
750
751 if(pNewObj)
752 {
753 pNewPage->InsertObject(pNewObj, SAL_MAX_SIZE((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
754
755 // #i13033#
756 aCloneList.AddPair(pObj, pNewObj);
757 }
758 }
759
760 // #i13033#
761 // New mechanism to re-create the connections of cloned connectors
762 aCloneList.CopyConnections();
763
764 return pNewModel;
765}
766
767/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/svx/svdmrkv.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_SVX_SVDMRKV_HXX
21#define INCLUDED_SVX_SVDMRKV_HXX
22
23#include <svx/svdmark.hxx>
24#include <svx/svdhdl.hxx>
25#include <svx/svdsnpv.hxx>
26#include <svx/svdtypes.hxx>
27#include <svx/svxdllapi.h>
28#include <o3tl/typed_flags_set.hxx>
29#include <basegfx/range/b2drectangle.hxx>
30
31
32class SfxViewShell;
33
34// The following is not yet implemented, or just partially:
35enum class SdrSearchOptions
36{
37 NONE = 0x0000,
38 DEEP = 0x0001, /* recursive into group objects */
39 ALSOONMASTER = 0x0002, /* MasterPages are also scanned */
40 WHOLEPAGE = 0x0004, /* Not just the ObjList of PageView */
41 TESTMARKABLE = 0x0008, /* just markable objects/points/handles/... */
42 TESTMACRO = 0x0010, /* Just objects with macro */
43 TESTTEXTEDIT = 0x0020, /* Just TextEdit-enabled objects */
44 MARKED = 0x0040, /* Just marked objects/points/... */
45 PASS2BOUND = 0x0080, /* In case of empty search results, then 2nd. try with BoundRectHit */
46 BEFOREMARK = 0x0100, /* if one marked one found, ignore all behind that */
47
48 IMPISMASTER = 0x0200, /* MasterPage is being searched right now */
49 PICKMARKABLE = TESTMARKABLE,
50 PICKTEXTEDIT = DEEP | TESTMARKABLE | TESTTEXTEDIT,
51 PICKMACRO = DEEP | ALSOONMASTER | WHOLEPAGE | TESTMACRO,
52};
53namespace o3tl
54{
55 template<> struct typed_flags<SdrSearchOptions> : is_typed_flags<SdrSearchOptions, 0x03ff> {};
56}
57
58enum class SdrHitKind
59{
60 NONE, // No hit
61 Object, // Hit
62 Handle, // Marking handle
63 HelpLine, // Reference line
64 Gluepoint, // Glue point
65 TextEdit, // Open OutlinerView was hit
66 TextEditObj, // Object for SdrBeginTextEdit (Textbereich)
67 UrlField, // Field in TextObj was hit (while it is currently not edited)
68 Macro, // Object for BegMacroObj
69 MarkedObject, // Marked object (e.g. for dragging)
70 UnmarkedObject, // non-marked Object (e.g. for marking)
71 Cell // hit on a cell inside a table shape (outside of the cells text area)
72};
73
74enum class SdrViewEditMode {
75 Edit, // Also known as arrow or pointer mode
76 Create, // Tool for object creation
77 GluePointEdit // Glue point editing mode
78};
79
80/** options for ImpGetDescriptionString() */
81enum class ImpGetDescriptionOptions
82{
83 NONE = 0,
84 POINTS = 1,
85 GLUEPOINTS = 2,
86};
87
88class ImplMarkingOverlay;
89class MarkingSubSelectionOverlay;
90
91class SVXCORE_DLLPUBLIC__attribute__ ((visibility("default"))) SdrMarkView : public SdrSnapView
92{
93 friend class SdrPageView;
94
95 // #114409#-3 Migrate selections
96 std::unique_ptr<ImplMarkingOverlay> mpMarkObjOverlay;
97 std::unique_ptr<ImplMarkingOverlay> mpMarkPointsOverlay;
98 std::unique_ptr<ImplMarkingOverlay> mpMarkGluePointsOverlay;
99
100 std::unique_ptr<MarkingSubSelectionOverlay> mpMarkingSubSelectionOverlay;
101
102protected:
103 SdrObject* mpMarkedObj; // If not just one object ( i.e. More than one object ) is marked.
104 SdrPageView* mpMarkedPV; // If all marked objects are situated on the same PageView.
105
106 Point maRef1; // Persistent - Rotation center / axis of reflection
107 Point maRef2; // Persistent
108 SdrHdlList maHdlList;
109
110 sdr::ViewSelection maSdrViewSelection;
111
112 std::vector<basegfx::B2DRectangle> maSubSelectionList;
113 tools::Rectangle maMarkedObjRect;
114 tools::Rectangle maMarkedPointsRect;
115 tools::Rectangle maMarkedGluePointsRect;
116
117 static constexpr sal_uInt16 mnFrameHandlesLimit = 50;
118
119 SdrDragMode meDragMode; // Persistent
120 SdrViewEditMode meEditMode; // Persistent
121 SdrViewEditMode meEditMode0; // Persistent
122
123 bool mbDesignMode : 1; // DesignMode for SdrUnoObj
124 bool mbForceFrameHandles : 1; // Persistent - FrameDrag also for single objects
125 bool mbPlusHdlAlways : 1; // Persistent
126 bool mbInsPolyPoint : 1; // at this time InsPolyPointDragging
127 bool mbMarkedObjRectDirty : 1;
128 bool mbMrkPntDirty : 1;
129 bool mbMarkedPointsRectsDirty : 1;
130
131 // flag to completely disable handles at the view
132 bool mbMarkHandlesHidden : 1;
133
134 // Helper to get a possible GridOffset from SdrObject
135 bool getPossibleGridOffsetForSdrObject(
136 basegfx::B2DVector& rOffset,
137 const SdrObject* pObj,
138 const SdrPageView* pPV) const;
139
140 // Helper to get a possible GridOffset from Position
141 bool getPossibleGridOffsetForPosition(
142 basegfx::B2DVector& rOffset,
143 const basegfx::B2DPoint& rPoint,
144 const SdrPageView* pPV) const;
145
146private:
147 SVX_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ImpSetPointsRects() const;
148 void UndirtyMrkPnt() const;
149
150 void SetMarkHandlesForLOKit(tools::Rectangle const & rRect, const SfxViewShell* pOtherShell);
151
152protected:
153 virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
154 virtual void ModelHasChanged() override; // Is called by the PaintView
155 virtual void SetMarkHandles(SfxViewShell* pOtherShell); // maHdlList - fill (List of handles)
156 void SetMarkRects(); // Rects at the PageViews
157 void CheckMarked(); // Scan MarkList after Del and Lock Layer ...
158 void AddDragModeHdl(SdrDragMode eMode);
159 virtual bool MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin) override;
160 virtual bool RequestHelp(const HelpEvent& rHEvt) override;
161
162 // add custom handles (used by other apps, e.g. AnchorPos)
163 virtual void AddCustomHdl();
164
165 void ForceRefToMarked();
166 void ForceUndirtyMrkPnt() const { if (mbMrkPntDirty) UndirtyMrkPnt(); }
167
168 virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay) const;
169 SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObjList const * pOL, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay, SdrObject*& rpRootObj) const;
170 SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObjList const * pOL, SdrPageView* pPV, SdrSearchOptions nOptions, const SdrLayerIDSet* pMVisLay, SdrObject*& rpRootObj,const SdrMarkList * pMarkList) const;
171 bool ImpIsFrameHandles() const;
172 OUString ImpGetDescriptionString(const char* pStrCacheID, ImpGetDescriptionOptions nOpt=ImpGetDescriptionOptions::NONE) const;
173
174 // Generates a string including degrees symbol, from an angel specification in 1/100deg
175 bool ImpMarkPoint(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark);
176 virtual bool MarkPoints(const tools::Rectangle* pRect, bool bUnmark);
177 bool MarkGluePoints(const tools::Rectangle* pRect, bool bUnmark);
178
179 void SetMoveOutside(bool bOn);
180 bool MarkableObjectsExceed( int n ) const;
181
182protected:
183 // #i71538# make constructors of SdrView sub-components protected to avoid incomplete incarnations which may get casted to SdrView
184 SdrMarkView(
185 SdrModel& rSdrModel,
186 OutputDevice* pOut);
187
188 virtual ~SdrMarkView() override;
189
190public:
191 virtual bool IsAction() const override;
192 virtual void MovAction(const Point& rPnt) override;
193 virtual void EndAction() override;
194 virtual void BckAction() override;
195 virtual void BrkAction() override;
196 virtual void TakeActionRect(tools::Rectangle& rRect) const override;
197
198 virtual void ClearPageView() override;
199 virtual void HideSdrPage() override;
200 bool IsObjMarkable(SdrObject const * pObj, SdrPageView const * pPV) const;
201
202 // Returns sal_True if objects, points or glue points are selected by drawing a frame
203 // (as long as the frame is drawn).
204 bool IsMarking() const { return IsMarkObj() || IsMarkPoints() || IsMarkGluePoints(); }
205
206 // Marking objects by drawing of a selection frame
207 void BegMarkObj(const Point& rPnt, bool bUnmark = false);
208 void MovMarkObj(const Point& rPnt);
209 bool EndMarkObj();
210 void BrkMarkObj();
211 bool IsMarkObj() const { return (nullptr != mpMarkObjOverlay); }
212
213 // DragModes: SDRDRAG_CREATE,SdrDragMode::Move,SdrDragMode::Resize,SdrDragMode::Rotate,SdrDragMode::Mirror,SdrDragMode::Shear,SdrDragMode::Crook
214 // Move==Resize
215 // The interface might maybe be changed in the future because of Ortho-Drag
216 void SetDragMode(SdrDragMode eMode);
217 SdrDragMode GetDragMode() const { return meDragMode; }
218 void SetFrameHandles(bool bOn);
219 bool IsFrameHandles() const { return mbForceFrameHandles; }
220
221 // returns true if number of markable objects is greater than 1
222 bool HasMultipleMarkableObjects() const { return MarkableObjectsExceed(1); };
223
224 void SetEditMode(SdrViewEditMode eMode);
225 SdrViewEditMode GetEditMode() const { return meEditMode; }
226
227 void SetEditMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::Edit:SdrViewEditMode::Create); }
228 bool IsEditMode() const { return meEditMode==SdrViewEditMode::Edit; }
229 void SetCreateMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::Create:SdrViewEditMode::Edit); }
230 bool IsCreateMode() const { return meEditMode==SdrViewEditMode::Create; }
231 void SetGluePointEditMode(bool bOn) { SetEditMode(bOn?SdrViewEditMode::GluePointEdit:meEditMode0); }
232 bool IsGluePointEditMode() const { return meEditMode==SdrViewEditMode::GluePointEdit; }
233
234 void SetDesignMode(bool bOn = true);
235 bool IsDesignMode() const { return mbDesignMode; }
236
237 void SetFrameDragSingles(bool bOn=true) { SetFrameHandles(bOn); }
238 bool IsFrameDragSingles() const { return IsFrameHandles(); }
239
240 bool HasMarkableObj() const { return MarkableObjectsExceed(0); };
241
242
243// migrate selections
244
245protected:
246 // all available changing methods
247 SdrMarkList& GetMarkedObjectListWriteAccess() { return maSdrViewSelection.GetMarkedObjectListWriteAccess(); }
248
249public:
250 // all available const methods for read access to selection
251 const SdrMarkList& GetMarkedObjectList() const { return maSdrViewSelection.GetMarkedObjectList(); }
252 // returns SAL_MAX_SIZE if not found
253 size_t TryToFindMarkedObject(const SdrObject* pObj) const { return GetMarkedObjectList().FindObject(pObj); }
254 SdrPageView* GetSdrPageViewOfMarkedByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum)->GetPageView(); }
255 SdrMark* GetSdrMarkByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum); }
256 SdrObject* GetMarkedObjectByIndex(size_t nNum) const { return GetMarkedObjectList().GetMark(nNum)->GetMarkedSdrObj(); }
257 size_t GetMarkedObjectCount() const { return GetMarkedObjectList().GetMarkCount(); }
258 void SortMarkedObjects() const { GetMarkedObjectList().ForceSort(); }
259 bool AreObjectsMarked() const { return 0 != GetMarkedObjectList().GetMarkCount(); }
2
Assuming the condition is true
3
Returning the value 1, which participates in a condition later
260 OUString const & GetDescriptionOfMarkedObjects() const { return GetMarkedObjectList().GetMarkDescription(); }
261 OUString const & GetDescriptionOfMarkedPoints() const { return GetMarkedObjectList().GetPointMarkDescription(); }
262 OUString const & GetDescriptionOfMarkedGluePoints() const { return GetMarkedObjectList().GetGluePointMarkDescription(); }
263
264 // Get a list of all those links which are connected to marked nodes,
265 // but which are not marked themselves.
266 const SdrMarkList& GetEdgesOfMarkedNodes() const { return maSdrViewSelection.GetEdgesOfMarkedNodes(); }
267 const SdrMarkList& GetMarkedEdgesOfMarkedNodes() const { return maSdrViewSelection.GetMarkedEdgesOfMarkedNodes(); }
268 const std::vector<SdrObject*>& GetTransitiveHullOfMarkedObjects() const { return maSdrViewSelection.GetAllMarkedObjects(); }
269
270
271 // mechanism to complete disable handles at the view. Handles will be hidden and deleted
272 // when set, no new ones created, no interaction allowed. Handles will be recreated and shown
273 // when reset. Default is false.
274 void hideMarkHandles();
275 void showMarkHandles();
276 bool areMarkHandlesHidden() const { return mbMarkHandlesHidden; }
277
278 bool IsMarkedHit(const Point& rPnt, short nTol=-2) const { return IsMarkedObjHit(rPnt,nTol); }
279 bool IsMarkedObjHit(const Point& rPnt, short nTol=-2) const;
280
281 SdrHdl* PickHandle(const Point& rPnt) const;
282
283 // Pick: Supported options for nOptions are:
284 // SdrSearchOptions::DEEP SdrSearchOptions::ALSOONMASTER SdrSearchOptions::TESTMARKABLE SdrSearchOptions::TESTTEXTEDIT
285 // SdrSearchOptions::MARKED
286 // SdrSearchOptions::WHOLEPAGE
287 SdrObject* PickObj(const Point& rPnt, short nTol, SdrPageView*& rpPV, SdrSearchOptions nOptions, SdrObject** ppRootObj, bool* pbHitPassDirect=nullptr) const;
288 SdrObject* PickObj(const Point& rPnt, short nTol, SdrPageView*& rpPV, SdrSearchOptions nOptions=SdrSearchOptions::NONE) const;
289 bool MarkObj(const Point& rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false);
290
291 // Pick: Supported options for nOptions are SdrSearchOptions::PASS2BOUND
292 bool PickMarkedObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, SdrSearchOptions nOptions) const;
293
294 // Selects the most upper of the marked objects (O1) and scans from there
295 // towards bottom direction, selecting the first non-marked object (O2).
296 // In case of success the marking of O1 is deleted, a marking is created at
297 // O2 and TRUE is returned. With the parameter bPrev=sal_True the scan
298 // direction is turned to the other direction.
299 bool MarkNextObj(bool bPrev=false);
300
301 // Selects the most upper of the marked objects which is hit by rPnt/nTol
302 // and scans from there to bottom direction, selecting the first non-marked
303 // object (O2). In case of success the marking of O1 is deleted, a marking
304 // is created at O2 and sal_True is returned. With the parameter
305 // bPrev=sal_True the scan direction is turned to the other direction.
306 bool MarkNextObj(const Point& rPnt, short nTol, bool bPrev);
307
308 // Mark all objects within a rectangular area
309 // Just objects are marked which are inclosed completely
310 void MarkObj(const tools::Rectangle& rRect, bool bUnmark);
311 void MarkObj(SdrObject* pObj, SdrPageView* pPV, bool bUnmark = false, bool bDoNoSetMarkHdl = false,
312 std::vector<basegfx::B2DRectangle> const & rSubSelections = std::vector<basegfx::B2DRectangle>());
313 void MarkAllObj(SdrPageView* pPV=nullptr); // pPage=NULL => all displayed pages
314 void UnmarkAllObj(SdrPageView const * pPV=nullptr); // pPage=NULL => all displayed pages
315
316 // This function is time-consuming intensive, as the MarkList has to be scanned.
317 bool IsObjMarked(SdrObject const * pObj) const;
318 void UnMarkAll(SdrPageView const * pPV=nullptr) { UnmarkAllObj(pPV); }
319
320 // Request/set the size of the marking handles. Declaration in Pixel.
321 // The value is meant to be the edge length ( link length ).
322 // Pair values are round up to impair values: 3->3, 4->5, 5->5, 6->7, 7->7, ...
323 // Default value is 7, minimum value is 3 Pixels.
324 sal_uInt16 GetMarkHdlSizePixel() const;
325 void SetMarkHdlSizePixel(sal_uInt16 nSiz);
326
327 virtual bool HasMarkablePoints() const;
328 virtual sal_Int32 GetMarkablePointCount() const;
329 virtual bool HasMarkedPoints() const;
330
331 // There might be points which can't be marked:
332 bool IsPointMarkable(const SdrHdl& rHdl) const;
333 virtual bool MarkPoint(SdrHdl& rHdl, bool bUnmark=false);
334
335 /** should only be used from outside svx for special ui elements */
336 bool MarkPointHelper(SdrHdl* pHdl, SdrMark* pMark, bool bUnmark);
337
338 bool UnmarkPoint(SdrHdl& rHdl) { return MarkPoint(rHdl,true); }
339 bool IsPointMarked(const SdrHdl& rHdl) const { ForceUndirtyMrkPnt(); return rHdl.IsSelected(); }
340 bool MarkAllPoints() { return MarkPoints(nullptr,false); }
341 bool UnmarkAllPoints() { return MarkPoints(nullptr,true); }
342
343 // Selects the first marked point (P1) which is hit by rPnt
344 // and from there it searches the first non-marked point(P2).
345 // In case of success the marking of
346 // P1 is deleted, a mark is set at P2.
347 void MarkNextPoint();
348
349 // Search for the number of the suitable handle. In case of empty search result,
350 // SAL_MAX_SIZE is returned.
351 size_t GetHdlNum(SdrHdl const * pHdl) const { return maHdlList.GetHdlNum(pHdl); }
352 SdrHdl* GetHdl(size_t nHdlNum) const { return maHdlList.GetHdl(nHdlNum); }
353 const SdrHdlList& GetHdlList() const { return maHdlList; }
354
355 // Draw a selection frame for marking of points.
356 // This routine will just be started in case that HasMarkablePoints() returns sal_True.
357 bool BegMarkPoints(const Point& rPnt, bool bUnmark = false);
358 void MovMarkPoints(const Point& rPnt);
359 bool EndMarkPoints();
360 void BrkMarkPoints();
361 bool IsMarkPoints() const { return (nullptr != mpMarkPointsOverlay); }
362
363 // Select that additional handles are displayed permanently.
364 void SetPlusHandlesAlwaysVisible(bool bOn);
365 bool IsPlusHandlesAlwaysVisible() const { return mbPlusHdlAlways; }
366
367 bool HasMarkableGluePoints() const;
368 bool HasMarkedGluePoints() const;
369
370 // A gluepoint is clearly identified by the SdrObject
371 // (to which it belongs) as well as by a sal_uInt16 nId (as each SdrObject may consist of
372 // several glue points. Here at the View there is an additional
373 // SdrPageView, which should be defined correctly always.
374 // Alternatively a gluepoint may be characterized by a SdrHdl.
375 // In this case the SdrHdl instance consists of all required information.
376 // And in this case, the glue point are always is marked by enforcement
377 // (Handlers are just situated at marked gluepoints )
378 // Attention: With each change of the glue point status the handle list is re-calculated.
379 // All previously saved SdrHdl* became invalid by this, the same with the point IDs!
380 bool PickGluePoint(const Point& rPnt, SdrObject*& rpObj, sal_uInt16& rnId, SdrPageView*& rpPV) const;
381 bool MarkGluePoint(const SdrObject* pObj, sal_uInt16 nId, bool bUnmark);
382 void UnmarkGluePoint(const SdrObject* pObj, sal_uInt16 nId) { MarkGluePoint(pObj,nId,true); }
383 bool IsGluePointMarked(const SdrObject* pObj, sal_uInt16 nId) const;
384
385 // Get the Hdl (handle) of a marked GluePoint. Non-marked
386 // GluePoints don`t have handles
387 SdrHdl* GetGluePointHdl(const SdrObject* pObj, sal_uInt16 nId) const;
388
389 // Mark all points within this rectangular (View coordinates)
390 bool MarkAllGluePoints() { return MarkGluePoints(nullptr,false); }
391 bool UnmarkAllGluePoints() { return MarkGluePoints(nullptr,true); }
392
393 // Selects the first marked point (P1) which is hit by rPnt
394 // and from there it searches the first non-marked point(P2).
395 // In case of success the marking of
396 // P1 is deleted, a mark is set at P2.
397 void MarkNextGluePoint();
398
399 // Draw a selection frame for glue point marking.
400 // This routine will just be started in case that HasMarkablePoints() returns sal_True.
401 // The GlueEditMode sal_True is disregarded.
402 // bool BegMarkGluePoints(const Point& rPnt, OutputDevice* pOut);
403 bool BegMarkGluePoints(const Point& rPnt, bool bUnmark = false);
404 void MovMarkGluePoints(const Point& rPnt);
405 void EndMarkGluePoints();
406 void BrkMarkGluePoints();
407 bool IsMarkGluePoints() const { return (nullptr != mpMarkGluePointsOverlay); }
408
409 // bRestraintPaint=sal_False causes the handles not to be drawn immediately.
410 // AdjustMarkHdl is just called in case of changes; usually this causes an Invalidate
411 // At the end of a redraw the handles are drawn automatically.
412 // The purpose is to avoid unnecessary flickering. -> This does not yet work, that's why sal_True!
413 void AdjustMarkHdl(SfxViewShell* pOtherShell = nullptr); //HMHBOOL bRestraintPaint=sal_True);
414
415 const tools::Rectangle& GetMarkedObjRect() const; // SnapRects of Objects, without line width
416 tools::Rectangle GetMarkedObjBoundRect() const; // incl. line width, overlapping rags, ...
417 const tools::Rectangle& GetMarkedPointsRect() const; // Enclosing rectangle of all marked points
418 const tools::Rectangle& GetMarkedGluePointsRect() const; // Enclosing rectangle of all marked glue points
419 const tools::Rectangle& GetAllMarkedRect() const { return GetMarkedObjRect(); }
420 tools::Rectangle GetAllMarkedBoundRect() const { return GetMarkedObjBoundRect(); }
421
422 // Will be always called, if the list of marked objects might be changed.
423 // If you override this method, be sure that you call the
424 // methods of the base class!
425 virtual void MarkListHasChanged();
426
427 // Entering (Editing) of a maybe marked object group. If there are several
428 // object groups marked, the most upper group is selected. After that
429 // all member objects of the group are directly accessible. All other
430 // objects may not be processed in the meantime (until the next
431 // LeaveGroup()). With markings which overlaps pages, every page is processed
432 // separately. The method returns sal_True, if at least one group was entered.
433 void EnterMarkedGroup();
434
435 // Rotation center point and start point of the axis of reflection, respectively
436 const Point& GetRef1() const { return maRef1; }
437 void SetRef1(const Point& rPt);
438
439 // End point of the axis of reflection
440 const Point& GetRef2() const { return maRef2; }
441 void SetRef2(const Point& rPt);
442 /// Get access to the view shell owning this draw view, if any.
443 virtual SfxViewShell* GetSfxViewShell() const;
444};
445
446
447// - Hit tolerances:
448// It has to be declared in logical coordinates. So please translate the
449// wanted pixel value with PixelToLogic in Logical values.
450// Taking as example a logical value of 100:
451// - For a horizontal hairline (Object with height 0), the generated data is +/-100, i.e.
452// a vertical area of 200 logical units is sensitive.
453// - For a polygon, a rectangular of the size (200,200) is generated and a
454// touch test between Poly and this Rect is processed.
455// - Objects which respond SdrObject::HasEdit()==TRUE ( e.g. a text frame ),
456// are specially treated: An additional sensitive area with a width of
457// 2*Tol (200 units for this example) is created around the object.
458// When an object is directly hit, the Edit method is called.
459// In opposite, a hit in the surrounding sensitive area enables Dragging.
460
461
462#endif // INCLUDED_SVX_SVDMRKV_HXX
463
464/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/bitmapex.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_VCL_BITMAPEX_HXX
21#define INCLUDED_VCL_BITMAPEX_HXX
22
23#include <vcl/dllapi.h>
24#include <vcl/alpha.hxx>
25#include <vcl/Scanline.hxx>
26#include <tools/color.hxx>
27
28#include <sal/types.h>
29
30namespace com::sun::star::rendering {
31 class XBitmapCanvas;
32}
33namespace com::sun::star::uno { template <class interface_type> class Reference; }
34namespace basegfx { class BColorModifierStack; }
35
36enum class TransparentType
37{
38 NONE,
39 Color,
40 Bitmap
41};
42
43class SAL_WARN_UNUSED__attribute__((warn_unused)) VCL_DLLPUBLIC__attribute__ ((visibility("default"))) BitmapEx
44{
45public:
46
47 BitmapEx();
48 explicit BitmapEx( const OUString& rIconName );
49 BitmapEx( const BitmapEx& rBitmapEx );
50 BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize );
51 BitmapEx( Size aSize, sal_uInt16 nBitCount );
52 explicit BitmapEx( const Bitmap& rBmp );
53 BitmapEx( const Bitmap& rBmp, const Bitmap& rMask );
54 BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask );
55 BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor );
56
57 BitmapEx& operator=( const BitmapEx& rBitmapEx );
58 BitmapEx& operator=( const Bitmap& rBitmap ) { return operator=(BitmapEx(rBitmap)); }
59 bool operator==( const BitmapEx& rBitmapEx ) const;
60 bool operator!=( const BitmapEx& rBitmapEx ) const { return !(*this==rBitmapEx); }
61 bool operator!() const { return !maBitmap; }
9
Calling 'Bitmap::operator!'
19
Returning from 'Bitmap::operator!'
20
Returning the value 1, which participates in a condition later
62
63 bool IsEmpty() const;
64 void SetEmpty();
65 void Clear();
66
67 void Draw( OutputDevice* pOutDev,
68 const Point& rDestPt ) const;
69 void Draw( OutputDevice* pOutDev,
70 const Point& rDestPt, const Size& rDestSize ) const;
71
72 bool IsTransparent() const;
73 TransparentType GetTransparentType() const { return meTransparent; }
74
75 Bitmap GetBitmap( Color aTransparentReplaceColor ) const;
76 /// Gives direct access to the contained bitmap.
77 const Bitmap& GetBitmap() const;
78 Bitmap GetMask() const;
79
80 bool IsAlpha() const;
81 AlphaMask GetAlpha() const;
82
83 const Size& GetSizePixel() const { return maBitmapSize; }
84 void SetSizePixel(const Size& rNewSize);
85
86 const Size& GetPrefSize() const { return maBitmap.GetPrefSize(); }
87 void SetPrefSize( const Size& rPrefSize ) { maBitmap.SetPrefSize( rPrefSize ); }
88
89 const MapMode& GetPrefMapMode() const { return maBitmap.GetPrefMapMode(); }
90 void SetPrefMapMode( const MapMode& rPrefMapMode ) { maBitmap.SetPrefMapMode( rPrefMapMode ); }
91
92 const Color& GetTransparentColor() const { return maTransparentColor; }
93
94 sal_uInt16 GetBitCount() const { return maBitmap.GetBitCount(); }
95 sal_uLong GetSizeBytes() const;
96 BitmapChecksum GetChecksum() const;
97
98 /** Convert bitmap format
99
100 @param eConversion
101 The format this bitmap should be converted to.
102
103 @return true, if the conversion was completed successfully.
104 */
105 bool Convert( BmpConversion eConversion );
106
107 /** Crop the bitmap
108
109 @param rRectPixel
110 A rectangle specifying the crop amounts on all four sides of
111 the bitmap. If the upper left corner of the bitmap is assigned
112 (0,0), then this method cuts out the given rectangle from the
113 bitmap. Note that the rectangle is clipped to the bitmap's
114 dimension, i.e. negative left,top rectangle coordinates or
115 exceeding width or height is ignored.
116
117 @return true, if cropping was performed successfully. If
118 nothing had to be cropped, because e.g. the crop rectangle
119 included the bitmap, false is returned, too!
120 */
121 bool Crop( const tools::Rectangle& rRectPixel );
122
123 /** Expand the bitmap by pixel padding
124
125 @param nDX
126 Number of pixel to pad at the right border of the bitmap
127
128 @param nDY
129 Number of scanlines to pad at the bottom border of the bitmap
130
131 @param bExpandTransparent
132 Whether to expand the transparency color or not.
133 */
134 void Expand(
135 sal_uLong nDX, sal_uLong nDY,
136 bool bExpandTransparent = false );
137
138 /** Copy a rectangular area from another bitmap
139
140 @param rRectDst
141 Destination rectangle in this bitmap. This is clipped to the
142 bitmap dimensions.
143
144 @param rRectSrc
145 Source rectangle in pBmpSrc. This is clipped to the source
146 bitmap dimensions. Note further that no scaling takes place
147 during this copy operation, i.e. only the minimum of source
148 and destination rectangle's width and height are used.
149
150 @param pBmpExSrc
151 The source bitmap to copy from. If this argument is NULL, or
152 equal to the object this method is called on, copying takes
153 place within the same bitmap.
154
155 @return true, if the operation completed successfully. false
156 is not only returned when the operation failed, but also if
157 nothing had to be done, e.g. because one of the rectangles are
158 empty.
159 */
160 bool CopyPixel(
161 const tools::Rectangle& rRectDst,
162 const tools::Rectangle& rRectSrc,
163 const BitmapEx* pBmpExSrc );
164
165 /** Fill the entire bitmap with the given color
166
167 @param rFillColor
168 Color value to use for filling. Set the transparency part of
169 the color to fill the mask.
170
171 @return true, if the operation was completed successfully.
172 */
173 bool Erase( const Color& rFillColor );
174
175 /** Perform the Invert operation on every pixel
176
177 @return true, if the operation was completed successfully.
178 */
179 bool Invert();
180
181 /** Mirror the bitmap
182
183 @param nMirrorFlags
184 About which axis (horizontal, vertical, or both) to mirror
185
186 @return true, if the operation was completed successfully.
187 */
188 bool Mirror( BmpMirrorFlags nMirrorFlags );
189
190 /** Scale the bitmap
191
192 @param rNewSize
193 The resulting size of the scaled bitmap
194
195 @param nScaleFlag
196 The algorithm to be used for scaling
197
198 @return true, if the operation was completed successfully.
199 */
200 bool Scale(
201 const Size& rNewSize,
202 BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
203
204 /** Scale the bitmap
205
206 @param rScaleX
207 The scale factor in x direction.
208
209 @param rScaleY
210 The scale factor in y direction.
211
212 @param nScaleFlag
213 The algorithm to be used for scaling
214
215 @return true, if the operation was completed successfully.
216 */
217 bool Scale(
218 const double& rScaleX,
219 const double& rScaleY,
220 BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
221
222 /** Rotate bitmap by the specified angle
223
224 @param nAngle10
225 The rotation angle in tenth of a degree. The bitmap is always rotated around its center.
226
227 @param rFillColor
228 The color to use for filling blank areas. During rotation, the
229 bitmap is enlarged such that the whole rotation result fits
230 in. The empty spaces around that rotated original bitmap are
231 then filled with this color.
232
233 @return true, if the operation was completed successfully.
234 */
235 bool Rotate(
236 long nAngle10,
237 const Color& rFillColor );
238
239 /** Replace all pixel having the search color with the specified color
240
241 @param rSearchColor
242 Color specifying which pixel should be replaced
243
244 @param rReplaceColor
245 Color to be placed in all changed pixel
246 */
247 void Replace(
248 const Color& rSearchColor,
249 const Color& rReplaceColor );
250
251 /** Replace all pixel having the search color with the specified color
252
253 @param rSearchColor
254 Color specifying which pixel should be replaced
255
256 @param rReplaceColor
257 Color to be placed in all changed pixel
258
259 @param nTolerance
260 Tolerance value. Specifies the maximal difference between
261 rSearchColor and the individual pixel values, such that the
262 corresponding pixel is still regarded a match.
263 */
264 void Replace(
265 const Color& rSearchColor,
266 const Color& rReplaceColor,
267 sal_uInt8 nTolerance );
268
269 /** Replace all pixel having one the search colors with the corresponding replace color
270
271 @param pSearchColors
272 Array of colors specifying which pixel should be replaced
273
274 @param pReplaceColors
275 Array of colors to be placed in all changed pixel
276
277 @param nColorCount
278 Size of the aforementioned color arrays
279
280 @param pTols
281 Tolerance value. Specifies the maximal difference between
282 pSearchColor colors and the individual pixel values, such that
283 the corresponding pixel is still regarded a match.
284 */
285 void Replace(
286 const Color* pSearchColors,
287 const Color* pReplaceColors,
288 sal_uLong nColorCount );
289
290 /** Replace all pixel having one the search colors with the corresponding replace color
291
292 @param pSearchColors
293 Array of colors specifying which pixel should be replaced
294
295 @param rReplaceColors
296 Array of colors to be placed in all changed pixel
297
298 @param nColorCount
299 Size of the aforementioned color arrays
300
301 @param pTols
302 Tolerance value. Specifies the maximal difference between
303 pSearchColor colors and the individual pixel values, such that
304 the corresponding pixel is still regarded a match.
305
306 @return true, if the operation was completed successfully.
307 */
308 void Replace(
309 const Color* pSearchColors,
310 const Color* pReplaceColors,
311 sal_uLong nColorCount,
312 sal_uInt8 const * pTols );
313
314 /** Replace transparency with given color.
315 */
316 void ReplaceTransparency( const Color& rColor );
317
318 /** Get contours in image */
319 tools::Polygon GetContour( bool bContourEdgeDetect, const tools::Rectangle* pWorkRect );
320
321 /** Change various global color characteristics
322
323 @param nLuminancePercent
324 Percent of luminance change, valid range [-100,100]. Values outside this range are clipped to the valid range.
325
326 @param nContrastPercent
327 Percent of contrast change, valid range [-100,100]. Values outside this range are clipped to the valid range.
328
329 @param nChannelRPercent
330 Percent of red channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
331
332 @param nChannelGPercent
333 Percent of green channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
334
335 @param nChannelBPercent
336 Percent of blue channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
337
338 @param fGamma
339 Exponent of the gamma function applied to the bitmap. The
340 value 1.0 results in no change, the valid range is
341 (0.0,10.0]. Values outside this range are regarded as 1.0.
342
343 @param bInvert
344 If true, invert the channel values with the logical 'not' operator
345
346 @param msoBrightness
347 Use the same formula for brightness as used by MSOffice.
348
349 @return true, if the operation was completed successfully.
350 */
351 bool Adjust(
352 short nLuminancePercent,
353 short nContrastPercent,
354 short nChannelRPercent,
355 short nChannelGPercent,
356 short nChannelBPercent,
357 double fGamma = 1.0,
358 bool bInvert = false,
359 bool msoBrightness = false );
360
361 /** Get transparency at given position
362
363 @param nX
364 integer X-Position in Bitmap
365
366 @param nY
367 integer Y-Position in Bitmap
368
369 @return transparency value in the range of [0 .. 255] where
370 0 is not transparent, 255 is fully transparent
371 */
372 sal_uInt8 GetTransparency(
373 sal_Int32 nX,
374 sal_Int32 nY) const;
375
376 /** Get pixel color (including alpha) at given position
377
378 @param nX
379 integer X-Position in Bitmap
380
381 @param nY
382 integer Y-Position in Bitmap
383 */
384 ::Color GetPixelColor(
385 sal_Int32 nX,
386 sal_Int32 nY) const;
387
388 /** Create transformed Bitmap
389
390 @param fWidth
391 The target width in pixels
392
393 @param fHeight
394 The target height in pixels
395
396 @param rTransformation
397 The back transformation for each pixel in (0 .. fWidth),(0 .. fHeight) to
398 local pixel coordinates
399 */
400 [[nodiscard]]
401 BitmapEx TransformBitmapEx(
402 double fWidth,
403 double fHeight,
404 const basegfx::B2DHomMatrix& rTransformation) const;
405
406 /** Create transformed Bitmap
407
408 @param rTransformation
409 The transformation from unit coordinates to the unit range
410
411 @param rVisibleRange
412 The relative visible range in unit coordinates, relative to (0,0,1,1) which
413 defines the whole target area
414
415 @param fMaximumArea
416 A limitation for the maximum size of pixels to use for the result
417
418 The target size of the result bitmap is defined by transforming the given
419 rTargetRange with the given rTransformation; the area of the result is
420 linearly scaled to not exceed the given fMaximumArea
421
422 @return The transformed bitmap
423 */
424 [[nodiscard]]
425 BitmapEx getTransformed(
426 const basegfx::B2DHomMatrix& rTransformation,
427 const basegfx::B2DRange& rVisibleRange,
428 double fMaximumArea) const;
429
430 /** Create ColorStack-modified version of this BitmapEx
431
432 @param rBColorModifierStack
433 A ColrModifierStack which defines how each pixel has to be modified
434 */
435 [[nodiscard]]
436 BitmapEx ModifyBitmapEx( const basegfx::BColorModifierStack& rBColorModifierStack) const;
437
438 [[nodiscard]]
439 static BitmapEx AutoScaleBitmap( BitmapEx const & aBitmap, const long aStandardSize );
440
441 /// populate from a canvas implementation
442 bool Create(
443 const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas,
444 const Size &rSize );
445
446 void setAlphaFrom( sal_uInt8 cIndexFrom, sal_Int8 nAlphaTo );
447
448 void AdjustTransparency( sal_uInt8 cTrans );
449
450 void CombineMaskOr(Color maskColor, sal_uInt8 nTol);
451
452 /**
453 * Retrieves the color model data we need for the XImageConsumer stuff.
454 */
455 void GetColorModel(css::uno::Sequence< sal_Int32 >& rRGBPalette,
456 sal_uInt32& rnRedMask, sal_uInt32& rnGreenMask, sal_uInt32& rnBlueMask, sal_uInt32& rnAlphaMask, sal_uInt32& rnTransparencyIndex,
457 sal_uInt32& rnWidth, sal_uInt32& rnHeight, sal_uInt8& rnBitCount);
458
459 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) std::shared_ptr<SalBitmap> const & ImplGetBitmapSalBitmap() const { return maBitmap.ImplGetSalBitmap(); }
460 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) std::shared_ptr<SalBitmap> const & ImplGetMaskSalBitmap() const { return maMask.ImplGetSalBitmap(); }
461
462
463private:
464 friend class ImpGraphic;
465 friend class OutputDevice;
466 friend bool VCL_DLLPUBLIC__attribute__ ((visibility("default"))) WriteDIBBitmapEx(const BitmapEx& rSource, SvStream& rOStm);
467 friend bool VCL_DLLPUBLIC__attribute__ ((visibility("default"))) ReadRawDIB(BitmapEx& rTarget, const unsigned char* pBuf,
468 const ScanlineFormat nFormat,
469 const int nHeight,
470 const int nStride);
471
472 void loadFromIconTheme( const OUString& rIconName );
473
474 Bitmap maBitmap;
475 Bitmap maMask;
476 Size maBitmapSize;
477 Color maTransparentColor;
478 TransparentType meTransparent;
479 bool mbAlpha;
480
481};
482
483
484/** Create a blend frame as BitmapEx
485
486 @param nAlpha
487 The blend value defines how strong the frame will be blended with the
488 existing content, 255 == full coverage, 0 == no frame will be drawn
489
490 @param aColorTopLeft, aColorBottomRight
491 The colors defining the frame. These colors are linearly interpolated from
492 aColorTopLeft and aColorBottomRight using the width and height of the area
493
494 @param rSize
495 The size of the frame in pixels
496 */
497BitmapEx VCL_DLLPUBLIC__attribute__ ((visibility("default"))) createBlendFrame(
498 const Size& rSize,
499 sal_uInt8 nAlpha,
500 Color aColorTopLeft,
501 Color aColorBottomRight);
502
503
504/** Create a blend frame as BitmapEx
505
506 @param nAlpha
507 The blend value defines how strong the frame will be blended with the
508 existing content, 255 == full coverage, 0 == no frame will be drawn
509
510 @param aColorTopLeft, aColorBottomRight, aColorTopRight, aColorBottomLeft
511 The colors defining the frame.
512
513 @param rSize
514 The size of the frame in pixels
515 */
516BitmapEx createBlendFrame(
517 const Size& rSize,
518 sal_uInt8 nAlpha,
519 Color aColorTopLeft,
520 Color aColorTopRight,
521 Color aColorBottomRight,
522 Color aColorBottomLeft);
523
524#endif // INCLUDED_VCL_BITMAPEX_HXX
525
526/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/bitmap.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_VCL_BITMAP_HXX
21#define INCLUDED_VCL_BITMAP_HXX
22
23#include <tools/solar.h>
24#include <vcl/checksum.hxx>
25#include <vcl/dllapi.h>
26#include <vcl/mapmod.hxx>
27#include <vcl/region.hxx>
28#include <vcl/scopedbitmapaccess.hxx>
29#include <o3tl/typed_flags_set.hxx>
30#include <memory>
31
32class Color;
33
34template <typename Arg, typename Ret> class Link;
35
36enum class BmpMirrorFlags
37{
38 NONE = 0x00,
39 Horizontal = 0x01,
40 Vertical = 0x02,
41};
42
43namespace o3tl
44{
45 template<> struct typed_flags<BmpMirrorFlags> : is_typed_flags<BmpMirrorFlags, 0x03> {};
46}
47
48enum class BmpScaleFlag
49{
50// Try to preferably use these.
51 Default,
52 Fast,
53 BestQuality,
54// Specific algorithms, use only if you really need to (mainly used for tests)
55 NearestNeighbor,
56 Interpolate, // fast, integer bilinear
57 Lanczos,
58 BiCubic,
59 BiLinear,
60 Super // bilinear interpolation when supersampling and averaging when subsampling under certain scale
61};
62
63#define BMP_COL_TRANSColor( 252, 3, 251 ) Color( 252, 3, 251 )
64
65enum class BmpConversion
66{
67 NNONE,
68 N1BitThreshold,
69 N4BitGreys,
70 N4BitColors,
71 N8BitGreys,
72 N8BitColors,
73 N24Bit,
74 N32Bit,
75 N8BitTrans,
76 N8BitNoConversion // make 8bit without color conversion (e.g. take the red channel)
77};
78
79enum class BmpCombine
80{
81 Or, And
82};
83
84class BitmapInfoAccess;
85class BitmapReadAccess;
86class BitmapWriteAccess;
87class BitmapPalette;
88class GDIMetaFile;
89class AlphaMask;
90class OutputDevice;
91class SalBitmap;
92
93struct BitmapSystemData
94{
95 #if defined(_WIN32)
96 void* pDIB; // device independent byte buffer
97 #elif defined( MACOSX ) || defined( IOS )
98 // Nothing needed, apparently
99 #else
100 void* aPixmap;
101 #endif
102 int mnWidth;
103 int mnHeight;
104};
105
106class SAL_WARN_UNUSED__attribute__((warn_unused)) VCL_DLLPUBLIC__attribute__ ((visibility("default"))) Bitmap
107{
108public:
109
110 Bitmap();
111 Bitmap( const Bitmap& rBitmap );
112 Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal = nullptr );
113 explicit Bitmap( std::shared_ptr<SalBitmap> const & xSalBitmap );
114 virtual ~Bitmap();
115
116 Bitmap& operator=( const Bitmap& rBitmap );
117 Bitmap& operator=( Bitmap&& rBitmap ) noexcept;
118 inline bool operator!() const;
119 bool operator==( const Bitmap& rBitmap ) const;
120 bool operator!=( const Bitmap& rBitmap ) const { return !operator==(rBitmap); }
121
122 inline bool IsEmpty() const;
123 void SetEmpty();
124
125 inline const MapMode& GetPrefMapMode() const;
126 inline void SetPrefMapMode( const MapMode& rMapMode );
127
128 inline const Size& GetPrefSize() const;
129 inline void SetPrefSize( const Size& rSize );
130
131 Size GetSizePixel() const;
132
133 sal_uInt16 GetBitCount() const;
134 inline sal_Int64 GetColorCount() const;
135 inline sal_uLong GetSizeBytes() const;
136 bool HasGreyPalette8Bit() const;
137 bool HasGreyPaletteAny() const;
138 /** get system dependent bitmap data
139
140 @param rData
141 The system dependent BitmapSystemData structure to be filled
142
143 @return true if the bitmap has a valid system object (e.g. not empty)
144 */
145 bool GetSystemData( BitmapSystemData& rData ) const;
146
147 BitmapChecksum GetChecksum() const;
148
149 Bitmap CreateDisplayBitmap( OutputDevice* pDisplay ) const;
150
151 static const BitmapPalette&
152 GetGreyPalette( int nEntries );
153
154public:
155
156 /** Convert bitmap format
157
158 @param eConversion
159 The format this bitmap should be converted to.
160
161 @return true the conversion was completed successfully.
162 */
163 bool Convert( BmpConversion eConversion );
164
165 /** Apply a Floyd dither algorithm to the bitmap
166
167 This method dithers the bitmap inplace, i.e. a true color
168 bitmap is converted to a paletted bitmap, reducing the color
169 deviation by error diffusion.
170
171 */
172 bool Dither();
173
174 /** Crop the bitmap
175
176 @param rRectPixel
177 A rectangle specifying the crop amounts on all four sides of
178 the bitmap. If the upper left corner of the bitmap is assigned
179 (0,0), then this method cuts out the given rectangle from the
180 bitmap. Note that the rectangle is clipped to the bitmap's
181 dimension, i.e. negative left,top rectangle coordinates or
182 exceeding width or height is ignored.
183
184 @return true cropping was performed successfully. If
185 nothing had to be cropped, because e.g. the crop rectangle
186 included the bitmap, false is returned, too!
187 */
188 bool Crop( const tools::Rectangle& rRectPixel );
189
190 /** Expand the bitmap by pixel padding
191
192 @param nDX
193 Number of pixel to pad at the right border of the bitmap
194
195 @param nDY
196 Number of scanlines to pad at the bottom border of the bitmap
197
198 @param pInitColor
199 Color to use for padded pixel
200
201 @return true, if padding was performed successfully. false is
202 not only returned when the operation failed, but also if
203 nothing had to be done, e.g. because nDX and nDY were zero.
204 */
205 bool Expand(
206 sal_uLong nDX, sal_uLong nDY,
207 const Color* pInitColor = nullptr );
208
209 /** Copy a rectangular area from another bitmap
210
211 @param rRectDst
212 Destination rectangle in this bitmap. This is clipped to the
213 bitmap dimensions.
214
215 @param rRectSrc
216 Source rectangle in pBmpSrc. This is clipped to the source
217 bitmap dimensions. Note further that no scaling takes place
218 during this copy operation, i.e. only the minimum of source
219 and destination rectangle's width and height are used.
220
221 @param pBmpSrc
222 The source bitmap to copy from. If this argument is NULL, or
223 equal to the object this method is called on, copying takes
224 place within the same bitmap.
225
226 @return true, if the operation completed successfully. false
227 is not only returned when the operation failed, but also if
228 nothing had to be done, e.g. because one of the rectangles are
229 empty.
230 */
231 bool CopyPixel(
232 const tools::Rectangle& rRectDst,
233 const tools::Rectangle& rRectSrc,
234 const Bitmap* pBmpSrc = nullptr );
235
236 bool CopyPixel_AlphaOptimized(
237 const tools::Rectangle& rRectDst,
238 const tools::Rectangle& rRectSrc,
239 const Bitmap* pBmpSrc );
240
241 /** Perform boolean operations with another bitmap
242
243 @param rMask
244 The mask bitmap in the selected combine operation
245
246 @param eCombine
247 The combine operation to perform on the bitmap
248
249 @return true, if the operation was completed successfully.
250 */
251 bool CombineSimple(
252 const Bitmap& rMask,
253 BmpCombine eCombine );
254
255 /** Alpha-blend the given bitmap against a specified uniform
256 background color.
257
258 @attention This method might convert paletted bitmaps to
259 truecolor, to be able to represent every necessary color. Note
260 that during alpha blending, lots of colors not originally
261 included in the bitmap can be generated.
262
263 @param rAlpha
264 Alpha mask to blend with
265
266 @param rBackgroundColor
267 Background color to use for every pixel during alpha blending
268
269 @return true, if blending was successful, false otherwise
270 */
271 bool Blend(
272 const AlphaMask& rAlpha,
273 const Color& rBackgroundColor );
274
275 /** Fill the entire bitmap with the given color
276
277 @param rFillColor
278 Color value to use for filling
279
280 @return true, if the operation was completed successfully.
281 */
282 bool Erase( const Color& rFillColor );
283
284 /** Perform the Invert operation on every pixel
285
286 @return true, if the operation was completed successfully.
287 */
288 bool Invert();
289
290 /** Mirror the bitmap
291
292 @param nMirrorFlags
293 About which axis (horizontal, vertical, or both) to mirror
294
295 @return true, if the operation was completed successfully.
296 */
297 bool Mirror( BmpMirrorFlags nMirrorFlags );
298
299 /** Scale the bitmap
300
301 @param rNewSize
302 The resulting size of the scaled bitmap
303
304 @param nScaleFlag
305 The algorithm to be used for scaling
306
307 @return true, if the operation was completed successfully.
308 */
309 bool Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
310
311 /** Scale the bitmap
312
313 @param rScaleX
314 The scale factor in x direction.
315
316 @param rScaleY
317 The scale factor in y direction.
318
319 @param nScaleFlag
320 Method of scaling - it is recommended that either BmpScaleFlag::Default or BmpScaleFlag::BestQuality be used.
321
322 @return true, if the operation was completed successfully.
323 */
324 bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag = BmpScaleFlag::Default );
325
326 /**
327 Returns true if bitmap scaling is considered to be fast.
328
329 Currently this returns true if OpenGL is used for scaling, otherwise false (CPU scaling is slower).
330
331 @since 4.5
332 */
333 static bool HasFastScale();
334
335 // Adapt the BitCount of rNew to BitCount of total, including grey or color palette
336 // Can be used to create alpha/mask bitmaps after their processing in 24bit
337 void AdaptBitCount(Bitmap& rNew) const;
338
339 /** Rotate bitmap by the specified angle
340
341 @param nAngle10
342 The rotation angle in tenth of a degree. The bitmap is always rotated around its center.
343
344 @param rFillColor
345 The color to use for filling blank areas. During rotation, the
346 bitmap is enlarged such that the whole rotation result fits
347 in. The empty spaces around that rotated original bitmap are
348 then filled with this color.
349
350 @return true, if the operation was completed successfully.
351 */
352 bool Rotate( long nAngle10, const Color& rFillColor );
353
354 /** Create on-off mask from bitmap
355
356 This method creates a bitmask from the bitmap, where every
357 pixel that equals rTransColor is set transparent, the rest
358 opaque.
359
360 @param rTransColor
361 Color value where the bitmask should be transparent
362
363 @param nTol
364 Tolerance value. Specifies the maximal difference between
365 rTransColor and the individual pixel values, such that the
366 corresponding pixel is still regarded as transparent.
367
368 @return the resulting bitmask.
369 */
370 Bitmap CreateMask( const Color& rTransColor, sal_uInt8 nTol = 0 ) const;
371
372 /** Create region of similar colors in a given rectangle
373
374 @param rColor
375 All pixel which have this color are included in the calculated region
376
377 @param rRect
378 The rectangle within which matching pixel are looked for. This
379 rectangle is always clipped to the bitmap dimensions.
380
381 @return the generated region.
382 */
383 vcl::Region CreateRegion( const Color& rColor, const tools::Rectangle& rRect ) const;
384
385 /** Replace all pixel where the given mask is on with the specified color
386
387 @param rMask
388 Mask specifying which pixel should be replaced
389
390 @param rReplaceColor
391 Color to be placed in all changed pixel
392
393 @return true, if the operation was completed successfully.
394 */
395 bool Replace( const Bitmap& rMask, const Color& rReplaceColor );
396
397 /** Merge bitmap with given background color according to specified alpha mask
398
399 @param rAlpha
400 Alpha mask specifying the amount of background color to merge in
401
402 @param rMergeColor
403 Background color to be used for merging
404
405 @return true, if the operation was completed successfully.
406 */
407 bool Replace( const AlphaMask& rAlpha, const Color& rMergeColor );
408
409 /** Replace all pixel having the search color with the specified color
410
411 @param rSearchColor
412 Color specifying which pixel should be replaced
413
414 @param rReplaceColor
415 Color to be placed in all changed pixel
416
417 @param nTol
418 Tolerance value. Specifies the maximal difference between
419 rSearchColor and the individual pixel values, such that the
420 corresponding pixel is still regarded a match.
421
422 @return true, if the operation was completed successfully.
423 */
424 bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol = 0 );
425
426 /** Replace all pixel having one the search colors with the corresponding replace color
427
428 @param pSearchColors
429 Array of colors specifying which pixel should be replaced
430
431 @param rReplaceColors
432 Array of colors to be placed in all changed pixel
433
434 @param nColorCount
435 Size of the aforementioned color arrays
436
437 @param pTols
438 Tolerance value. Specifies the maximal difference between
439 pSearchColor colors and the individual pixel values, such that
440 the corresponding pixel is still regarded a match.
441
442 @return true, if the operation was completed successfully.
443 */
444 bool Replace(
445 const Color* pSearchColors,
446 const Color* rReplaceColors,
447 sal_uLong nColorCount,
448 sal_uInt8 const * pTols );
449
450 /** Convert the bitmap to a meta file
451
452 This works by putting continuous areas of the same color into
453 polygons painted in this color, by tracing the area's bounding
454 line.
455
456 @param rMtf
457 The resulting meta file
458
459 @param cReduce
460 If non-null, minimal size of bound rects for individual polygons. Smaller ones are ignored.
461
462 @param pProgress
463 A callback for showing the progress of the vectorization
464 */
465 void Vectorize(
466 GDIMetaFile& rMtf,
467 sal_uInt8 cReduce,
468 const Link<long,void>* pProgress );
469
470 /** Change various global color characteristics
471
472 @param nLuminancePercent
473 Percent of luminance change, valid range [-100,100]. Values outside this range are clipped to the valid range.
474
475 @param nContrastPercent
476 Percent of contrast change, valid range [-100,100]. Values outside this range are clipped to the valid range.
477
478 @param nChannelRPercent
479 Percent of red channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
480
481 @param nChannelGPercent
482 Percent of green channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
483
484 @param nChannelBPercent
485 Percent of blue channel change, valid range [-100,100]. Values outside this range are clipped to the valid range.
486
487 @param fGamma
488 Exponent of the gamma function applied to the bitmap. The
489 value 1.0 results in no change, the valid range is
490 (0.0,10.0]. Values outside this range are regarded as 1.0.
491
492 @param bInvert
493 If true, invert the channel values with the logical 'not' operator
494
495 @param msoBrightness
496 Use the same formula for brightness as used by MSOffice.
497
498 @return true, if the operation was completed successfully.
499 */
500 bool Adjust(
501 short nLuminancePercent,
502 short nContrastPercent = 0,
503 short nChannelRPercent = 0,
504 short nChannelGPercent = 0,
505 short nChannelBPercent = 0,
506 double fGamma = 1.0,
507 bool bInvert = false,
508 bool msoBrightness = false );
509
510public:
511 /** ReassignWithSize and recalculate bitmap.
512
513 ReassignWithSizes the bitmap, and recalculates the bitmap size based on the new bitmap.
514
515 @param rBitmap Bitmap to reassign and use for size calculation
516 */
517 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ReassignWithSize(const Bitmap& rBitmap);
518
519 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ImplMakeUnique();
520 const std::shared_ptr<SalBitmap>& ImplGetSalBitmap() const { return mxSalBmp; }
521 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) void ImplSetSalBitmap( const std::shared_ptr<SalBitmap>& xImpBmp );
522
523 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool ImplMakeGreyscales( sal_uInt16 nGreyscales );
524
525public:
526
527 BitmapInfoAccess* AcquireInfoAccess();
528 BitmapReadAccess* AcquireReadAccess();
529 BitmapWriteAccess* AcquireWriteAccess();
530 static void ReleaseAccess( BitmapInfoAccess* pAccess );
531
532 typedef vcl::ScopedBitmapAccess<BitmapReadAccess, Bitmap, &Bitmap::AcquireReadAccess> ScopedReadAccess;
533 typedef vcl::ScopedBitmapAccess<BitmapInfoAccess, Bitmap, &Bitmap::AcquireInfoAccess> ScopedInfoAccess;
534
535private:
536 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool ImplConvertUp(sal_uInt16 nBitCount, Color const* pExtColor = nullptr);
537 SAL_DLLPRIVATE__attribute__ ((visibility("hidden"))) bool ImplConvertDown(sal_uInt16 nBitCount, Color const* pExtColor = nullptr);
538
539private:
540 std::shared_ptr<SalBitmap> mxSalBmp;
541 MapMode maPrefMapMode;
542 Size maPrefSize;
543
544};
545
546inline bool Bitmap::operator!() const
547{
548 return( mxSalBmp == nullptr );
10
Calling 'operator==<SalBitmap>'
17
Returning from 'operator==<SalBitmap>'
18
Returning the value 1, which participates in a condition later
549}
550
551inline bool Bitmap::IsEmpty() const
552{
553 return( mxSalBmp == nullptr );
554}
555
556inline const MapMode& Bitmap::GetPrefMapMode() const
557{
558 return maPrefMapMode;
559}
560
561inline void Bitmap::SetPrefMapMode( const MapMode& rMapMode )
562{
563 maPrefMapMode = rMapMode;
564}
565
566inline const Size& Bitmap::GetPrefSize() const
567{
568 return maPrefSize;
569}
570
571inline void Bitmap::SetPrefSize( const Size& rSize )
572{
573 maPrefSize = rSize;
574}
575
576inline sal_Int64 Bitmap::GetColorCount() const
577{
578 return sal_Int64(1) << sal_Int64(GetBitCount());
579}
580
581inline sal_uLong Bitmap::GetSizeBytes() const
582{
583 const Size aSizePix( GetSizePixel() );
584 return( ( static_cast<sal_uLong>(aSizePix.Width()) * aSizePix.Height() * GetBitCount() ) >> 3 );
585}
586
587#endif // INCLUDED_VCL_BITMAP_HXX
588
589/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

1// shared_ptr and weak_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2007-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// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_H1
50#define _SHARED_PTR_H1 1
51
52#include <bits/shared_ptr_base.h>
53
54namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
57
58 /**
59 * @addtogroup pointer_abstractions
60 * @{
61 */
62
63 // 20.7.2.2.11 shared_ptr I/O
64
65 /// Write the stored pointer to an ostream.
66 /// @relates shared_ptr
67 template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
68 inline std::basic_ostream<_Ch, _Tr>&
69 operator<<(std::basic_ostream<_Ch, _Tr>& __os,
70 const __shared_ptr<_Tp, _Lp>& __p)
71 {
72 __os << __p.get();
73 return __os;
74 }
75
76 template<typename _Del, typename _Tp, _Lock_policy _Lp>
77 inline _Del*
78 get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
79 {
80#if __cpp_rtti199711L
81 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
82#else
83 return 0;
84#endif
85 }
86
87 /// 20.7.2.2.10 shared_ptr get_deleter
88
89 /// If `__p` has a deleter of type `_Del`, return a pointer to it.
90 /// @relates shared_ptr
91 template<typename _Del, typename _Tp>
92 inline _Del*
93 get_deleter(const shared_ptr<_Tp>& __p) noexcept
94 {
95#if __cpp_rtti199711L
96 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
97#else
98 return 0;
99#endif
100 }
101
102 /**
103 * @brief A smart pointer with reference-counted copy semantics.
104 *
105 * A `shared_ptr` object is either empty or _owns_ a pointer passed
106 * to the constructor. Copies of a `shared_ptr` share ownership of
107 * the same pointer. When the last `shared_ptr` that owns the pointer
108 * is destroyed or reset, the owned pointer is freed (either by `delete`
109 * or by invoking a custom deleter that was passed to the constructor).
110 *
111 * A `shared_ptr` also stores another pointer, which is usually
112 * (but not always) the same pointer as it owns. The stored pointer
113 * can be retrieved by calling the `get()` member function.
114 *
115 * The equality and relational operators for `shared_ptr` only compare
116 * the stored pointer returned by `get()`, not the owned pointer.
117 * To test whether two `shared_ptr` objects share ownership of the same
118 * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
119 */
120 template<typename _Tp>
121 class shared_ptr : public __shared_ptr<_Tp>
122 {
123 template<typename... _Args>
124 using _Constructible = typename enable_if<
125 is_constructible<__shared_ptr<_Tp>, _Args...>::value
126 >::type;
127
128 template<typename _Arg>
129 using _Assignable = typename enable_if<
130 is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
131 >::type;
132
133 public:
134
135 /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
136 using element_type = typename __shared_ptr<_Tp>::element_type;
137
138#if __cplusplus201703L >= 201703L
139# define __cpp_lib_shared_ptr_weak_type201606 201606
140 /// The corresponding weak_ptr type for this shared_ptr
141 using weak_type = weak_ptr<_Tp>;
142#endif
143 /**
144 * @brief Construct an empty %shared_ptr.
145 * @post use_count()==0 && get()==0
146 */
147 constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
148
149 shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
150
151 /**
152 * @brief Construct a %shared_ptr that owns the pointer @a __p.
153 * @param __p A pointer that is convertible to element_type*.
154 * @post use_count() == 1 && get() == __p
155 * @throw std::bad_alloc, in which case @c delete @a __p is called.
156 */
157 template<typename _Yp, typename = _Constructible<_Yp*>>
158 explicit
159 shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
160
161 /**
162 * @brief Construct a %shared_ptr that owns the pointer @a __p
163 * and the deleter @a __d.
164 * @param __p A pointer.
165 * @param __d A deleter.
166 * @post use_count() == 1 && get() == __p
167 * @throw std::bad_alloc, in which case @a __d(__p) is called.
168 *
169 * Requirements: _Deleter's copy constructor and destructor must
170 * not throw
171 *
172 * __shared_ptr will release __p by calling __d(__p)
173 */
174 template<typename _Yp, typename _Deleter,
175 typename = _Constructible<_Yp*, _Deleter>>
176 shared_ptr(_Yp* __p, _Deleter __d)
177 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
178
179 /**
180 * @brief Construct a %shared_ptr that owns a null pointer
181 * and the deleter @a __d.
182 * @param __p A null pointer constant.
183 * @param __d A deleter.
184 * @post use_count() == 1 && get() == __p
185 * @throw std::bad_alloc, in which case @a __d(__p) is called.
186 *
187 * Requirements: _Deleter's copy constructor and destructor must
188 * not throw
189 *
190 * The last owner will call __d(__p)
191 */
192 template<typename _Deleter>
193 shared_ptr(nullptr_t __p, _Deleter __d)
194 : __shared_ptr<_Tp>(__p, std::move(__d)) { }
195
196 /**
197 * @brief Construct a %shared_ptr that owns the pointer @a __p
198 * and the deleter @a __d.
199 * @param __p A pointer.
200 * @param __d A deleter.
201 * @param __a An allocator.
202 * @post use_count() == 1 && get() == __p
203 * @throw std::bad_alloc, in which case @a __d(__p) is called.
204 *
205 * Requirements: _Deleter's copy constructor and destructor must
206 * not throw _Alloc's copy constructor and destructor must not
207 * throw.
208 *
209 * __shared_ptr will release __p by calling __d(__p)
210 */
211 template<typename _Yp, typename _Deleter, typename _Alloc,
212 typename = _Constructible<_Yp*, _Deleter, _Alloc>>
213 shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
214 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
215
216 /**
217 * @brief Construct a %shared_ptr that owns a null pointer
218 * and the deleter @a __d.
219 * @param __p A null pointer constant.
220 * @param __d A deleter.
221 * @param __a An allocator.
222 * @post use_count() == 1 && get() == __p
223 * @throw std::bad_alloc, in which case @a __d(__p) is called.
224 *
225 * Requirements: _Deleter's copy constructor and destructor must
226 * not throw _Alloc's copy constructor and destructor must not
227 * throw.
228 *
229 * The last owner will call __d(__p)
230 */
231 template<typename _Deleter, typename _Alloc>
232 shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
233 : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
234
235 // Aliasing constructor
236
237 /**
238 * @brief Constructs a `shared_ptr` instance that stores `__p`
239 * and shares ownership with `__r`.
240 * @param __r A `shared_ptr`.
241 * @param __p A pointer that will remain valid while `*__r` is valid.
242 * @post `get() == __p && use_count() == __r.use_count()`
243 *
244 * This can be used to construct a `shared_ptr` to a sub-object
245 * of an object managed by an existing `shared_ptr`. The complete
246 * object will remain valid while any `shared_ptr` owns it, even
247 * if they don't store a pointer to the complete object.
248 *
249 * @code
250 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
251 * shared_ptr<int> pi(pii, &pii->first);
252 * assert(pii.use_count() == 2);
253 * @endcode
254 */
255 template<typename _Yp>
256 shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
257 : __shared_ptr<_Tp>(__r, __p) { }
258
259#if __cplusplus201703L > 201703L
260 // _GLIBCXX_RESOLVE_LIB_DEFECTS
261 // 2996. Missing rvalue overloads for shared_ptr operations
262 /**
263 * @brief Constructs a `shared_ptr` instance that stores `__p`
264 * and shares ownership with `__r`.
265 * @param __r A `shared_ptr`.
266 * @param __p A pointer that will remain valid while `*__r` is valid.
267 * @post `get() == __p && !__r.use_count() && !__r.get()`
268 *
269 * This can be used to construct a `shared_ptr` to a sub-object
270 * of an object managed by an existing `shared_ptr`. The complete
271 * object will remain valid while any `shared_ptr` owns it, even
272 * if they don't store a pointer to the complete object.
273 *
274 * @code
275 * shared_ptr<pair<int,int>> pii(new pair<int,int>());
276 * shared_ptr<int> pi1(pii, &pii->first);
277 * assert(pii.use_count() == 2);
278 * shared_ptr<int> pi2(std::move(pii), &pii->second);
279 * assert(pii.use_count() == 0);
280 * @endcode
281 */
282 template<typename _Yp>
283 shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
284 : __shared_ptr<_Tp>(std::move(__r), __p) { }
285#endif
286 /**
287 * @brief If @a __r is empty, constructs an empty %shared_ptr;
288 * otherwise construct a %shared_ptr that shares ownership
289 * with @a __r.
290 * @param __r A %shared_ptr.
291 * @post get() == __r.get() && use_count() == __r.use_count()
292 */
293 template<typename _Yp,
294 typename = _Constructible<const shared_ptr<_Yp>&>>
295 shared_ptr(const shared_ptr<_Yp>& __r) noexcept
296 : __shared_ptr<_Tp>(__r) { }
297
298 /**
299 * @brief Move-constructs a %shared_ptr instance from @a __r.
300 * @param __r A %shared_ptr rvalue.
301 * @post *this contains the old value of @a __r, @a __r is empty.
302 */
303 shared_ptr(shared_ptr&& __r) noexcept
304 : __shared_ptr<_Tp>(std::move(__r)) { }
305
306 /**
307 * @brief Move-constructs a %shared_ptr instance from @a __r.
308 * @param __r A %shared_ptr rvalue.
309 * @post *this contains the old value of @a __r, @a __r is empty.
310 */
311 template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
312 shared_ptr(shared_ptr<_Yp>&& __r) noexcept
313 : __shared_ptr<_Tp>(std::move(__r)) { }
314
315 /**
316 * @brief Constructs a %shared_ptr that shares ownership with @a __r
317 * and stores a copy of the pointer stored in @a __r.
318 * @param __r A weak_ptr.
319 * @post use_count() == __r.use_count()
320 * @throw bad_weak_ptr when __r.expired(),
321 * in which case the constructor has no effect.
322 */
323 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
324 explicit shared_ptr(const weak_ptr<_Yp>& __r)
325 : __shared_ptr<_Tp>(__r) { }
326
327#if _GLIBCXX_USE_DEPRECATED1
328#pragma GCC diagnostic push
329#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
330 template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
331 shared_ptr(auto_ptr<_Yp>&& __r);
332#pragma GCC diagnostic pop
333#endif
334
335 // _GLIBCXX_RESOLVE_LIB_DEFECTS
336 // 2399. shared_ptr's constructor from unique_ptr should be constrained
337 template<typename _Yp, typename _Del,
338 typename = _Constructible<unique_ptr<_Yp, _Del>>>
339 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
340 : __shared_ptr<_Tp>(std::move(__r)) { }
341
342#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
343 // This non-standard constructor exists to support conversions that
344 // were possible in C++11 and C++14 but are ill-formed in C++17.
345 // If an exception is thrown this constructor has no effect.
346 template<typename _Yp, typename _Del,
347 _Constructible<unique_ptr<_Yp, _Del>, __sp_array_delete>* = 0>
348 shared_ptr(unique_ptr<_Yp, _Del>&& __r)
349 : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
350#endif
351
352 /**
353 * @brief Construct an empty %shared_ptr.
354 * @post use_count() == 0 && get() == nullptr
355 */
356 constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
357
358 shared_ptr& operator=(const shared_ptr&) noexcept = default;
359
360 template<typename _Yp>
361 _Assignable<const shared_ptr<_Yp>&>
362 operator=(const shared_ptr<_Yp>& __r) noexcept
363 {
364 this->__shared_ptr<_Tp>::operator=(__r);
365 return *this;
366 }
367
368#if _GLIBCXX_USE_DEPRECATED1
369#pragma GCC diagnostic push
370#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
371 template<typename _Yp>
372 _Assignable<auto_ptr<_Yp>>
373 operator=(auto_ptr<_Yp>&& __r)
374 {
375 this->__shared_ptr<_Tp>::operator=(std::move(__r));
376 return *this;
377 }
378#pragma GCC diagnostic pop
379#endif
380
381 shared_ptr&
382 operator=(shared_ptr&& __r) noexcept
383 {
384 this->__shared_ptr<_Tp>::operator=(std::move(__r));
385 return *this;
386 }
387
388 template<class _Yp>
389 _Assignable<shared_ptr<_Yp>>
390 operator=(shared_ptr<_Yp>&& __r) noexcept
391 {
392 this->__shared_ptr<_Tp>::operator=(std::move(__r));
393 return *this;
394 }
395
396 template<typename _Yp, typename _Del>
397 _Assignable<unique_ptr<_Yp, _Del>>
398 operator=(unique_ptr<_Yp, _Del>&& __r)
399 {
400 this->__shared_ptr<_Tp>::operator=(std::move(__r));
401 return *this;
402 }
403
404 private:
405 // This constructor is non-standard, it is used by allocate_shared.
406 template<typename _Alloc, typename... _Args>
407 shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
408 : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
409 { }
410
411 template<typename _Yp, typename _Alloc, typename... _Args>
412 friend shared_ptr<_Yp>
413 allocate_shared(const _Alloc& __a, _Args&&... __args);
414
415 // This constructor is non-standard, it is used by weak_ptr::lock().
416 shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
417 : __shared_ptr<_Tp>(__r, std::nothrow) { }
418
419 friend class weak_ptr<_Tp>;
420 };
421
422#if __cpp_deduction_guides201703L >= 201606
423 template<typename _Tp>
424 shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
425 template<typename _Tp, typename _Del>
426 shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
427#endif
428
429 // 20.7.2.2.7 shared_ptr comparisons
430
431 /// @relates shared_ptr @{
432
433 /// Equality operator for shared_ptr objects, compares the stored pointers
434 template<typename _Tp, typename _Up>
435 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
436 operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
437 { return __a.get() == __b.get(); }
438
439 /// shared_ptr comparison with nullptr
440 template<typename _Tp>
441 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
442 operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
443 { return !__a; }
11
Calling '__shared_ptr::operator bool'
15
Returning from '__shared_ptr::operator bool'
16
Returning the value 1, which participates in a condition later
444
445#ifdef __cpp_lib_three_way_comparison
446 template<typename _Tp, typename _Up>
447 inline strong_ordering
448 operator<=>(const shared_ptr<_Tp>& __a,
449 const shared_ptr<_Up>& __b) noexcept
450 { return compare_three_way()(__a.get(), __b.get()); }
451
452 template<typename _Tp>
453 inline strong_ordering
454 operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
455 {
456 using pointer = typename shared_ptr<_Tp>::element_type*;
457 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
458 }
459#else
460 /// shared_ptr comparison with nullptr
461 template<typename _Tp>
462 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
463 operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
464 { return !__a; }
465
466 /// Inequality operator for shared_ptr objects, compares the stored pointers
467 template<typename _Tp, typename _Up>
468 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
469 operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
470 { return __a.get() != __b.get(); }
471
472 /// shared_ptr comparison with nullptr
473 template<typename _Tp>
474 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
475 operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
476 { return (bool)__a; }
477
478 /// shared_ptr comparison with nullptr
479 template<typename _Tp>
480 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
481 operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
482 { return (bool)__a; }
483
484 /// Relational operator for shared_ptr objects, compares the stored pointers
485 template<typename _Tp, typename _Up>
486 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
487 operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
488 {
489 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
490 using _Up_elt = typename shared_ptr<_Up>::element_type;
491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
492 return less<_Vp>()(__a.get(), __b.get());
493 }
494
495 /// shared_ptr comparison with nullptr
496 template<typename _Tp>
497 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
498 operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
499 {
500 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
501 return less<_Tp_elt*>()(__a.get(), nullptr);
502 }
503
504 /// shared_ptr comparison with nullptr
505 template<typename _Tp>
506 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
507 operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
508 {
509 using _Tp_elt = typename shared_ptr<_Tp>::element_type;
510 return less<_Tp_elt*>()(nullptr, __a.get());
511 }
512
513 /// Relational operator for shared_ptr objects, compares the stored pointers
514 template<typename _Tp, typename _Up>
515 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
516 operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
517 { return !(__b < __a); }
518
519 /// shared_ptr comparison with nullptr
520 template<typename _Tp>
521 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
522 operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
523 { return !(nullptr < __a); }
524
525 /// shared_ptr comparison with nullptr
526 template<typename _Tp>
527 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
528 operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
529 { return !(__a < nullptr); }
530
531 /// Relational operator for shared_ptr objects, compares the stored pointers
532 template<typename _Tp, typename _Up>
533 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
534 operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
535 { return (__b < __a); }
536
537 /// shared_ptr comparison with nullptr
538 template<typename _Tp>
539 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
540 operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
541 { return nullptr < __a; }
542
543 /// shared_ptr comparison with nullptr
544 template<typename _Tp>
545 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
546 operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
547 { return __a < nullptr; }
548
549 /// Relational operator for shared_ptr objects, compares the stored pointers
550 template<typename _Tp, typename _Up>
551 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
552 operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
553 { return !(__a < __b); }
554
555 /// shared_ptr comparison with nullptr
556 template<typename _Tp>
557 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
558 operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
559 { return !(__a < nullptr); }
560
561 /// shared_ptr comparison with nullptr
562 template<typename _Tp>
563 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
564 operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
565 { return !(nullptr < __a); }
566#endif
567
568 // 20.7.2.2.8 shared_ptr specialized algorithms.
569
570 /// Swap overload for shared_ptr
571 template<typename _Tp>
572 inline void
573 swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
574 { __a.swap(__b); }
575
576 // 20.7.2.2.9 shared_ptr casts.
577
578 /// Convert type of `shared_ptr`, via `static_cast`
579 template<typename _Tp, typename _Up>
580 inline shared_ptr<_Tp>
581 static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
582 {
583 using _Sp = shared_ptr<_Tp>;
584 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
585 }
586
587 /// Convert type of `shared_ptr`, via `const_cast`
588 template<typename _Tp, typename _Up>
589 inline shared_ptr<_Tp>
590 const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
591 {
592 using _Sp = shared_ptr<_Tp>;
593 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
594 }
595
596 /// Convert type of `shared_ptr`, via `dynamic_cast`
597 template<typename _Tp, typename _Up>
598 inline shared_ptr<_Tp>
599 dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
600 {
601 using _Sp = shared_ptr<_Tp>;
602 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
603 return _Sp(__r, __p);
604 return _Sp();
605 }
606
607#if __cplusplus201703L >= 201703L
608 /// Convert type of `shared_ptr`, via `reinterpret_cast`
609 template<typename _Tp, typename _Up>
610 inline shared_ptr<_Tp>
611 reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
612 {
613 using _Sp = shared_ptr<_Tp>;
614 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
615 }
616
617#if __cplusplus201703L > 201703L
618 // _GLIBCXX_RESOLVE_LIB_DEFECTS
619 // 2996. Missing rvalue overloads for shared_ptr operations
620
621 /// Convert type of `shared_ptr` rvalue, via `static_cast`
622 template<typename _Tp, typename _Up>
623 inline shared_ptr<_Tp>
624 static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
625 {
626 using _Sp = shared_ptr<_Tp>;
627 return _Sp(std::move(__r),
628 static_cast<typename _Sp::element_type*>(__r.get()));
629 }
630
631 /// Convert type of `shared_ptr` rvalue, via `const_cast`
632 template<typename _Tp, typename _Up>
633 inline shared_ptr<_Tp>
634 const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
635 {
636 using _Sp = shared_ptr<_Tp>;
637 return _Sp(std::move(__r),
638 const_cast<typename _Sp::element_type*>(__r.get()));
639 }
640
641 /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
642 template<typename _Tp, typename _Up>
643 inline shared_ptr<_Tp>
644 dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
645 {
646 using _Sp = shared_ptr<_Tp>;
647 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
648 return _Sp(std::move(__r), __p);
649 return _Sp();
650 }
651
652 /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
653 template<typename _Tp, typename _Up>
654 inline shared_ptr<_Tp>
655 reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
656 {
657 using _Sp = shared_ptr<_Tp>;
658 return _Sp(std::move(__r),
659 reinterpret_cast<typename _Sp::element_type*>(__r.get()));
660 }
661#endif // C++20
662#endif // C++17
663
664 // @}
665
666 /**
667 * @brief A non-owning observer for a pointer owned by a shared_ptr
668 *
669 * A weak_ptr provides a safe alternative to a raw pointer when you want
670 * a non-owning reference to an object that is managed by a shared_ptr.
671 *
672 * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
673 * that shares ownership with every other shared_ptr that already owns
674 * the pointer. In other words you can upgrade from a non-owning "weak"
675 * reference to an owning shared_ptr, without having access to any of
676 * the existing shared_ptr objects.
677 *
678 * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
679 * the object it points to has been destroyed. Instead, a weak_ptr
680 * becomes _expired_ and can no longer be converted to a shared_ptr that
681 * owns the freed pointer, so you cannot accidentally access the pointed-to
682 * object after it has been destroyed.
683 */
684 template<typename _Tp>
685 class weak_ptr : public __weak_ptr<_Tp>
686 {
687 template<typename _Arg>
688 using _Constructible = typename enable_if<
689 is_constructible<__weak_ptr<_Tp>, _Arg>::value
690 >::type;
691
692 template<typename _Arg>
693 using _Assignable = typename enable_if<
694 is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
695 >::type;
696
697 public:
698 constexpr weak_ptr() noexcept = default;
699
700 template<typename _Yp,
701 typename = _Constructible<const shared_ptr<_Yp>&>>
702 weak_ptr(const shared_ptr<_Yp>& __r) noexcept
703 : __weak_ptr<_Tp>(__r) { }
704
705 weak_ptr(const weak_ptr&) noexcept = default;
706
707 template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
708 weak_ptr(const weak_ptr<_Yp>& __r) noexcept
709 : __weak_ptr<_Tp>(__r) { }
710
711 weak_ptr(weak_ptr&&) noexcept = default;
712
713 template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
714 weak_ptr(weak_ptr<_Yp>&& __r) noexcept
715 : __weak_ptr<_Tp>(std::move(__r)) { }
716
717 weak_ptr&
718 operator=(const weak_ptr& __r) noexcept = default;
719
720 template<typename _Yp>
721 _Assignable<const weak_ptr<_Yp>&>
722 operator=(const weak_ptr<_Yp>& __r) noexcept
723 {
724 this->__weak_ptr<_Tp>::operator=(__r);
725 return *this;
726 }
727
728 template<typename _Yp>
729 _Assignable<const shared_ptr<_Yp>&>
730 operator=(const shared_ptr<_Yp>& __r) noexcept
731 {
732 this->__weak_ptr<_Tp>::operator=(__r);
733 return *this;
734 }
735
736 weak_ptr&
737 operator=(weak_ptr&& __r) noexcept = default;
738
739 template<typename _Yp>
740 _Assignable<weak_ptr<_Yp>>
741 operator=(weak_ptr<_Yp>&& __r) noexcept
742 {
743 this->__weak_ptr<_Tp>::operator=(std::move(__r));
744 return *this;
745 }
746
747 shared_ptr<_Tp>
748 lock() const noexcept
749 { return shared_ptr<_Tp>(*this, std::nothrow); }
750 };
751
752#if __cpp_deduction_guides201703L >= 201606
753 template<typename _Tp>
754 weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
755#endif
756
757 // 20.7.2.3.6 weak_ptr specialized algorithms.
758 /// Swap overload for weak_ptr
759 /// @relates weak_ptr
760 template<typename _Tp>
761 inline void
762 swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
763 { __a.swap(__b); }
764
765
766 /// Primary template owner_less
767 template<typename _Tp = void>
768 struct owner_less;
769
770 /// Void specialization of owner_less compares either shared_ptr or weak_ptr
771 template<>
772 struct owner_less<void> : _Sp_owner_less<void, void>
773 { };
774
775 /// Partial specialization of owner_less for shared_ptr.
776 template<typename _Tp>
777 struct owner_less<shared_ptr<_Tp>>
778 : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
779 { };
780
781 /// Partial specialization of owner_less for weak_ptr.
782 template<typename _Tp>
783 struct owner_less<weak_ptr<_Tp>>
784 : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
785 { };
786
787 /**
788 * @brief Base class allowing use of member function shared_from_this.
789 */
790 template<typename _Tp>
791 class enable_shared_from_this
792 {
793 protected:
794 constexpr enable_shared_from_this() noexcept { }
795
796 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
797
798 enable_shared_from_this&
799 operator=(const enable_shared_from_this&) noexcept
800 { return *this; }
801
802 ~enable_shared_from_this() { }
803
804 public:
805 shared_ptr<_Tp>
806 shared_from_this()
807 { return shared_ptr<_Tp>(this->_M_weak_this); }
808
809 shared_ptr<const _Tp>
810 shared_from_this() const
811 { return shared_ptr<const _Tp>(this->_M_weak_this); }
812
813#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
814#define __cpp_lib_enable_shared_from_this201603 201603
815 weak_ptr<_Tp>
816 weak_from_this() noexcept
817 { return this->_M_weak_this; }
818
819 weak_ptr<const _Tp>
820 weak_from_this() const noexcept
821 { return this->_M_weak_this; }
822#endif
823
824 private:
825 template<typename _Tp1>
826 void
827 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
828 { _M_weak_this._M_assign(__p, __n); }
829
830 // Found by ADL when this is an associated class.
831 friend const enable_shared_from_this*
832 __enable_shared_from_this_base(const __shared_count<>&,
833 const enable_shared_from_this* __p)
834 { return __p; }
835
836 template<typename, _Lock_policy>
837 friend class __shared_ptr;
838
839 mutable weak_ptr<_Tp> _M_weak_this;
840 };
841
842 /// @relates shared_ptr @{
843
844 /**
845 * @brief Create an object that is owned by a shared_ptr.
846 * @param __a An allocator.
847 * @param __args Arguments for the @a _Tp object's constructor.
848 * @return A shared_ptr that owns the newly created object.
849 * @throw An exception thrown from @a _Alloc::allocate or from the
850 * constructor of @a _Tp.
851 *
852 * A copy of @a __a will be used to allocate memory for the shared_ptr
853 * and the new object.
854 */
855 template<typename _Tp, typename _Alloc, typename... _Args>
856 inline shared_ptr<_Tp>
857 allocate_shared(const _Alloc& __a, _Args&&... __args)
858 {
859 return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
860 std::forward<_Args>(__args)...);
861 }
862
863 /**
864 * @brief Create an object that is owned by a shared_ptr.
865 * @param __args Arguments for the @a _Tp object's constructor.
866 * @return A shared_ptr that owns the newly created object.
867 * @throw std::bad_alloc, or an exception thrown from the
868 * constructor of @a _Tp.
869 */
870 template<typename _Tp, typename... _Args>
871 inline shared_ptr<_Tp>
872 make_shared(_Args&&... __args)
873 {
874 typedef typename std::remove_cv<_Tp>::type _Tp_nc;
875 return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
876 std::forward<_Args>(__args)...);
877 }
878
879 /// std::hash specialization for shared_ptr.
880 template<typename _Tp>
881 struct hash<shared_ptr<_Tp>>
882 : public __hash_base<size_t, shared_ptr<_Tp>>
883 {
884 size_t
885 operator()(const shared_ptr<_Tp>& __s) const noexcept
886 {
887 return std::hash<typename shared_ptr<_Tp>::element_type*>()(__s.get());
888 }
889 };
890
891 // @} relates shared_ptr
892 // @} group pointer_abstractions
893
894#if __cplusplus201703L >= 201703L
895 namespace __detail::__variant
896 {
897 template<typename> struct _Never_valueless_alt; // see <variant>
898
899 // Provide the strong exception-safety guarantee when emplacing a
900 // shared_ptr into a variant.
901 template<typename _Tp>
902 struct _Never_valueless_alt<std::shared_ptr<_Tp>>
903 : std::true_type
904 { };
905
906 // Provide the strong exception-safety guarantee when emplacing a
907 // weak_ptr into a variant.
908 template<typename _Tp>
909 struct _Never_valueless_alt<std::weak_ptr<_Tp>>
910 : std::true_type
911 { };
912 } // namespace __detail::__variant
913#endif // C++17
914
915_GLIBCXX_END_NAMESPACE_VERSION
916} // namespace
917
918#endif // _SHARED_PTR_H

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

1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-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// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H1
50#define _SHARED_PTR_BASE_H1 1
51
52#include <typeinfo>
53#include <bits/allocated_ptr.h>
54#include <bits/refwrap.h>
55#include <bits/stl_function.h>
56#include <ext/aligned_buffer.h>
57#if __cplusplus201703L > 201703L
58# include <compare>
59#endif
60
61namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
62{
63_GLIBCXX_BEGIN_NAMESPACE_VERSION
64
65#if _GLIBCXX_USE_DEPRECATED1
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
68 template<typename> class auto_ptr;
69#pragma GCC diagnostic pop
70#endif
71
72 /**
73 * @brief Exception possibly thrown by @c shared_ptr.
74 * @ingroup exceptions
75 */
76 class bad_weak_ptr : public std::exception
77 {
78 public:
79 virtual char const* what() const noexcept;
80
81 virtual ~bad_weak_ptr() noexcept;
82 };
83
84 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
85 inline void
86 __throw_bad_weak_ptr()
87 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr())(throw (bad_weak_ptr())); }
88
89 using __gnu_cxx::_Lock_policy;
90 using __gnu_cxx::__default_lock_policy;
91 using __gnu_cxx::_S_single;
92 using __gnu_cxx::_S_mutex;
93 using __gnu_cxx::_S_atomic;
94
95 // Empty helper class except when the template argument is _S_mutex.
96 template<_Lock_policy _Lp>
97 class _Mutex_base
98 {
99 protected:
100 // The atomic policy uses fully-fenced builtins, single doesn't care.
101 enum { _S_need_barriers = 0 };
102 };
103
104 template<>
105 class _Mutex_base<_S_mutex>
106 : public __gnu_cxx::__mutex
107 {
108 protected:
109 // This policy is used when atomic builtins are not available.
110 // The replacement atomic operations might not have the necessary
111 // memory barriers.
112 enum { _S_need_barriers = 1 };
113 };
114
115 template<_Lock_policy _Lp = __default_lock_policy>
116 class _Sp_counted_base
117 : public _Mutex_base<_Lp>
118 {
119 public:
120 _Sp_counted_base() noexcept
121 : _M_use_count(1), _M_weak_count(1) { }
122
123 virtual
124 ~_Sp_counted_base() noexcept
125 { }
126
127 // Called when _M_use_count drops to zero, to release the resources
128 // managed by *this.
129 virtual void
130 _M_dispose() noexcept = 0;
131
132 // Called when _M_weak_count drops to zero.
133 virtual void
134 _M_destroy() noexcept
135 { delete this; }
136
137 virtual void*
138 _M_get_deleter(const std::type_info&) noexcept = 0;
139
140 void
141 _M_add_ref_copy()
142 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
143
144 void
145 _M_add_ref_lock();
146
147 bool
148 _M_add_ref_lock_nothrow();
149
150 void
151 _M_release() noexcept
152 {
153 // Be race-detector-friendly. For more info see bits/c++config.
154 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
155 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
156 {
157 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
158 _M_dispose();
159 // There must be a memory barrier between dispose() and destroy()
160 // to ensure that the effects of dispose() are observed in the
161 // thread that runs destroy().
162 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
163 if (_Mutex_base<_Lp>::_S_need_barriers)
164 {
165 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
166 }
167
168 // Be race-detector-friendly. For more info see bits/c++config.
169 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
170 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
171 -1) == 1)
172 {
173 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
174 _M_destroy();
175 }
176 }
177 }
178
179 void
180 _M_weak_add_ref() noexcept
181 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
182
183 void
184 _M_weak_release() noexcept
185 {
186 // Be race-detector-friendly. For more info see bits/c++config.
187 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
188 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
189 {
190 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
191 if (_Mutex_base<_Lp>::_S_need_barriers)
192 {
193 // See _M_release(),
194 // destroy() must observe results of dispose()
195 __atomic_thread_fence (__ATOMIC_ACQ_REL4);
196 }
197 _M_destroy();
198 }
199 }
200
201 long
202 _M_get_use_count() const noexcept
203 {
204 // No memory barrier is used here so there is no synchronization
205 // with other threads.
206 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED0);
207 }
208
209 private:
210 _Sp_counted_base(_Sp_counted_base const&) = delete;
211 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
212
213 _Atomic_word _M_use_count; // #shared
214 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
215 };
216
217 template<>
218 inline void
219 _Sp_counted_base<_S_single>::
220 _M_add_ref_lock()
221 {
222 if (_M_use_count == 0)
223 __throw_bad_weak_ptr();
224 ++_M_use_count;
225 }
226
227 template<>
228 inline void
229 _Sp_counted_base<_S_mutex>::
230 _M_add_ref_lock()
231 {
232 __gnu_cxx::__scoped_lock sentry(*this);
233 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
234 {
235 _M_use_count = 0;
236 __throw_bad_weak_ptr();
237 }
238 }
239
240 template<>
241 inline void
242 _Sp_counted_base<_S_atomic>::
243 _M_add_ref_lock()
244 {
245 // Perform lock-free add-if-not-zero operation.
246 _Atomic_word __count = _M_get_use_count();
247 do
248 {
249 if (__count == 0)
250 __throw_bad_weak_ptr();
251 // Replace the current counter value with the old value + 1, as
252 // long as it's not changed meanwhile.
253 }
254 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
255 true, __ATOMIC_ACQ_REL4,
256 __ATOMIC_RELAXED0));
257 }
258
259 template<>
260 inline bool
261 _Sp_counted_base<_S_single>::
262 _M_add_ref_lock_nothrow()
263 {
264 if (_M_use_count == 0)
265 return false;
266 ++_M_use_count;
267 return true;
268 }
269
270 template<>
271 inline bool
272 _Sp_counted_base<_S_mutex>::
273 _M_add_ref_lock_nothrow()
274 {
275 __gnu_cxx::__scoped_lock sentry(*this);
276 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
277 {
278 _M_use_count = 0;
279 return false;
280 }
281 return true;
282 }
283
284 template<>
285 inline bool
286 _Sp_counted_base<_S_atomic>::
287 _M_add_ref_lock_nothrow()
288 {
289 // Perform lock-free add-if-not-zero operation.
290 _Atomic_word __count = _M_get_use_count();
291 do
292 {
293 if (__count == 0)
294 return false;
295 // Replace the current counter value with the old value + 1, as
296 // long as it's not changed meanwhile.
297 }
298 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
299 true, __ATOMIC_ACQ_REL4,
300 __ATOMIC_RELAXED0));
301 return true;
302 }
303
304 template<>
305 inline void
306 _Sp_counted_base<_S_single>::_M_add_ref_copy()
307 { ++_M_use_count; }
308
309 template<>
310 inline void
311 _Sp_counted_base<_S_single>::_M_release() noexcept
312 {
313 if (--_M_use_count == 0)
314 {
315 _M_dispose();
316 if (--_M_weak_count == 0)
317 _M_destroy();
318 }
319 }
320
321 template<>
322 inline void
323 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
324 { ++_M_weak_count; }
325
326 template<>
327 inline void
328 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
329 {
330 if (--_M_weak_count == 0)
331 _M_destroy();
332 }
333
334 template<>
335 inline long
336 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
337 { return _M_use_count; }
338
339
340 // Forward declarations.
341 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
342 class __shared_ptr;
343
344 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
345 class __weak_ptr;
346
347 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
348 class __enable_shared_from_this;
349
350 template<typename _Tp>
351 class shared_ptr;
352
353 template<typename _Tp>
354 class weak_ptr;
355
356 template<typename _Tp>
357 struct owner_less;
358
359 template<typename _Tp>
360 class enable_shared_from_this;
361
362 template<_Lock_policy _Lp = __default_lock_policy>
363 class __weak_count;
364
365 template<_Lock_policy _Lp = __default_lock_policy>
366 class __shared_count;
367
368
369 // Counted ptr with no deleter or allocator support
370 template<typename _Ptr, _Lock_policy _Lp>
371 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
372 {
373 public:
374 explicit
375 _Sp_counted_ptr(_Ptr __p) noexcept
376 : _M_ptr(__p) { }
377
378 virtual void
379 _M_dispose() noexcept
380 { delete _M_ptr; }
381
382 virtual void
383 _M_destroy() noexcept
384 { delete this; }
385
386 virtual void*
387 _M_get_deleter(const std::type_info&) noexcept
388 { return nullptr; }
389
390 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
391 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
392
393 private:
394 _Ptr _M_ptr;
395 };
396
397 template<>
398 inline void
399 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
400
401 template<>
402 inline void
403 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
404
405 template<>
406 inline void
407 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
408
409 template<int _Nm, typename _Tp,
410 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
411 struct _Sp_ebo_helper;
412
413 /// Specialization using EBO.
414 template<int _Nm, typename _Tp>
415 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
416 {
417 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
418 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
419
420 static _Tp&
421 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
422 };
423
424 /// Specialization not using EBO.
425 template<int _Nm, typename _Tp>
426 struct _Sp_ebo_helper<_Nm, _Tp, false>
427 {
428 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
429 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
430
431 static _Tp&
432 _S_get(_Sp_ebo_helper& __eboh)
433 { return __eboh._M_tp; }
434
435 private:
436 _Tp _M_tp;
437 };
438
439 // Support for custom deleter and/or allocator
440 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
441 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
442 {
443 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
444 {
445 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
446 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
447
448 public:
449 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
450 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
451 { }
452
453 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
454 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
455
456 _Ptr _M_ptr;
457 };
458
459 public:
460 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
461
462 // __d(__p) must not throw.
463 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
464 : _M_impl(__p, std::move(__d), _Alloc()) { }
465
466 // __d(__p) must not throw.
467 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
468 : _M_impl(__p, std::move(__d), __a) { }
469
470 ~_Sp_counted_deleter() noexcept { }
471
472 virtual void
473 _M_dispose() noexcept
474 { _M_impl._M_del()(_M_impl._M_ptr); }
475
476 virtual void
477 _M_destroy() noexcept
478 {
479 __allocator_type __a(_M_impl._M_alloc());
480 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
481 this->~_Sp_counted_deleter();
482 }
483
484 virtual void*
485 _M_get_deleter(const std::type_info& __ti) noexcept
486 {
487#if __cpp_rtti199711L
488 // _GLIBCXX_RESOLVE_LIB_DEFECTS
489 // 2400. shared_ptr's get_deleter() should use addressof()
490 return __ti == typeid(_Deleter)
491 ? std::__addressof(_M_impl._M_del())
492 : nullptr;
493#else
494 return nullptr;
495#endif
496 }
497
498 private:
499 _Impl _M_impl;
500 };
501
502 // helpers for make_shared / allocate_shared
503
504 struct _Sp_make_shared_tag
505 {
506 private:
507 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
508 friend class _Sp_counted_ptr_inplace;
509
510 static const type_info&
511 _S_ti() noexcept _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
512 {
513 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
514 return reinterpret_cast<const type_info&>(__tag);
515 }
516
517 static bool _S_eq(const type_info&) noexcept;
518 };
519
520 template<typename _Alloc>
521 struct _Sp_alloc_shared_tag
522 {
523 const _Alloc& _M_a;
524 };
525
526 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
527 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
528 {
529 class _Impl : _Sp_ebo_helper<0, _Alloc>
530 {
531 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
532
533 public:
534 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
535
536 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
537
538 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
539 };
540
541 public:
542 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
543
544 // Alloc parameter is not a reference so doesn't alias anything in __args
545 template<typename... _Args>
546 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
547 : _M_impl(__a)
548 {
549 // _GLIBCXX_RESOLVE_LIB_DEFECTS
550 // 2070. allocate_shared should use allocator_traits<A>::construct
551 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
552 std::forward<_Args>(__args)...); // might throw
553 }
554
555 ~_Sp_counted_ptr_inplace() noexcept { }
556
557 virtual void
558 _M_dispose() noexcept
559 {
560 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
561 }
562
563 // Override because the allocator needs to know the dynamic type
564 virtual void
565 _M_destroy() noexcept
566 {
567 __allocator_type __a(_M_impl._M_alloc());
568 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
569 this->~_Sp_counted_ptr_inplace();
570 }
571
572 private:
573 friend class __shared_count<_Lp>; // To be able to call _M_ptr().
574
575 // No longer used, but code compiled against old libstdc++ headers
576 // might still call it from __shared_ptr ctor to get the pointer out.
577 virtual void*
578 _M_get_deleter(const std::type_info& __ti) noexcept override
579 {
580 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
581 // Check for the fake type_info first, so we don't try to access it
582 // as a real type_info object. Otherwise, check if it's the real
583 // type_info for this class. With RTTI enabled we can check directly,
584 // or call a library function to do it.
585 if (&__ti == &_Sp_make_shared_tag::_S_ti()
586 ||
587#if __cpp_rtti199711L
588 __ti == typeid(_Sp_make_shared_tag)
589#else
590 _Sp_make_shared_tag::_S_eq(__ti)
591#endif
592 )
593 return __ptr;
594 return nullptr;
595 }
596
597 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
598
599 _Impl _M_impl;
600 };
601
602 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
603 struct __sp_array_delete
604 {
605 template<typename _Yp>
606 void operator()(_Yp* __p) const { delete[] __p; }
607 };
608
609 template<_Lock_policy _Lp>
610 class __shared_count
611 {
612 template<typename _Tp>
613 struct __not_alloc_shared_tag { using type = void; };
614
615 template<typename _Tp>
616 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
617
618 public:
619 constexpr __shared_count() noexcept : _M_pi(0)
620 { }
621
622 template<typename _Ptr>
623 explicit
624 __shared_count(_Ptr __p) : _M_pi(0)
625 {
626 __trytry
627 {
628 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
629 }
630 __catch(...)catch(...)
631 {
632 delete __p;
633 __throw_exception_againthrow;
634 }
635 }
636
637 template<typename _Ptr>
638 __shared_count(_Ptr __p, /* is_array = */ false_type)
639 : __shared_count(__p)
640 { }
641
642 template<typename _Ptr>
643 __shared_count(_Ptr __p, /* is_array = */ true_type)
644 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
645 { }
646
647 template<typename _Ptr, typename _Deleter,
648 typename = typename __not_alloc_shared_tag<_Deleter>::type>
649 __shared_count(_Ptr __p, _Deleter __d)
650 : __shared_count(__p, std::move(__d), allocator<void>())
651 { }
652
653 template<typename _Ptr, typename _Deleter, typename _Alloc,
654 typename = typename __not_alloc_shared_tag<_Deleter>::type>
655 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
656 {
657 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
658 __trytry
659 {
660 typename _Sp_cd_type::__allocator_type __a2(__a);
661 auto __guard = std::__allocate_guarded(__a2);
662 _Sp_cd_type* __mem = __guard.get();
663 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
664 _M_pi = __mem;
665 __guard = nullptr;
666 }
667 __catch(...)catch(...)
668 {
669 __d(__p); // Call _Deleter on __p.
670 __throw_exception_againthrow;
671 }
672 }
673
674 template<typename _Tp, typename _Alloc, typename... _Args>
675 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
676 _Args&&... __args)
677 {
678 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
679 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
680 auto __guard = std::__allocate_guarded(__a2);
681 _Sp_cp_type* __mem = __guard.get();
682 auto __pi = ::new (__mem)
683 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
684 __guard = nullptr;
685 _M_pi = __pi;
686 __p = __pi->_M_ptr();
687 }
688
689#if _GLIBCXX_USE_DEPRECATED1
690#pragma GCC diagnostic push
691#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
692 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
693 template<typename _Tp>
694 explicit
695 __shared_count(std::auto_ptr<_Tp>&& __r);
696#pragma GCC diagnostic pop
697#endif
698
699 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
700 template<typename _Tp, typename _Del>
701 explicit
702 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
703 {
704 // _GLIBCXX_RESOLVE_LIB_DEFECTS
705 // 2415. Inconsistency between unique_ptr and shared_ptr
706 if (__r.get() == nullptr)
707 return;
708
709 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
710 using _Del2 = typename conditional<is_reference<_Del>::value,
711 reference_wrapper<typename remove_reference<_Del>::type>,
712 _Del>::type;
713 using _Sp_cd_type
714 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
715 using _Alloc = allocator<_Sp_cd_type>;
716 using _Alloc_traits = allocator_traits<_Alloc>;
717 _Alloc __a;
718 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
719 _Alloc_traits::construct(__a, __mem, __r.release(),
720 __r.get_deleter()); // non-throwing
721 _M_pi = __mem;
722 }
723
724 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
725 explicit __shared_count(const __weak_count<_Lp>& __r);
726
727 // Does not throw if __r._M_get_use_count() == 0, caller must check.
728 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
729
730 ~__shared_count() noexcept
731 {
732 if (_M_pi != nullptr)
733 _M_pi->_M_release();
734 }
735
736 __shared_count(const __shared_count& __r) noexcept
737 : _M_pi(__r._M_pi)
738 {
739 if (_M_pi != 0)
740 _M_pi->_M_add_ref_copy();
741 }
742
743 __shared_count&
744 operator=(const __shared_count& __r) noexcept
745 {
746 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
747 if (__tmp != _M_pi)
748 {
749 if (__tmp != 0)
750 __tmp->_M_add_ref_copy();
751 if (_M_pi != 0)
752 _M_pi->_M_release();
753 _M_pi = __tmp;
754 }
755 return *this;
756 }
757
758 void
759 _M_swap(__shared_count& __r) noexcept
760 {
761 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
762 __r._M_pi = _M_pi;
763 _M_pi = __tmp;
764 }
765
766 long
767 _M_get_use_count() const noexcept
768 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
769
770 bool
771 _M_unique() const noexcept
772 { return this->_M_get_use_count() == 1; }
773
774 void*
775 _M_get_deleter(const std::type_info& __ti) const noexcept
776 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
777
778 bool
779 _M_less(const __shared_count& __rhs) const noexcept
780 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
781
782 bool
783 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
784 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
785
786 // Friend function injected into enclosing namespace and found by ADL
787 friend inline bool
788 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
789 { return __a._M_pi == __b._M_pi; }
790
791 private:
792 friend class __weak_count<_Lp>;
793
794 _Sp_counted_base<_Lp>* _M_pi;
795 };
796
797
798 template<_Lock_policy _Lp>
799 class __weak_count
800 {
801 public:
802 constexpr __weak_count() noexcept : _M_pi(nullptr)
803 { }
804
805 __weak_count(const __shared_count<_Lp>& __r) noexcept
806 : _M_pi(__r._M_pi)
807 {
808 if (_M_pi != nullptr)
809 _M_pi->_M_weak_add_ref();
810 }
811
812 __weak_count(const __weak_count& __r) noexcept
813 : _M_pi(__r._M_pi)
814 {
815 if (_M_pi != nullptr)
816 _M_pi->_M_weak_add_ref();
817 }
818
819 __weak_count(__weak_count&& __r) noexcept
820 : _M_pi(__r._M_pi)
821 { __r._M_pi = nullptr; }
822
823 ~__weak_count() noexcept
824 {
825 if (_M_pi != nullptr)
826 _M_pi->_M_weak_release();
827 }
828
829 __weak_count&
830 operator=(const __shared_count<_Lp>& __r) noexcept
831 {
832 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
833 if (__tmp != nullptr)
834 __tmp->_M_weak_add_ref();
835 if (_M_pi != nullptr)
836 _M_pi->_M_weak_release();
837 _M_pi = __tmp;
838 return *this;
839 }
840
841 __weak_count&
842 operator=(const __weak_count& __r) noexcept
843 {
844 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
845 if (__tmp != nullptr)
846 __tmp->_M_weak_add_ref();
847 if (_M_pi != nullptr)
848 _M_pi->_M_weak_release();
849 _M_pi = __tmp;
850 return *this;
851 }
852
853 __weak_count&
854 operator=(__weak_count&& __r) noexcept
855 {
856 if (_M_pi != nullptr)
857 _M_pi->_M_weak_release();
858 _M_pi = __r._M_pi;
859 __r._M_pi = nullptr;
860 return *this;
861 }
862
863 void
864 _M_swap(__weak_count& __r) noexcept
865 {
866 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
867 __r._M_pi = _M_pi;
868 _M_pi = __tmp;
869 }
870
871 long
872 _M_get_use_count() const noexcept
873 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
874
875 bool
876 _M_less(const __weak_count& __rhs) const noexcept
877 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
878
879 bool
880 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
881 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
882
883 // Friend function injected into enclosing namespace and found by ADL
884 friend inline bool
885 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
886 { return __a._M_pi == __b._M_pi; }
887
888 private:
889 friend class __shared_count<_Lp>;
890
891 _Sp_counted_base<_Lp>* _M_pi;
892 };
893
894 // Now that __weak_count is defined we can define this constructor:
895 template<_Lock_policy _Lp>
896 inline
897 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
898 : _M_pi(__r._M_pi)
899 {
900 if (_M_pi != nullptr)
901 _M_pi->_M_add_ref_lock();
902 else
903 __throw_bad_weak_ptr();
904 }
905
906 // Now that __weak_count is defined we can define this constructor:
907 template<_Lock_policy _Lp>
908 inline
909 __shared_count<_Lp>::
910 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
911 : _M_pi(__r._M_pi)
912 {
913 if (_M_pi != nullptr)
914 if (!_M_pi->_M_add_ref_lock_nothrow())
915 _M_pi = nullptr;
916 }
917
918#define __cpp_lib_shared_ptr_arrays201611L 201611L
919
920 // Helper traits for shared_ptr of array:
921
922 // A pointer type Y* is said to be compatible with a pointer type T* when
923 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
924 template<typename _Yp_ptr, typename _Tp_ptr>
925 struct __sp_compatible_with
926 : false_type
927 { };
928
929 template<typename _Yp, typename _Tp>
930 struct __sp_compatible_with<_Yp*, _Tp*>
931 : is_convertible<_Yp*, _Tp*>::type
932 { };
933
934 template<typename _Up, size_t _Nm>
935 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
936 : true_type
937 { };
938
939 template<typename _Up, size_t _Nm>
940 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
941 : true_type
942 { };
943
944 template<typename _Up, size_t _Nm>
945 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
946 : true_type
947 { };
948
949 template<typename _Up, size_t _Nm>
950 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
951 : true_type
952 { };
953
954 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
955 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
956 struct __sp_is_constructible_arrN
957 : false_type
958 { };
959
960 template<typename _Up, size_t _Nm, typename _Yp>
961 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
962 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
963 { };
964
965 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
966 template<typename _Up, typename _Yp, typename = void>
967 struct __sp_is_constructible_arr
968 : false_type
969 { };
970
971 template<typename _Up, typename _Yp>
972 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
973 : is_convertible<_Yp(*)[], _Up(*)[]>::type
974 { };
975
976 // Trait to check if shared_ptr<T> can be constructed from Y*.
977 template<typename _Tp, typename _Yp>
978 struct __sp_is_constructible;
979
980 // When T is U[N], Y(*)[N] shall be convertible to T*;
981 template<typename _Up, size_t _Nm, typename _Yp>
982 struct __sp_is_constructible<_Up[_Nm], _Yp>
983 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
984 { };
985
986 // when T is U[], Y(*)[] shall be convertible to T*;
987 template<typename _Up, typename _Yp>
988 struct __sp_is_constructible<_Up[], _Yp>
989 : __sp_is_constructible_arr<_Up, _Yp>::type
990 { };
991
992 // otherwise, Y* shall be convertible to T*.
993 template<typename _Tp, typename _Yp>
994 struct __sp_is_constructible
995 : is_convertible<_Yp*, _Tp*>::type
996 { };
997
998
999 // Define operator* and operator-> for shared_ptr<T>.
1000 template<typename _Tp, _Lock_policy _Lp,
1001 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
1002 class __shared_ptr_access
1003 {
1004 public:
1005 using element_type = _Tp;
1006
1007 element_type&
1008 operator*() const noexcept
1009 {
1010 __glibcxx_assert(_M_get() != nullptr);
1011 return *_M_get();
1012 }
1013
1014 element_type*
1015 operator->() const noexcept
1016 {
1017 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1018 return _M_get();
1019 }
1020
1021 private:
1022 element_type*
1023 _M_get() const noexcept
1024 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1025 };
1026
1027 // Define operator-> for shared_ptr<cv void>.
1028 template<typename _Tp, _Lock_policy _Lp>
1029 class __shared_ptr_access<_Tp, _Lp, false, true>
1030 {
1031 public:
1032 using element_type = _Tp;
1033
1034 element_type*
1035 operator->() const noexcept
1036 {
1037 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
1038 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
1039 return __ptr;
1040 }
1041 };
1042
1043 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
1044 template<typename _Tp, _Lock_policy _Lp>
1045 class __shared_ptr_access<_Tp, _Lp, true, false>
1046 {
1047 public:
1048 using element_type = typename remove_extent<_Tp>::type;
1049
1050#if __cplusplus201703L <= 201402L
1051 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1052 element_type&
1053 operator*() const noexcept
1054 {
1055 __glibcxx_assert(_M_get() != nullptr);
1056 return *_M_get();
1057 }
1058
1059 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1060 element_type*
1061 operator->() const noexcept
1062 {
1063 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1064 return _M_get();
1065 }
1066#endif
1067
1068 element_type&
1069 operator[](ptrdiff_t __i) const
1070 {
1071 __glibcxx_assert(_M_get() != nullptr);
1072 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1073 return _M_get()[__i];
1074 }
1075
1076 private:
1077 element_type*
1078 _M_get() const noexcept
1079 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1080 };
1081
1082 template<typename _Tp, _Lock_policy _Lp>
1083 class __shared_ptr
1084 : public __shared_ptr_access<_Tp, _Lp>
1085 {
1086 public:
1087 using element_type = typename remove_extent<_Tp>::type;
1088
1089 private:
1090 // Constraint for taking ownership of a pointer of type _Yp*:
1091 template<typename _Yp>
1092 using _SafeConv
1093 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1094
1095 // Constraint for construction from shared_ptr and weak_ptr:
1096 template<typename _Yp, typename _Res = void>
1097 using _Compatible = typename
1098 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1099
1100 // Constraint for assignment from shared_ptr and weak_ptr:
1101 template<typename _Yp>
1102 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1103
1104 // Constraint for construction from unique_ptr:
1105 template<typename _Yp, typename _Del, typename _Res = void,
1106 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1107 using _UniqCompatible = typename enable_if<__and_<
1108 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
1109 >::value, _Res>::type;
1110
1111 // Constraint for assignment from unique_ptr:
1112 template<typename _Yp, typename _Del>
1113 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1114
1115 public:
1116
1117#if __cplusplus201703L > 201402L
1118 using weak_type = __weak_ptr<_Tp, _Lp>;
1119#endif
1120
1121 constexpr __shared_ptr() noexcept
1122 : _M_ptr(0), _M_refcount()
1123 { }
1124
1125 template<typename _Yp, typename = _SafeConv<_Yp>>
1126 explicit
1127 __shared_ptr(_Yp* __p)
1128 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1129 {
1130 static_assert( !is_void<_Yp>::value, "incomplete type" );
1131 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1132 _M_enable_shared_from_this_with(__p);
1133 }
1134
1135 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1136 __shared_ptr(_Yp* __p, _Deleter __d)
1137 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1138 {
1139 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1140 "deleter expression d(p) is well-formed");
1141 _M_enable_shared_from_this_with(__p);
1142 }
1143
1144 template<typename _Yp, typename _Deleter, typename _Alloc,
1145 typename = _SafeConv<_Yp>>
1146 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1147 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1148 {
1149 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1150 "deleter expression d(p) is well-formed");
1151 _M_enable_shared_from_this_with(__p);
1152 }
1153
1154 template<typename _Deleter>
1155 __shared_ptr(nullptr_t __p, _Deleter __d)
1156 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1157 { }
1158
1159 template<typename _Deleter, typename _Alloc>
1160 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1161 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1162 { }
1163
1164 // Aliasing constructor
1165 template<typename _Yp>
1166 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1167 element_type* __p) noexcept
1168 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1169 { }
1170
1171 // Aliasing constructor
1172 template<typename _Yp>
1173 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
1174 element_type* __p) noexcept
1175 : _M_ptr(__p), _M_refcount()
1176 {
1177 _M_refcount._M_swap(__r._M_refcount);
1178 __r._M_ptr = 0;
1179 }
1180
1181 __shared_ptr(const __shared_ptr&) noexcept = default;
1182 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
1183 ~__shared_ptr() = default;
1184
1185 template<typename _Yp, typename = _Compatible<_Yp>>
1186 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1187 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1188 { }
1189
1190 __shared_ptr(__shared_ptr&& __r) noexcept
1191 : _M_ptr(__r._M_ptr), _M_refcount()
1192 {
1193 _M_refcount._M_swap(__r._M_refcount);
1194 __r._M_ptr = 0;
1195 }
1196
1197 template<typename _Yp, typename = _Compatible<_Yp>>
1198 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1199 : _M_ptr(__r._M_ptr), _M_refcount()
1200 {
1201 _M_refcount._M_swap(__r._M_refcount);
1202 __r._M_ptr = 0;
1203 }
1204
1205 template<typename _Yp, typename = _Compatible<_Yp>>
1206 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1207 : _M_refcount(__r._M_refcount) // may throw
1208 {
1209 // It is now safe to copy __r._M_ptr, as
1210 // _M_refcount(__r._M_refcount) did not throw.
1211 _M_ptr = __r._M_ptr;
1212 }
1213
1214 // If an exception is thrown this constructor has no effect.
1215 template<typename _Yp, typename _Del,
1216 typename = _UniqCompatible<_Yp, _Del>>
1217 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1218 : _M_ptr(__r.get()), _M_refcount()
1219 {
1220 auto __raw = __to_address(__r.get());
1221 _M_refcount = __shared_count<_Lp>(std::move(__r));
1222 _M_enable_shared_from_this_with(__raw);
1223 }
1224
1225#if __cplusplus201703L <= 201402L && _GLIBCXX_USE_DEPRECATED1
1226 protected:
1227 // If an exception is thrown this constructor has no effect.
1228 template<typename _Tp1, typename _Del,
1229 typename enable_if<__and_<
1230 __not_<is_array<_Tp>>, is_array<_Tp1>,
1231 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1232 >::value, bool>::type = true>
1233 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1234 : _M_ptr(__r.get()), _M_refcount()
1235 {
1236 auto __raw = __to_address(__r.get());
1237 _M_refcount = __shared_count<_Lp>(std::move(__r));
1238 _M_enable_shared_from_this_with(__raw);
1239 }
1240 public:
1241#endif
1242
1243#if _GLIBCXX_USE_DEPRECATED1
1244#pragma GCC diagnostic push
1245#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1246 // Postcondition: use_count() == 1 and __r.get() == 0
1247 template<typename _Yp, typename = _Compatible<_Yp>>
1248 __shared_ptr(auto_ptr<_Yp>&& __r);
1249#pragma GCC diagnostic pop
1250#endif
1251
1252 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1253
1254 template<typename _Yp>
1255 _Assignable<_Yp>
1256 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1257 {
1258 _M_ptr = __r._M_ptr;
1259 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1260 return *this;
1261 }
1262
1263#if _GLIBCXX_USE_DEPRECATED1
1264#pragma GCC diagnostic push
1265#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1266 template<typename _Yp>
1267 _Assignable<_Yp>
1268 operator=(auto_ptr<_Yp>&& __r)
1269 {
1270 __shared_ptr(std::move(__r)).swap(*this);
1271 return *this;
1272 }
1273#pragma GCC diagnostic pop
1274#endif
1275
1276 __shared_ptr&
1277 operator=(__shared_ptr&& __r) noexcept
1278 {
1279 __shared_ptr(std::move(__r)).swap(*this);
1280 return *this;
1281 }
1282
1283 template<class _Yp>
1284 _Assignable<_Yp>
1285 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1286 {
1287 __shared_ptr(std::move(__r)).swap(*this);
1288 return *this;
1289 }
1290
1291 template<typename _Yp, typename _Del>
1292 _UniqAssignable<_Yp, _Del>
1293 operator=(unique_ptr<_Yp, _Del>&& __r)
1294 {
1295 __shared_ptr(std::move(__r)).swap(*this);
1296 return *this;
1297 }
1298
1299 void
1300 reset() noexcept
1301 { __shared_ptr().swap(*this); }
1302
1303 template<typename _Yp>
1304 _SafeConv<_Yp>
1305 reset(_Yp* __p) // _Yp must be complete.
1306 {
1307 // Catch self-reset errors.
1308 __glibcxx_assert(__p == 0 || __p != _M_ptr);
1309 __shared_ptr(__p).swap(*this);
1310 }
1311
1312 template<typename _Yp, typename _Deleter>
1313 _SafeConv<_Yp>
1314 reset(_Yp* __p, _Deleter __d)
1315 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1316
1317 template<typename _Yp, typename _Deleter, typename _Alloc>
1318 _SafeConv<_Yp>
1319 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1320 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1321
1322 /// Return the stored pointer.
1323 element_type*
1324 get() const noexcept
1325 { return _M_ptr; }
1326
1327 /// Return true if the stored pointer is not null.
1328 explicit operator bool() const // never throws
1329 { return _M_ptr == 0 ? false : true; }
12
Assuming field '_M_ptr' is equal to null
13
'?' condition is true
14
Returning zero, which participates in a condition later
1330
1331 /// Return true if use_count() == 1.
1332 bool
1333 unique() const noexcept
1334 { return _M_refcount._M_unique(); }
1335
1336 /// If *this owns a pointer, return the number of owners, otherwise zero.
1337 long
1338 use_count() const noexcept
1339 { return _M_refcount._M_get_use_count(); }
1340
1341 /// Exchange both the owned pointer and the stored pointer.
1342 void
1343 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1344 {
1345 std::swap(_M_ptr, __other._M_ptr);
1346 _M_refcount._M_swap(__other._M_refcount);
1347 }
1348
1349 /** @brief Define an ordering based on ownership.
1350 *
1351 * This function defines a strict weak ordering between two shared_ptr
1352 * or weak_ptr objects, such that one object is less than the other
1353 * unless they share ownership of the same pointer, or are both empty.
1354 * @{
1355 */
1356 template<typename _Tp1>
1357 bool
1358 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1359 { return _M_refcount._M_less(__rhs._M_refcount); }
1360
1361 template<typename _Tp1>
1362 bool
1363 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1364 { return _M_refcount._M_less(__rhs._M_refcount); }
1365 // @}
1366
1367 protected:
1368 // This constructor is non-standard, it is used by allocate_shared.
1369 template<typename _Alloc, typename... _Args>
1370 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1371 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
1372 { _M_enable_shared_from_this_with(_M_ptr); }
1373
1374 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1375 typename... _Args>
1376 friend __shared_ptr<_Tp1, _Lp1>
1377 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1378
1379 // This constructor is used by __weak_ptr::lock() and
1380 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1381 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
1382 : _M_refcount(__r._M_refcount, std::nothrow)
1383 {
1384 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1385 }
1386
1387 friend class __weak_ptr<_Tp, _Lp>;
1388
1389 private:
1390
1391 template<typename _Yp>
1392 using __esft_base_t = decltype(__enable_shared_from_this_base(
1393 std::declval<const __shared_count<_Lp>&>(),
1394 std::declval<_Yp*>()));
1395
1396 // Detect an accessible and unambiguous enable_shared_from_this base.
1397 template<typename _Yp, typename = void>
1398 struct __has_esft_base
1399 : false_type { };
1400
1401 template<typename _Yp>
1402 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1403 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1404
1405 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1406 typename enable_if<__has_esft_base<_Yp2>::value>::type
1407 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1408 {
1409 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1410 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1411 }
1412
1413 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1414 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1415 _M_enable_shared_from_this_with(_Yp*) noexcept
1416 { }
1417
1418 void*
1419 _M_get_deleter(const std::type_info& __ti) const noexcept
1420 { return _M_refcount._M_get_deleter(__ti); }
1421
1422 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1423 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1424
1425 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1426 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1427
1428 template<typename _Del, typename _Tp1>
1429 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1430
1431 element_type* _M_ptr; // Contained pointer.
1432 __shared_count<_Lp> _M_refcount; // Reference counter.
1433 };
1434
1435
1436 // 20.7.2.2.7 shared_ptr comparisons
1437 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1438 inline bool
1439 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1440 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1441 { return __a.get() == __b.get(); }
1442
1443 template<typename _Tp, _Lock_policy _Lp>
1444 inline bool
1445 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1446 { return !__a; }
1447
1448#ifdef __cpp_lib_three_way_comparison
1449 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1450 inline strong_ordering
1451 operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
1452 const __shared_ptr<_Up, _Lp>& __b) noexcept
1453 { return compare_three_way()(__a.get(), __b.get()); }
1454
1455 template<typename _Tp, _Lock_policy _Lp>
1456 inline strong_ordering
1457 operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1458 {
1459 using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
1460 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
1461 }
1462#else
1463 template<typename _Tp, _Lock_policy _Lp>
1464 inline bool
1465 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1466 { return !__a; }
1467
1468 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1469 inline bool
1470 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1471 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1472 { return __a.get() != __b.get(); }
1473
1474 template<typename _Tp, _Lock_policy _Lp>
1475 inline bool
1476 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1477 { return (bool)__a; }
1478
1479 template<typename _Tp, _Lock_policy _Lp>
1480 inline bool
1481 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1482 { return (bool)__a; }
1483
1484 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1485 inline bool
1486 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1487 const __shared_ptr<_Up, _Lp>& __b) noexcept
1488 {
1489 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1490 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1491 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1492 return less<_Vp>()(__a.get(), __b.get());
1493 }
1494
1495 template<typename _Tp, _Lock_policy _Lp>
1496 inline bool
1497 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1498 {
1499 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1500 return less<_Tp_elt*>()(__a.get(), nullptr);
1501 }
1502
1503 template<typename _Tp, _Lock_policy _Lp>
1504 inline bool
1505 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1506 {
1507 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1508 return less<_Tp_elt*>()(nullptr, __a.get());
1509 }
1510
1511 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1512 inline bool
1513 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1514 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1515 { return !(__b < __a); }
1516
1517 template<typename _Tp, _Lock_policy _Lp>
1518 inline bool
1519 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1520 { return !(nullptr < __a); }
1521
1522 template<typename _Tp, _Lock_policy _Lp>
1523 inline bool
1524 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1525 { return !(__a < nullptr); }
1526
1527 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1528 inline bool
1529 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1530 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1531 { return (__b < __a); }
1532
1533 template<typename _Tp, _Lock_policy _Lp>
1534 inline bool
1535 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1536 { return nullptr < __a; }
1537
1538 template<typename _Tp, _Lock_policy _Lp>
1539 inline bool
1540 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1541 { return __a < nullptr; }
1542
1543 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1544 inline bool
1545 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1546 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1547 { return !(__a < __b); }
1548
1549 template<typename _Tp, _Lock_policy _Lp>
1550 inline bool
1551 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1552 { return !(__a < nullptr); }
1553
1554 template<typename _Tp, _Lock_policy _Lp>
1555 inline bool
1556 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1557 { return !(nullptr < __a); }
1558#endif // three-way comparison
1559
1560 // 20.7.2.2.8 shared_ptr specialized algorithms.
1561 template<typename _Tp, _Lock_policy _Lp>
1562 inline void
1563 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1564 { __a.swap(__b); }
1565
1566 // 20.7.2.2.9 shared_ptr casts
1567
1568 // The seemingly equivalent code:
1569 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1570 // will eventually result in undefined behaviour, attempting to
1571 // delete the same object twice.
1572 /// static_pointer_cast
1573 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1574 inline __shared_ptr<_Tp, _Lp>
1575 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1576 {
1577 using _Sp = __shared_ptr<_Tp, _Lp>;
1578 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1579 }
1580
1581 // The seemingly equivalent code:
1582 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1583 // will eventually result in undefined behaviour, attempting to
1584 // delete the same object twice.
1585 /// const_pointer_cast
1586 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1587 inline __shared_ptr<_Tp, _Lp>
1588 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1589 {
1590 using _Sp = __shared_ptr<_Tp, _Lp>;
1591 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1592 }
1593
1594 // The seemingly equivalent code:
1595 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1596 // will eventually result in undefined behaviour, attempting to
1597 // delete the same object twice.
1598 /// dynamic_pointer_cast
1599 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1600 inline __shared_ptr<_Tp, _Lp>
1601 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1602 {
1603 using _Sp = __shared_ptr<_Tp, _Lp>;
1604 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1605 return _Sp(__r, __p);
1606 return _Sp();
1607 }
1608
1609#if __cplusplus201703L > 201402L
1610 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1611 inline __shared_ptr<_Tp, _Lp>
1612 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1613 {
1614 using _Sp = __shared_ptr<_Tp, _Lp>;
1615 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1616 }
1617#endif
1618
1619 template<typename _Tp, _Lock_policy _Lp>
1620 class __weak_ptr
1621 {
1622 template<typename _Yp, typename _Res = void>
1623 using _Compatible = typename
1624 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1625
1626 // Constraint for assignment from shared_ptr and weak_ptr:
1627 template<typename _Yp>
1628 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1629
1630 public:
1631 using element_type = typename remove_extent<_Tp>::type;
1632
1633 constexpr __weak_ptr() noexcept
1634 : _M_ptr(nullptr), _M_refcount()
1635 { }
1636
1637 __weak_ptr(const __weak_ptr&) noexcept = default;
1638
1639 ~__weak_ptr() = default;
1640
1641 // The "obvious" converting constructor implementation:
1642 //
1643 // template<typename _Tp1>
1644 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1645 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1646 // { }
1647 //
1648 // has a serious problem.
1649 //
1650 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1651 // conversion may require access to *__r._M_ptr (virtual inheritance).
1652 //
1653 // It is not possible to avoid spurious access violations since
1654 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1655 template<typename _Yp, typename = _Compatible<_Yp>>
1656 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1657 : _M_refcount(__r._M_refcount)
1658 { _M_ptr = __r.lock().get(); }
1659
1660 template<typename _Yp, typename = _Compatible<_Yp>>
1661 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1662 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1663 { }
1664
1665 __weak_ptr(__weak_ptr&& __r) noexcept
1666 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1667 { __r._M_ptr = nullptr; }
1668
1669 template<typename _Yp, typename = _Compatible<_Yp>>
1670 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1671 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1672 { __r._M_ptr = nullptr; }
1673
1674 __weak_ptr&
1675 operator=(const __weak_ptr& __r) noexcept = default;
1676
1677 template<typename _Yp>
1678 _Assignable<_Yp>
1679 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1680 {
1681 _M_ptr = __r.lock().get();
1682 _M_refcount = __r._M_refcount;
1683 return *this;
1684 }
1685
1686 template<typename _Yp>
1687 _Assignable<_Yp>
1688 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1689 {
1690 _M_ptr = __r._M_ptr;
1691 _M_refcount = __r._M_refcount;
1692 return *this;
1693 }
1694
1695 __weak_ptr&
1696 operator=(__weak_ptr&& __r) noexcept
1697 {
1698 _M_ptr = __r._M_ptr;
1699 _M_refcount = std::move(__r._M_refcount);
1700 __r._M_ptr = nullptr;
1701 return *this;
1702 }
1703
1704 template<typename _Yp>
1705 _Assignable<_Yp>
1706 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1707 {
1708 _M_ptr = __r.lock().get();
1709 _M_refcount = std::move(__r._M_refcount);
1710 __r._M_ptr = nullptr;
1711 return *this;
1712 }
1713
1714 __shared_ptr<_Tp, _Lp>
1715 lock() const noexcept
1716 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1717
1718 long
1719 use_count() const noexcept
1720 { return _M_refcount._M_get_use_count(); }
1721
1722 bool
1723 expired() const noexcept
1724 { return _M_refcount._M_get_use_count() == 0; }
1725
1726 template<typename _Tp1>
1727 bool
1728 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1729 { return _M_refcount._M_less(__rhs._M_refcount); }
1730
1731 template<typename _Tp1>
1732 bool
1733 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1734 { return _M_refcount._M_less(__rhs._M_refcount); }
1735
1736 void
1737 reset() noexcept
1738 { __weak_ptr().swap(*this); }
1739
1740 void
1741 swap(__weak_ptr& __s) noexcept
1742 {
1743 std::swap(_M_ptr, __s._M_ptr);
1744 _M_refcount._M_swap(__s._M_refcount);
1745 }
1746
1747 private:
1748 // Used by __enable_shared_from_this.
1749 void
1750 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1751 {
1752 if (use_count() == 0)
1753 {
1754 _M_ptr = __ptr;
1755 _M_refcount = __refcount;
1756 }
1757 }
1758
1759 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1760 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1761 friend class __enable_shared_from_this<_Tp, _Lp>;
1762 friend class enable_shared_from_this<_Tp>;
1763
1764 element_type* _M_ptr; // Contained pointer.
1765 __weak_count<_Lp> _M_refcount; // Reference counter.
1766 };
1767
1768 // 20.7.2.3.6 weak_ptr specialized algorithms.
1769 template<typename _Tp, _Lock_policy _Lp>
1770 inline void
1771 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1772 { __a.swap(__b); }
1773
1774 template<typename _Tp, typename _Tp1>
1775 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1776 {
1777 bool
1778 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1779 { return __lhs.owner_before(__rhs); }
1780
1781 bool
1782 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1783 { return __lhs.owner_before(__rhs); }
1784
1785 bool
1786 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1787 { return __lhs.owner_before(__rhs); }
1788 };
1789
1790 template<>
1791 struct _Sp_owner_less<void, void>
1792 {
1793 template<typename _Tp, typename _Up>
1794 auto
1795 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1796 -> decltype(__lhs.owner_before(__rhs))
1797 { return __lhs.owner_before(__rhs); }
1798
1799 using is_transparent = void;
1800 };
1801
1802 template<typename _Tp, _Lock_policy _Lp>
1803 struct owner_less<__shared_ptr<_Tp, _Lp>>
1804 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1805 { };
1806
1807 template<typename _Tp, _Lock_policy _Lp>
1808 struct owner_less<__weak_ptr<_Tp, _Lp>>
1809 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1810 { };
1811
1812
1813 template<typename _Tp, _Lock_policy _Lp>
1814 class __enable_shared_from_this
1815 {
1816 protected:
1817 constexpr __enable_shared_from_this() noexcept { }
1818
1819 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1820
1821 __enable_shared_from_this&
1822 operator=(const __enable_shared_from_this&) noexcept
1823 { return *this; }
1824
1825 ~__enable_shared_from_this() { }
1826
1827 public:
1828 __shared_ptr<_Tp, _Lp>
1829 shared_from_this()
1830 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1831
1832 __shared_ptr<const _Tp, _Lp>
1833 shared_from_this() const
1834 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1835
1836#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
1837 __weak_ptr<_Tp, _Lp>
1838 weak_from_this() noexcept
1839 { return this->_M_weak_this; }
1840
1841 __weak_ptr<const _Tp, _Lp>
1842 weak_from_this() const noexcept
1843 { return this->_M_weak_this; }
1844#endif
1845
1846 private:
1847 template<typename _Tp1>
1848 void
1849 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1850 { _M_weak_this._M_assign(__p, __n); }
1851
1852 friend const __enable_shared_from_this*
1853 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1854 const __enable_shared_from_this* __p)
1855 { return __p; }
1856
1857 template<typename, _Lock_policy>
1858 friend class __shared_ptr;
1859
1860 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1861 };
1862
1863 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1864 typename _Alloc, typename... _Args>
1865 inline __shared_ptr<_Tp, _Lp>
1866 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1867 {
1868 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
1869 std::forward<_Args>(__args)...);
1870 }
1871
1872 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1873 typename... _Args>
1874 inline __shared_ptr<_Tp, _Lp>
1875 __make_shared(_Args&&... __args)
1876 {
1877 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1878 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1879 std::forward<_Args>(__args)...);
1880 }
1881
1882 /// std::hash specialization for __shared_ptr.
1883 template<typename _Tp, _Lock_policy _Lp>
1884 struct hash<__shared_ptr<_Tp, _Lp>>
1885 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1886 {
1887 size_t
1888 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1889 {
1890 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1891 __s.get());
1892 }
1893 };
1894
1895_GLIBCXX_END_NAMESPACE_VERSION
1896} // namespace
1897
1898#endif // _SHARED_PTR_BASE_H