Line data Source code
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 :
10 : #include "svl/sharedstringpool.hxx"
11 : #include "unotools/charclass.hxx"
12 :
13 : namespace svl {
14 :
15 1901 : SharedStringPool::SharedStringPool( const CharClass* pCharClass ) : mpCharClass(pCharClass) {}
16 :
17 18196 : SharedString SharedStringPool::intern( const OUString& rStr )
18 : {
19 18196 : osl::MutexGuard aGuard(&maMutex);
20 :
21 18196 : InsertResultType aRes = findOrInsert(maStrPool, rStr);
22 18196 : if (aRes.first == maStrPool.end())
23 : // Insertion failed.
24 0 : return SharedString();
25 :
26 18196 : rtl_uString* pOrig = aRes.first->pData;
27 :
28 18196 : if (!mpCharClass)
29 : // We don't track case insensitive strings.
30 0 : return SharedString(pOrig, NULL);
31 :
32 18196 : if (!aRes.second)
33 : {
34 : // No new string has been inserted. Return the existing string in the pool.
35 13322 : StrStoreType::iterator it = maStrStore.find(pOrig);
36 13322 : if (it == maStrStore.end())
37 0 : return SharedString();
38 :
39 13322 : rtl_uString* pUpper = it->second.pData;
40 13322 : return SharedString(pOrig, pUpper);
41 : }
42 :
43 : // This is a new string insertion. Establish mapping to upper-case variant.
44 :
45 9748 : OUString aUpper = mpCharClass->uppercase(rStr);
46 4874 : aRes = findOrInsert(maStrPoolUpper, aUpper);
47 4874 : if (aRes.first == maStrPoolUpper.end())
48 : // Failed to insert or fetch upper-case variant. Should never happen.
49 0 : return SharedString();
50 :
51 4874 : maStrStore.insert(StrStoreType::value_type(pOrig, *aRes.first));
52 :
53 23070 : return SharedString(pOrig, aRes.first->pData);
54 : }
55 :
56 : namespace {
57 :
58 56 : inline sal_Int32 getRefCount( const rtl_uString* p )
59 : {
60 56 : return (p->refCount & 0x3FFFFFFF);
61 : }
62 :
63 : }
64 :
65 12 : void SharedStringPool::purge()
66 : {
67 12 : osl::MutexGuard aGuard(&maMutex);
68 :
69 24 : StrHashType aNewStrPool;
70 12 : StrHashType::iterator it = maStrPool.begin(), itEnd = maStrPool.end();
71 47 : for (; it != itEnd; ++it)
72 : {
73 35 : const rtl_uString* p = it->pData;
74 35 : if (getRefCount(p) == 1)
75 : {
76 : // Remove it from the upper string map. This should unref the
77 : // upper string linked to this original string.
78 11 : maStrStore.erase(p);
79 : }
80 : else
81 : // Still referenced outside the pool. Keep it.
82 24 : aNewStrPool.insert(*it);
83 : }
84 :
85 12 : maStrPool.swap(aNewStrPool);
86 :
87 12 : aNewStrPool.clear(); // for re-use.
88 :
89 : // Purge the upper string pool as well.
90 12 : it = maStrPoolUpper.begin();
91 12 : itEnd = maStrPoolUpper.end();
92 33 : for (; it != itEnd; ++it)
93 : {
94 21 : const rtl_uString* p = it->pData;
95 21 : if (getRefCount(p) > 1)
96 16 : aNewStrPool.insert(*it);
97 : }
98 :
99 24 : maStrPoolUpper.swap(aNewStrPool);
100 12 : }
101 :
102 14 : size_t SharedStringPool::getCount() const
103 : {
104 14 : osl::MutexGuard aGuard(&maMutex);
105 14 : return maStrPool.size();
106 : }
107 :
108 14 : size_t SharedStringPool::getCountIgnoreCase() const
109 : {
110 14 : osl::MutexGuard aGuard(&maMutex);
111 14 : return maStrPoolUpper.size();
112 : }
113 :
114 23070 : SharedStringPool::InsertResultType SharedStringPool::findOrInsert( StrHashType& rPool, const OUString& rStr ) const
115 : {
116 23070 : StrHashType::iterator it = rPool.find(rStr);
117 23070 : bool bInserted = false;
118 23070 : if (it == rPool.end())
119 : {
120 : // Not yet in the pool.
121 9700 : std::pair<StrHashType::iterator, bool> r = rPool.insert(rStr);
122 9700 : if (!r.second)
123 : // Insertion failed.
124 0 : return InsertResultType(rPool.end(), false);
125 :
126 9700 : it = r.first;
127 9700 : bInserted = true;
128 : }
129 :
130 23070 : return InsertResultType(it, bInserted);
131 : }
132 :
133 : }
134 :
135 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|