LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
stringspool.cpp
Go to the documentation of this file.
1// Copyright 2002-2020 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6//
7// C++ Implementation: stringspool
8//
9// Description:
10//
11//
12// Author: CEA LIST <Gael.de-Chalendar@cea.fr>
13//
14// Copyright: See COPYING file that comes with this distribution
15//
16//
17#include "stringspool.h"
19
20#include <QMutex>
21
22#include <set>
23
24namespace Lima {
25
27{
28 friend class StringsPool;
29
31
32 StringsPoolPrivate(const StringsPool& /*unused p*/);
33
35
36 void clear();
37 void clear(const uint64_t pos);
38
39 struct HashLimaStringPtr
40 {
41 size_t operator()(const Lima::LimaString* s) const;
42 };
43
44 struct EquaLimaStringPtr
45 {
46 bool operator()(const Lima::LimaString* s1, const Lima::LimaString* s2) const;
47 };
48
49 typedef std::unordered_map<
50 const Lima::LimaString*,
51 StringsPoolIndex,
52 HashLimaStringPtr,
53 EquaLimaStringPtr > LimaStringPtrHashMap;
54 LimaStringPtrHashMap m_hashPool;
55 LimaStringPtrHashMap m_resourcesHashPool;
56 std::vector< LimaString* > m_vecPool;
57
58 // index of the position in vecPool for reinitialization (after
59 // data initialized by resources)
60 uint64_t m_resourcesPoolIndex;
61
62 std::set< void* > m_users;
63
64 QMutex m_mutex;
65};
66
67StringsPoolPrivate::StringsPoolPrivate():
68 m_hashPool(),
69 m_resourcesHashPool(),
70 m_vecPool(),
71 m_resourcesPoolIndex(0),
72 m_users(),
73 m_mutex()
74{
75 StringsPoolIndex newPosition = static_cast<StringsPoolIndex>(m_vecPool.size());
76 LimaString* newString = new LimaString();
77 const_cast< std::vector< LimaString* >* >(&m_vecPool)->push_back(newString);
78 const_cast< StringsPoolPrivate::LimaStringPtrHashMap* >(&m_hashPool)->insert(std::make_pair(newString, newPosition));
79 m_resourcesPoolIndex=1;
80}
81
82
83StringsPoolPrivate::~StringsPoolPrivate()
84{
85 // delete all (including resourcesPool)
86 clear(0);
87}
88
93
95{
96 delete m_d;
97}
98
100{
101 return m_d->m_vecPool.size()==1;
102}
103
104uint64_t StringsPool::size() const
105{
106 return m_d->m_vecPool.size();
107}
108
109
111 m_d->m_resourcesPoolIndex=m_d->m_vecPool.size();
112 m_d->m_resourcesHashPool=m_d->m_hashPool;
113}
114
115StringsPoolIndex StringsPool::operator[](const LimaString& str) const
116{
117 //STRPOOLLOGINIT;
118 //LTRACE << "StringsPool[" << str << "]";
119 if (m_d->m_hashPool.find(&str) == m_d->m_hashPool.end())
120 {
121 StringsPoolIndex newPosition = static_cast<StringsPoolIndex>(m_d->m_vecPool.size());
122 LimaString* newString = new LimaString(str);
123 const_cast< std::vector< LimaString* >* >(&m_d->m_vecPool)->push_back(newString);
124 const_cast< StringsPoolPrivate::LimaStringPtrHashMap* >(&m_d->m_hashPool)->insert(std::make_pair(newString, newPosition));
125 //LTRACE << " ... not found. Created entry n" << newPosition;
126 return newPosition;
127 }
128 else
129 {
130 StringsPoolIndex pos = (*(const_cast< StringsPoolPrivate::LimaStringPtrHashMap* >(&m_d->m_hashPool)))[&str];
131 //LTRACE << " ... found at index " << pos;
132 return pos;
133 }
134}
135
136StringsPoolIndex StringsPool::operator[](const LimaString& str)
137{
138 //STRPOOLLOGINIT;
139 //LTRACE << "StringsPool[" << str << "]";
140 if (m_d->m_hashPool.find(&str) == m_d->m_hashPool.end())
141 {
142 QMutexLocker locker(&m_d->m_mutex);
143 StringsPoolIndex newPosition = static_cast<StringsPoolIndex>(m_d->m_vecPool.size());
144 LimaString* newString = new LimaString(str);
145 m_d->m_vecPool.push_back(newString);
146 m_d->m_hashPool.insert(std::make_pair(newString, newPosition));
147 //LTRACE << " ... not found. Created entry n" << newPosition;
148 return newPosition;
149 }
150 else
151 {
152 StringsPoolIndex pos = m_d->m_hashPool[&str];
153 //LTRACE << " ... found at index " << pos;
154 return pos;
155 }
156}
157
158const LimaString& StringsPool::operator[](const StringsPoolIndex ind) const
159{
160 //STRPOOLLOGINIT;
161 //LTRACE << "const StringsPool[" << ind << "]";
162 if (ind >= static_cast<StringsPoolIndex>(m_d->m_vecPool.size()))
163 {
164 std::ostringstream oss;
165 oss << "stringspool(size = " << m_d->m_vecPool.size() << "): Out of bounds (" << ind << ")";
166 throw std::runtime_error(oss.str());
167 }
168 //LTRACE << "StringsPool[" << ind << "] = " << *(m_d->m_vecPool[ind]);
169 return *(m_d->m_vecPool[ind]);
170}
171
172LimaString& StringsPool::operator[](const StringsPoolIndex ind)
173{
174 //STRPOOLLOGINIT;
175 //LTRACE << "StringsPool[" << ind << "]";
176 if (ind >= static_cast<StringsPoolIndex>(m_d->m_vecPool.size()))
177 {
178 std::ostringstream oss;
179 oss << "stringspool(size = " << m_d->m_vecPool.size() << "): Out of bounds (" << ind << ")";
180 throw std::runtime_error(oss.str());
181 }
182 //LTRACE << "StringsPool[" << ind << "] = " << *(m_d->m_vecPool[ind]);
183 return *(m_d->m_vecPool[ind]);
184}
185
187{
188// STRPOOLLOGINIT;
189// LDEBUG << "Stringspool registering user " << p;
190 m_d->m_users.insert(p);
191}
192
194{
195// STRPOOLLOGINIT;
196// LDEBUG << "Stringspool unregistering user " << p;
197 std::set< void* >::iterator it = m_d->m_users.find(p);
198 if ( it != m_d->m_users.end() )
199 m_d->m_users.erase(it);
200
201 if (m_d->m_users.empty())
202 m_d->clear();
203}
204
205void StringsPoolPrivate::clear()
206{
207 clear(m_resourcesPoolIndex);
208}
209
210// reinit from pos to the end
211void StringsPoolPrivate::clear(const uint64_t pos)
212{
213 // reinitialize hashPool
214 // WARNING: The m_hashPool hash table contains the same pointer as the m_vecPool
215 // vector. So, override its content BEFORE free memory to avoid crash (on Windows)
216 m_hashPool=m_resourcesHashPool;
217
218// STRPOOLLOGINIT;
219// LDEBUG << "clearing StringsPool";
220 uint64_t i(pos),size(m_vecPool.size());
221 for (; i != size; i++)
222 {
223 delete (m_vecPool[i]);
224 m_vecPool[i] = 0;
225 }
226 m_vecPool.resize(pos);
227}
228
229#define MAX_DEPTH 25
230size_t StringsPoolPrivate::HashLimaStringPtr::operator()(const Lima::LimaString* s) const
231{
232 const int shift[] = {0,8,16,24}; // 4 shifts to "occupy" 32 bits
233 uint64_t key = 0x55555555; //0101...
234 uint64_t oneChar;
235 int depth = s->length();
236 if (depth > MAX_DEPTH)
237 depth = MAX_DEPTH;
238 for (int i=0; i<depth; i++) {
239 oneChar = ((uint64_t) ((*s)[i].unicode()) )<<shift[i%4];
240 key^=oneChar; // exclusive or
241 }
242 return key;
243}
244
245bool StringsPoolPrivate::EquaLimaStringPtr::operator()(
246 const Lima::LimaString* s1,
247 const Lima::LimaString* s2) const
248{
249 return ((*s1) == (*s2));
250}
251
252
253} // closing namespace Lima
StringsPoolIndex operator[](const LimaString &str) const
void registerUser(void *p)
void unregisterUser(void *p)
uint64_t size() const
bool empty() const
NAUTITIA.
QString LimaString
Definition LimaString.h:33
#define MAX_DEPTH