LibreOffice Module comphelper (master) 1
numberedcollection.cxx
Go to the documentation of this file.
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 <algorithm>
22#include <com/sun/star/frame/UntitledNumbersConst.hpp>
23#include <com/sun/star/lang/IllegalArgumentException.hpp>
24
25namespace comphelper{
26
27constexpr OUStringLiteral ERRMSG_INVALID_COMPONENT_PARAM = u"NULL as component reference not allowed.";
28
29
31{
32}
33
34
36{
37}
38
39
40void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner)
41{
42 // SYNCHRONIZED ->
43 std::scoped_lock aLock(m_aMutex);
44
45 m_xOwner = xOwner;
46
47 // <- SYNCHRONIZED
48}
49
50
52{
53 // SYNCHRONIZED ->
54 std::scoped_lock aLock(m_aMutex);
55
57
58 // <- SYNCHRONIZED
59}
60
61
62::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent)
63{
64 // SYNCHRONIZED ->
65 std::scoped_lock aLock(m_aMutex);
66
67 if ( ! xComponent.is ())
68 throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1);
69
70 sal_IntPtr pComponent = reinterpret_cast<sal_IntPtr>( xComponent.get() );
71 TNumberedItemHash::const_iterator pIt = m_lComponents.find (pComponent);
72
73 // a) component already exists - return its number directly
74 if (pIt != m_lComponents.end())
75 return pIt->second.nNumber;
76
77 // b) component must be added new to this container
78
79 // b1) collection is full - no further components possible
80 // -> return INVALID_NUMBER
81 ::sal_Int32 nFreeNumber = impl_searchFreeNumber();
82 if (nFreeNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
83 return css::frame::UntitledNumbersConst::INVALID_NUMBER;
84
85 // b2) add component to collection and return its number
86 TNumberedItem aItem;
87 aItem.xItem = css::uno::WeakReference< css::uno::XInterface >(xComponent);
88 aItem.nNumber = nFreeNumber;
89 m_lComponents[pComponent] = aItem;
90
91 return nFreeNumber;
92
93 // <- SYNCHRONIZED
94}
95
96
97void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber)
98{
99 // SYNCHRONIZED ->
100 std::scoped_lock aLock(m_aMutex);
101
102 if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
103 throw css::lang::IllegalArgumentException ("Special value INVALID_NUMBER not allowed as input parameter.", m_xOwner.get(), 1);
104
105 TDeadItemList lDeadItems;
106 TNumberedItemHash::iterator pComponent;
107
108 for ( pComponent = m_lComponents.begin ();
109 pComponent != m_lComponents.end ();
110 ++pComponent )
111 {
112 const TNumberedItem& rItem = pComponent->second;
113 const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get();
114
115 if ( ! xItem.is ())
116 {
117 lDeadItems.push_back(pComponent->first);
118 continue;
119 }
120
121 if (rItem.nNumber == nNumber)
122 {
123 m_lComponents.erase (pComponent);
124 break;
125 }
126 }
127
129
130 // <- SYNCHRONIZED
131}
132
133
134void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent)
135{
136 // SYNCHRONIZED ->
137 std::scoped_lock aLock(m_aMutex);
138
139 if ( ! xComponent.is ())
140 throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1);
141
142 sal_IntPtr pComponent = reinterpret_cast<sal_IntPtr>( xComponent.get() );
143 TNumberedItemHash::iterator pIt = m_lComponents.find (pComponent);
144
145 // a) component exists and will be removed
146 if (pIt != m_lComponents.end())
147 m_lComponents.erase(pIt);
148
149 // else
150 // b) component does not exists - nothing todo here (ignore request!)
151
152 // <- SYNCHRONIZED
153}
154
155
157{
158 // SYNCHRONIZED ->
159 std::scoped_lock aLock(m_aMutex);
160
161 return m_sUntitledPrefix;
162
163 // <- SYNCHRONIZED
164}
165
166
180{
181 // create bitset, where each position represents one possible number.
182 std::vector<bool> aUsedNumbers((m_lComponents.size() * 2) + 1, false);
183
184 for (const auto& rPair : m_lComponents)
185 {
186 // numbers start at 1
187 sal_Int32 pos = rPair.second.nNumber - 1;
188 if (pos >= static_cast<sal_Int32>(aUsedNumbers.size()))
189 aUsedNumbers.resize(pos * 2, false); // should be rare
190 aUsedNumbers[pos] = true;
191 }
192
193 // a) non free numbers ... return INVALID_NUMBER
194 auto it = std::find(aUsedNumbers.begin(), aUsedNumbers.end(), false);
195 if (it == aUsedNumbers.end())
196 return css::frame::UntitledNumbersConst::INVALID_NUMBER;
197
198 // b) return first free number
199 return it - aUsedNumbers.begin() + 1;
200}
201
203 const TDeadItemList& lDeadItems)
204{
205 for (const sal_IntPtr& rDeadItem : lDeadItems)
206 {
207 lItems.erase(rDeadItem);
208 }
209}
210
211} // namespace comphelper
212
213/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString m_sUntitledPrefix
localized string to be used for untitled components
void setOwner(const css::uno::Reference< css::uno::XInterface > &xOwner)
set an outside component which uses this container and must be set as source of all broadcasted messa...
TNumberedItemHash m_lComponents
cache of all "leased numbers" and its bound components
::sal_Int32 impl_searchFreeNumber()
tries to find a unique number not already used within this collection.
NumberedCollection()
lightweight constructor.
virtual ~NumberedCollection() override
free all internally used resources.
css::uno::WeakReference< css::uno::XInterface > m_xOwner
used as source of broadcasted messages or exceptions (can be null !)
std::unordered_map< sal_IntPtr, TNumberedItem > TNumberedItemHash
virtual void SAL_CALL releaseNumber(::sal_Int32 nNumber) override
::std::vector< sal_IntPtr > TDeadItemList
static void impl_cleanUpDeadItems(TNumberedItemHash &lItems, const TDeadItemList &lDeadItems)
virtual OUString SAL_CALL getUntitledPrefix() override
virtual void SAL_CALL releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface > &xComponent) override
void setUntitledPrefix(const OUString &sPrefix)
set the localized prefix to be used for untitled components.
virtual ::sal_Int32 SAL_CALL leaseNumber(const css::uno::Reference< css::uno::XInterface > &xComponent) override
float u
Mutex aLock
OUString sPrefix
constexpr OUStringLiteral ERRMSG_INVALID_COMPONENT_PARAM
static PropertyMapEntry const * find(const rtl::Reference< PropertySetInfo > &mxInfo, const OUString &aName) noexcept
css::uno::WeakReference< css::uno::XInterface > xItem
size_t pos