tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svl / source / misc / inethist.cxx
blob12e0b66365cd282c58da58a3d96b52b8565d5031
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svl/inethist.hxx>
22 #include <algorithm>
23 #include <string.h>
25 #include <rtl/crc.h>
26 #include <tools/debug.hxx>
27 #include <tools/urlobj.hxx>
30 * INetURLHistory internals.
32 #define INETHIST_DEF_FTP_PORT 21
33 #define INETHIST_DEF_HTTP_PORT 80
34 #define INETHIST_DEF_HTTPS_PORT 443
36 #define INETHIST_SIZE_LIMIT 1024
37 #define INETHIST_MAGIC_HEAD 0x484D4849UL
39 class INetURLHistory_Impl
41 struct head_entry
43 /** Representation.
45 sal_uInt32 m_nMagic;
46 sal_uInt16 m_nNext;
48 /** Initialization.
50 void initialize()
52 m_nMagic = INETHIST_MAGIC_HEAD;
53 m_nNext = 0;
57 struct hash_entry
59 /** Representation.
61 sal_uInt32 m_nHash;
62 sal_uInt16 m_nLru;
64 /** Initialization.
66 void initialize (sal_uInt16 nLru)
68 m_nHash = 0;
69 m_nLru = nLru;
72 /** Comparison.
74 bool operator== (sal_uInt32 nHash) const
76 return (m_nHash == nHash);
78 bool operator< (sal_uInt32 nHash) const
80 return (m_nHash < nHash);
84 struct lru_entry
86 /** Representation.
88 sal_uInt32 m_nHash;
89 sal_uInt16 m_nNext;
90 sal_uInt16 m_nPrev;
92 /** Initialization.
94 void initialize (sal_uInt16 nThis)
96 m_nHash = 0;
97 m_nNext = nThis;
98 m_nPrev = nThis;
102 /** Representation.
104 head_entry m_aHead;
105 hash_entry m_pHash[INETHIST_SIZE_LIMIT];
106 lru_entry m_pList[INETHIST_SIZE_LIMIT];
108 /** Initialization.
110 void initialize();
112 static sal_uInt16 capacity()
114 return sal_uInt16(INETHIST_SIZE_LIMIT);
117 static sal_uInt32 crc32 (OUString const & rData)
119 return rtl_crc32 (0, rData.getStr(), rData.getLength() * sizeof(sal_Unicode));
122 sal_uInt16 find (sal_uInt32 nHash) const;
124 void move (sal_uInt16 nSI, sal_uInt16 nDI);
126 void backlink (sal_uInt16 nThis, sal_uInt16 nTail)
128 lru_entry &rThis = m_pList[nThis];
129 lru_entry &rTail = m_pList[nTail];
131 rTail.m_nNext = nThis;
132 rTail.m_nPrev = rThis.m_nPrev;
133 rThis.m_nPrev = nTail;
134 m_pList[rTail.m_nPrev].m_nNext = nTail;
137 void unlink (sal_uInt16 nThis)
139 lru_entry &rThis = m_pList[nThis];
141 m_pList[rThis.m_nPrev].m_nNext = rThis.m_nNext;
142 m_pList[rThis.m_nNext].m_nPrev = rThis.m_nPrev;
143 rThis.m_nNext = nThis;
144 rThis.m_nPrev = nThis;
147 public:
148 INetURLHistory_Impl();
149 INetURLHistory_Impl(const INetURLHistory_Impl&) = delete;
150 INetURLHistory_Impl& operator=(const INetURLHistory_Impl&) = delete;
152 /** putUrl/queryUrl.
154 void putUrl (const OUString &rUrl);
155 bool queryUrl (const OUString &rUrl) const;
158 INetURLHistory_Impl::INetURLHistory_Impl()
160 initialize();
163 void INetURLHistory_Impl::initialize()
165 m_aHead.initialize();
167 sal_uInt16 i, n = capacity();
168 for (i = 0; i < n; i++)
169 m_pHash[i].initialize(i);
170 for (i = 0; i < n; i++)
171 m_pList[i].initialize(i);
172 for (i = 1; i < n; i++)
173 backlink (m_aHead.m_nNext, i);
176 sal_uInt16 INetURLHistory_Impl::find (sal_uInt32 nHash) const
178 sal_uInt16 l = 0;
179 sal_uInt16 r = capacity() - 1;
180 sal_uInt16 c = capacity();
182 while ((l < r) && (r < c))
184 sal_uInt16 m = ((l + r) / 2) & 0xFFFF;
185 if (m_pHash[m] == nHash)
186 return m;
188 if (m_pHash[m] < nHash)
189 l = m + 1;
190 else
191 r = m - 1;
193 return l;
196 void INetURLHistory_Impl::move (sal_uInt16 nSI, sal_uInt16 nDI)
198 hash_entry e = m_pHash[nSI];
199 if (nSI < nDI)
201 // shift left.
202 memmove (
203 &m_pHash[nSI ],
204 &m_pHash[nSI + 1],
205 (nDI - nSI) * sizeof(hash_entry));
207 if (nSI > nDI)
209 // shift right.
210 memmove (
211 &m_pHash[nDI + 1],
212 &m_pHash[nDI ],
213 (nSI - nDI) * sizeof(hash_entry));
215 m_pHash[nDI] = e;
218 void INetURLHistory_Impl::putUrl (const OUString &rUrl)
220 sal_uInt32 h = crc32 (rUrl);
221 sal_uInt16 k = find (h);
222 if ((k < capacity()) && (m_pHash[k] == h))
224 // Cache hit.
225 sal_uInt16 nMRU = m_pHash[k].m_nLru;
226 if (nMRU != m_aHead.m_nNext)
228 // Update LRU chain.
229 unlink (nMRU);
230 backlink (m_aHead.m_nNext, nMRU);
232 // Rotate LRU chain.
233 m_aHead.m_nNext = m_pList[m_aHead.m_nNext].m_nPrev;
236 else
238 // Cache miss. Obtain least recently used.
239 sal_uInt16 nLRU = m_pList[m_aHead.m_nNext].m_nPrev;
241 sal_uInt16 nSI = find (m_pList[nLRU].m_nHash);
242 if (nLRU != m_pHash[nSI].m_nLru)
244 // Update LRU chain.
245 nLRU = m_pHash[nSI].m_nLru;
246 unlink (nLRU);
247 backlink (m_aHead.m_nNext, nLRU);
250 // Rotate LRU chain.
251 m_aHead.m_nNext = m_pList[m_aHead.m_nNext].m_nPrev;
253 // Check source and destination.
254 sal_uInt16 nDI = std::min (k, sal_uInt16(capacity() - 1));
255 if (nSI < nDI && !(m_pHash[nDI] < h))
256 nDI -= 1;
257 if (nDI < nSI && m_pHash[nDI] < h)
258 nDI += 1;
260 // Assign data.
261 m_pList[m_aHead.m_nNext].m_nHash = m_pHash[nSI].m_nHash = h;
262 move (nSI, nDI);
266 bool INetURLHistory_Impl::queryUrl (const OUString &rUrl) const
268 sal_uInt32 h = crc32 (rUrl);
269 sal_uInt16 k = find (h);
270 // true if cache hit
271 return (k < capacity()) && (m_pHash[k] == h);
274 INetURLHistory::INetURLHistory() : m_pImpl (new INetURLHistory_Impl())
278 INetURLHistory::~INetURLHistory()
283 * GetOrCreate.
285 INetURLHistory* INetURLHistory::GetOrCreate()
287 static INetURLHistory instance;
288 return &instance;
291 void INetURLHistory::NormalizeUrl_Impl (INetURLObject &rUrl)
293 switch (rUrl.GetProtocol())
295 case INetProtocol::File:
296 if (!INetURLObject::IsCaseSensitive())
298 OUString aPath (rUrl.GetURLPath(INetURLObject::DecodeMechanism::NONE).toAsciiLowerCase());
299 rUrl.SetURLPath (aPath, INetURLObject::EncodeMechanism::NotCanonical);
301 break;
303 case INetProtocol::Ftp:
304 if (!rUrl.HasPort())
305 rUrl.SetPort (INETHIST_DEF_FTP_PORT);
306 break;
308 case INetProtocol::Http:
309 if (!rUrl.HasPort())
310 rUrl.SetPort (INETHIST_DEF_HTTP_PORT);
311 if (!rUrl.HasURLPath())
312 rUrl.SetURLPath(u"/");
313 break;
315 case INetProtocol::Https:
316 if (!rUrl.HasPort())
317 rUrl.SetPort (INETHIST_DEF_HTTPS_PORT);
318 if (!rUrl.HasURLPath())
319 rUrl.SetURLPath(u"/");
320 break;
322 default:
323 break;
327 void INetURLHistory::PutUrl_Impl (const INetURLObject &rUrl)
329 DBG_ASSERT (m_pImpl, "PutUrl_Impl(): no Implementation");
330 if (!m_pImpl)
331 return;
333 INetURLObject aHistUrl (rUrl);
334 NormalizeUrl_Impl (aHistUrl);
336 m_pImpl->putUrl (aHistUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE));
337 Broadcast (INetURLHistoryHint (&rUrl));
339 if (aHistUrl.HasMark())
341 aHistUrl.SetURL (aHistUrl.GetURLNoMark(INetURLObject::DecodeMechanism::NONE),
342 INetURLObject::EncodeMechanism::NotCanonical);
344 m_pImpl->putUrl (aHistUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE));
345 Broadcast (INetURLHistoryHint (&aHistUrl));
349 bool INetURLHistory::QueryUrl(std::u16string_view rUrl) const
351 INetProtocol eProto = INetURLObject::CompareProtocolScheme (rUrl);
352 if (!QueryProtocol (eProto))
353 return false;
354 return QueryUrl_Impl( INetURLObject(rUrl) );
358 bool INetURLHistory::QueryUrl_Impl (INetURLObject rUrl) const
360 DBG_ASSERT (m_pImpl, "QueryUrl_Impl(): no Implementation");
361 if (m_pImpl)
363 NormalizeUrl_Impl (rUrl);
365 return m_pImpl->queryUrl (rUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE));
367 return false;
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */