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