1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: inethist.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include <svtools/inethist.hxx>
35 #ifndef INCLUDED_ALGORITHM
37 #define INCLUDED_ALGORITHM
39 #include "rtl/instance.hxx"
41 #include "rtl/memory.h"
42 #include <tools/solar.h>
43 #include <tools/debug.hxx>
44 #include <tools/string.hxx>
45 #include <tools/urlobj.hxx>
47 /*========================================================================
49 * INetURLHistory internals.
51 *======================================================================*/
52 #define INETHIST_DEF_FTP_PORT 21
53 #define INETHIST_DEF_HTTP_PORT 80
54 #define INETHIST_DEF_HTTPS_PORT 443
56 #define INETHIST_SIZE_LIMIT 1024
57 #define INETHIST_MAGIC_HEAD 0x484D4849UL
60 * INetURLHistoryHint implementation.
62 IMPL_PTRHINT (INetURLHistoryHint
, const INetURLObject
);
64 /*========================================================================
66 * INetURLHistory_Impl interface.
68 *======================================================================*/
69 class INetURLHistory_Impl
83 void initialize (void)
85 m_nMagic
= INETHIST_MAGIC_HEAD
;
103 void initialize (UINT16 nLru
, UINT32 nHash
= 0)
112 BOOL
operator== (const hash_entry
&rOther
) const
114 return (m_nHash
== rOther
.m_nHash
);
116 BOOL
operator< (const hash_entry
&rOther
) const
118 return (m_nHash
< rOther
.m_nHash
);
121 BOOL
operator== (UINT32 nHash
) const
123 return (m_nHash
== nHash
);
125 BOOL
operator< (UINT32 nHash
) const
127 return (m_nHash
< nHash
);
143 void initialize (UINT16 nThis
, UINT32 nHash
= 0)
154 hash_entry m_pHash
[INETHIST_SIZE_LIMIT
];
155 lru_entry m_pList
[INETHIST_SIZE_LIMIT
];
159 void initialize (void);
161 void downheap (hash_entry a
[], UINT16 n
, UINT16 k
);
162 void heapsort (hash_entry a
[], UINT16 n
);
166 UINT16
capacity (void) const
168 return (UINT16
)(INETHIST_SIZE_LIMIT
);
173 UINT32
crc32 (UniString
const & rData
) const
175 return rtl_crc32 (0, rData
.GetBuffer(), rData
.Len() * sizeof(sal_Unicode
));
180 UINT16
find (UINT32 nHash
) const;
184 void move (UINT16 nSI
, UINT16 nDI
);
188 void backlink (UINT16 nThis
, UINT16 nTail
)
190 register lru_entry
&rThis
= m_pList
[nThis
];
191 register lru_entry
&rTail
= m_pList
[nTail
];
193 rTail
.m_nNext
= nThis
;
194 rTail
.m_nPrev
= rThis
.m_nPrev
;
195 rThis
.m_nPrev
= nTail
;
196 m_pList
[rTail
.m_nPrev
].m_nNext
= nTail
;
201 void unlink (UINT16 nThis
)
203 register lru_entry
&rThis
= m_pList
[nThis
];
205 m_pList
[rThis
.m_nPrev
].m_nNext
= rThis
.m_nNext
;
206 m_pList
[rThis
.m_nNext
].m_nPrev
= rThis
.m_nPrev
;
207 rThis
.m_nNext
= nThis
;
208 rThis
.m_nPrev
= nThis
;
213 INetURLHistory_Impl (const INetURLHistory_Impl
&);
214 INetURLHistory_Impl
& operator= (const INetURLHistory_Impl
&);
217 INetURLHistory_Impl (void);
218 ~INetURLHistory_Impl (void);
222 void putUrl (const String
&rUrl
);
223 BOOL
queryUrl (const String
&rUrl
);
226 /*========================================================================
228 * INetURLHistory_Impl implementation.
230 *======================================================================*/
232 * INetURLHistory_Impl.
234 INetURLHistory_Impl::INetURLHistory_Impl (void)
240 * ~INetURLHistory_Impl.
242 INetURLHistory_Impl::~INetURLHistory_Impl (void)
249 void INetURLHistory_Impl::initialize (void)
251 m_aHead
.initialize();
253 USHORT i
, n
= capacity();
254 for (i
= 0; i
< n
; i
++)
255 m_pHash
[i
].initialize(i
);
256 for (i
= 0; i
< n
; i
++)
257 m_pList
[i
].initialize(i
);
258 for (i
= 1; i
< n
; i
++)
259 backlink (m_aHead
.m_nNext
, i
);
265 void INetURLHistory_Impl::downheap (hash_entry a
[], UINT16 n
, UINT16 k
)
270 UINT16 i
= k
+ k
+ 1;
271 if (((i
+ 1) < n
) && (a
[i
] < a
[i
+ 1])) i
++;
272 if (!(h
< a
[i
])) break;
282 void INetURLHistory_Impl::heapsort (hash_entry a
[], UINT16 n
)
286 for (UINT16 k
= (n
- 1) / 2 + 1; k
> 0; k
--)
287 downheap (a
, n
, k
- 1);
294 downheap (a
, --n
, 0);
301 UINT16
INetURLHistory_Impl::find (UINT32 nHash
) const
304 UINT16 r
= capacity() - 1;
305 UINT16 c
= capacity();
307 while ((l
< r
) && (r
< c
))
309 UINT16 m
= (l
+ r
) / 2;
310 if (m_pHash
[m
] == nHash
)
313 if (m_pHash
[m
] < nHash
)
324 void INetURLHistory_Impl::move (UINT16 nSI
, UINT16 nDI
)
326 hash_entry e
= m_pHash
[nSI
];
333 (nDI
- nSI
) * sizeof(hash_entry
));
341 (nSI
- nDI
) * sizeof(hash_entry
));
349 void INetURLHistory_Impl::putUrl (const String
&rUrl
)
351 UINT32 h
= crc32 (rUrl
);
353 if ((k
< capacity()) && (m_pHash
[k
] == h
))
356 UINT16 nMRU
= m_pHash
[k
].m_nLru
;
357 if (nMRU
!= m_aHead
.m_nNext
)
361 backlink (m_aHead
.m_nNext
, nMRU
);
364 m_aHead
.m_nNext
= m_pList
[m_aHead
.m_nNext
].m_nPrev
;
369 // Cache miss. Obtain least recently used.
370 UINT16 nLRU
= m_pList
[m_aHead
.m_nNext
].m_nPrev
;
372 UINT16 nSI
= find (m_pList
[nLRU
].m_nHash
);
373 if (!(nLRU
== m_pHash
[nSI
].m_nLru
))
376 nLRU
= m_pHash
[nSI
].m_nLru
;
378 backlink (m_aHead
.m_nNext
, nLRU
);
382 m_aHead
.m_nNext
= m_pList
[m_aHead
.m_nNext
].m_nPrev
;
384 // Check source and destination.
385 UINT16 nDI
= std::min (k
, UINT16(capacity() - 1));
388 if (!(m_pHash
[nDI
] < h
))
393 if (m_pHash
[nDI
] < h
)
398 m_pList
[m_aHead
.m_nNext
].m_nHash
= m_pHash
[nSI
].m_nHash
= h
;
406 BOOL
INetURLHistory_Impl::queryUrl (const String
&rUrl
)
408 UINT32 h
= crc32 (rUrl
);
410 if ((k
< capacity()) && (m_pHash
[k
] == h
))
422 /*========================================================================
424 * INetURLHistory::StaticInstance implementation.
426 *======================================================================*/
427 INetURLHistory
* INetURLHistory::StaticInstance::operator ()()
429 static INetURLHistory g_aInstance
;
433 /*========================================================================
435 * INetURLHistory implementation.
437 *======================================================================*/
441 INetURLHistory::INetURLHistory() : m_pImpl (new INetURLHistory_Impl())
448 INetURLHistory::~INetURLHistory()
456 INetURLHistory
* INetURLHistory::GetOrCreate()
459 INetURLHistory
, StaticInstance
,
460 osl::MutexGuard
, osl::GetGlobalMutex
>::create (
461 StaticInstance(), osl::GetGlobalMutex());
467 void INetURLHistory::NormalizeUrl_Impl (INetURLObject
&rUrl
)
469 switch (rUrl
.GetProtocol())
472 if (!rUrl
.IsCaseSensitive())
474 String
aPath (rUrl
.GetURLPath(INetURLObject::NO_DECODE
));
475 aPath
.ToLowerAscii();
476 rUrl
.SetURLPath (aPath
, INetURLObject::NOT_CANONIC
);
482 rUrl
.SetPort (INETHIST_DEF_FTP_PORT
);
487 rUrl
.SetPort (INETHIST_DEF_HTTP_PORT
);
488 if (!rUrl
.HasURLPath())
489 rUrl
.SetURLPath ("/");
492 case INET_PROT_HTTPS
:
494 rUrl
.SetPort (INETHIST_DEF_HTTPS_PORT
);
495 if (!rUrl
.HasURLPath())
496 rUrl
.SetURLPath ("/");
507 void INetURLHistory::PutUrl_Impl (const INetURLObject
&rUrl
)
509 DBG_ASSERT (m_pImpl
, "PutUrl_Impl(): no Implementation");
512 INetURLObject
aHistUrl (rUrl
);
513 NormalizeUrl_Impl (aHistUrl
);
515 m_pImpl
->putUrl (aHistUrl
.GetMainURL(INetURLObject::NO_DECODE
));
516 Broadcast (INetURLHistoryHint (&rUrl
));
518 if (aHistUrl
.HasMark())
520 aHistUrl
.SetURL (aHistUrl
.GetURLNoMark(INetURLObject::NO_DECODE
),
521 INetURLObject::NOT_CANONIC
);
523 m_pImpl
->putUrl (aHistUrl
.GetMainURL(INetURLObject::NO_DECODE
));
524 Broadcast (INetURLHistoryHint (&aHistUrl
));
532 BOOL
INetURLHistory::QueryUrl_Impl (const INetURLObject
&rUrl
)
534 DBG_ASSERT (m_pImpl
, "QueryUrl_Impl(): no Implementation");
537 INetURLObject
aHistUrl (rUrl
);
538 NormalizeUrl_Impl (aHistUrl
);
540 return m_pImpl
->queryUrl (aHistUrl
.GetMainURL(INetURLObject::NO_DECODE
));