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