1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <svl/sharedstringpool.hxx>
11 #include <svl/sharedstring.hxx>
12 #include <unotools/charclass.hxx>
13 #include <osl/mutex.hxx>
15 #include <unordered_map>
16 #include <unordered_set>
22 sal_Int32
getRefCount( const rtl_uString
* p
)
24 return (p
->refCount
& 0x3FFFFFFF);
29 struct SharedStringPool::Impl
31 mutable osl::Mutex maMutex
;
32 // set of upper-case, so we can share these as the value in the maStrMap
33 std::unordered_set
<OUString
> maStrPoolUpper
;
34 // map with rtl_uString* as key so we can avoid some ref-counting
35 std::unordered_map
<OUString
,rtl_uString
*> maStrMap
;
36 const CharClass
& mrCharClass
;
38 explicit Impl( const CharClass
& rCharClass
) : mrCharClass(rCharClass
) {}
41 SharedStringPool::SharedStringPool( const CharClass
& rCharClass
) :
42 mpImpl(new Impl(rCharClass
)) {}
44 SharedStringPool::~SharedStringPool()
48 SharedString
SharedStringPool::intern( const OUString
& rStr
)
50 osl::MutexGuard
aGuard(&mpImpl
->maMutex
);
52 auto [mapIt
,bInserted
] = mpImpl
->maStrMap
.emplace(rStr
, rStr
.pData
);
55 // This is a new string insertion. Establish mapping to upper-case variant.
56 OUString aUpper
= mpImpl
->mrCharClass
.uppercase(rStr
);
59 auto insertResult
= mpImpl
->maStrPoolUpper
.insert(rStr
);
60 mapIt
->second
= insertResult
.first
->pData
;
64 auto insertResult
= mpImpl
->maStrPoolUpper
.insert(aUpper
);
65 mapIt
->second
= insertResult
.first
->pData
;
68 return SharedString(mapIt
->first
.pData
, mapIt
->second
);
71 void SharedStringPool::purge()
73 osl::MutexGuard
aGuard(&mpImpl
->maMutex
);
75 std::unordered_set
<OUString
> aNewStrPoolUpper
;
77 auto it
= mpImpl
->maStrMap
.begin(), itEnd
= mpImpl
->maStrMap
.end();
80 const rtl_uString
* p
= it
->first
.pData
;
81 if (getRefCount(p
) == 1)
82 it
= mpImpl
->maStrMap
.erase(it
);
85 // Still referenced outside the pool. Keep it.
86 aNewStrPoolUpper
.insert(it
->second
);
91 mpImpl
->maStrPoolUpper
= std::move(aNewStrPoolUpper
);
94 size_t SharedStringPool::getCount() const
96 osl::MutexGuard
aGuard(&mpImpl
->maMutex
);
97 return mpImpl
->maStrMap
.size();
100 size_t SharedStringPool::getCountIgnoreCase() const
102 osl::MutexGuard
aGuard(&mpImpl
->maMutex
);
103 return mpImpl
->maStrPoolUpper
.size();
108 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */