LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/svl/source/misc - inethist.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 134 159 84.3 %
Date: 2013-07-09 Functions: 28 32 87.5 %
Legend: Lines: hit not hit

          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             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <svl/inethist.hxx>
      21             : 
      22             : #include <algorithm>
      23             : #include <string.h>
      24             : 
      25             : #include "rtl/instance.hxx"
      26             : #include "rtl/crc.h"
      27             : #include <tools/solar.h>
      28             : #include <tools/debug.hxx>
      29             : #include <tools/urlobj.hxx>
      30             : 
      31             : /*========================================================================
      32             :  *
      33             :  * INetURLHistory internals.
      34             :  *
      35             :  *======================================================================*/
      36             : #define INETHIST_DEF_FTP_PORT    21
      37             : #define INETHIST_DEF_HTTP_PORT   80
      38             : #define INETHIST_DEF_HTTPS_PORT 443
      39             : 
      40             : #define INETHIST_SIZE_LIMIT   1024
      41             : #define INETHIST_MAGIC_HEAD   0x484D4849UL
      42             : 
      43             : /*
      44             :  * INetURLHistoryHint implementation.
      45             :  */
      46         924 : IMPL_PTRHINT (INetURLHistoryHint, const INetURLObject);
      47             : 
      48             : /*========================================================================
      49             :  *
      50             :  * INetURLHistory_Impl interface.
      51             :  *
      52             :  *======================================================================*/
      53             : class INetURLHistory_Impl
      54             : {
      55             :     /** head_entry.
      56             :     */
      57             :     struct head_entry
      58             :     {
      59             :         /** Representation.
      60             :         */
      61             :         sal_uInt32 m_nMagic;
      62             :         sal_uInt16 m_nNext;
      63             :         sal_uInt16 m_nMBZ;
      64             : 
      65             :         /** Initialization.
      66             :         */
      67          35 :         void initialize (void)
      68             :         {
      69          35 :             m_nMagic = INETHIST_MAGIC_HEAD;
      70          35 :             m_nNext  = 0;
      71          35 :             m_nMBZ   = 0;
      72          35 :         }
      73             :     };
      74             : 
      75             :     /** hash_entry.
      76             :     */
      77             :     struct hash_entry
      78             :     {
      79             :         /** Representation.
      80             :         */
      81             :         sal_uInt32 m_nHash;
      82             :         sal_uInt16 m_nLru;
      83             :         sal_uInt16 m_nMBZ;
      84             : 
      85             :         /** Initialization.
      86             :         */
      87       35840 :         void initialize (sal_uInt16 nLru, sal_uInt32 nHash = 0)
      88             :         {
      89       35840 :             m_nHash = nHash;
      90       35840 :             m_nLru  = nLru;
      91       35840 :             m_nMBZ  = 0;
      92       35840 :         }
      93             : 
      94             :         /** Comparison.
      95             :         */
      96             :         bool operator== (const hash_entry &rOther) const
      97             :         {
      98             :             return (m_nHash == rOther.m_nHash);
      99             :         }
     100             :         bool operator< (const hash_entry &rOther) const
     101             :         {
     102             :             return (m_nHash < rOther.m_nHash);
     103             :         }
     104             : 
     105        5508 :         bool operator== (sal_uInt32 nHash) const
     106             :         {
     107        5508 :             return (m_nHash == nHash);
     108             :         }
     109        5015 :         bool operator< (sal_uInt32 nHash) const
     110             :         {
     111        5015 :             return (m_nHash < nHash);
     112             :         }
     113             :     };
     114             : 
     115             :     /** lru_entry.
     116             :     */
     117             :     struct lru_entry
     118             :     {
     119             :         /** Representation.
     120             :         */
     121             :         sal_uInt32 m_nHash;
     122             :         sal_uInt16 m_nNext;
     123             :         sal_uInt16 m_nPrev;
     124             : 
     125             :         /** Initialization.
     126             :         */
     127       35840 :         void initialize (sal_uInt16 nThis, sal_uInt32 nHash = 0)
     128             :         {
     129       35840 :             m_nHash = nHash;
     130       35840 :             m_nNext = nThis;
     131       35840 :             m_nPrev = nThis;
     132       35840 :         }
     133             :     };
     134             : 
     135             :     /** Representation.
     136             :     */
     137             :     head_entry m_aHead;
     138             :     hash_entry m_pHash[INETHIST_SIZE_LIMIT];
     139             :     lru_entry  m_pList[INETHIST_SIZE_LIMIT];
     140             : 
     141             :     /** Initialization.
     142             :     */
     143             :     void initialize (void);
     144             : 
     145             :     /** capacity.
     146             :     */
     147        2864 :     sal_uInt16 capacity (void) const
     148             :     {
     149        2864 :         return (sal_uInt16)(INETHIST_SIZE_LIMIT);
     150             :     }
     151             : 
     152             :     /** crc32.
     153             :     */
     154         491 :     sal_uInt32 crc32 (OUString const & rData) const
     155             :     {
     156         491 :         return rtl_crc32 (0, rData.getStr(), rData.getLength() * sizeof(sal_Unicode));
     157             :     }
     158             : 
     159             :     /** find.
     160             :     */
     161             :     sal_uInt16 find (sal_uInt32 nHash) const;
     162             : 
     163             :     /** move.
     164             :     */
     165             :     void move (sal_uInt16 nSI, sal_uInt16 nDI);
     166             : 
     167             :     /** backlink.
     168             :     */
     169       36257 :     void backlink (sal_uInt16 nThis, sal_uInt16 nTail)
     170             :     {
     171       36257 :         lru_entry &rThis = m_pList[nThis];
     172       36257 :         lru_entry &rTail = m_pList[nTail];
     173             : 
     174       36257 :         rTail.m_nNext = nThis;
     175       36257 :         rTail.m_nPrev = rThis.m_nPrev;
     176       36257 :         rThis.m_nPrev = nTail;
     177       36257 :         m_pList[rTail.m_nPrev].m_nNext = nTail;
     178       36257 :     }
     179             : 
     180             :     /** unlink.
     181             :     */
     182         452 :     void unlink (sal_uInt16 nThis)
     183             :     {
     184         452 :         lru_entry &rThis = m_pList[nThis];
     185             : 
     186         452 :         m_pList[rThis.m_nPrev].m_nNext = rThis.m_nNext;
     187         452 :         m_pList[rThis.m_nNext].m_nPrev = rThis.m_nPrev;
     188         452 :         rThis.m_nNext = nThis;
     189         452 :         rThis.m_nPrev = nThis;
     190         452 :     }
     191             : 
     192             :     /** Not implemented.
     193             :     */
     194             :     INetURLHistory_Impl (const INetURLHistory_Impl&);
     195             :     INetURLHistory_Impl& operator= (const INetURLHistory_Impl&);
     196             : 
     197             : public:
     198             :     INetURLHistory_Impl (void);
     199             :     ~INetURLHistory_Impl (void);
     200             : 
     201             :     /** putUrl/queryUrl.
     202             :     */
     203             :     void putUrl   (const OUString &rUrl);
     204             :     sal_Bool queryUrl (const OUString &rUrl);
     205             : };
     206             : 
     207             : /*========================================================================
     208             :  *
     209             :  * INetURLHistory_Impl implementation.
     210             :  *
     211             :  *======================================================================*/
     212             : /*
     213             :  * INetURLHistory_Impl.
     214             :  */
     215          35 : INetURLHistory_Impl::INetURLHistory_Impl (void)
     216             : {
     217          35 :     initialize();
     218          35 : }
     219             : 
     220             : /*
     221             :  * ~INetURLHistory_Impl.
     222             :  */
     223          35 : INetURLHistory_Impl::~INetURLHistory_Impl (void)
     224             : {
     225          35 : }
     226             : 
     227             : /*
     228             :  * initialize.
     229             :  */
     230          35 : void INetURLHistory_Impl::initialize (void)
     231             : {
     232          35 :     m_aHead.initialize();
     233             : 
     234          35 :     sal_uInt16 i, n = capacity();
     235       35875 :     for (i = 0; i < n; i++)
     236       35840 :         m_pHash[i].initialize(i);
     237       35875 :     for (i = 0; i < n; i++)
     238       35840 :         m_pList[i].initialize(i);
     239       35840 :     for (i = 1; i < n; i++)
     240       35805 :         backlink (m_aHead.m_nNext, i);
     241          35 : }
     242             : 
     243             : /*
     244             :  * find.
     245             :  */
     246         943 : sal_uInt16 INetURLHistory_Impl::find (sal_uInt32 nHash) const
     247             : {
     248         943 :     sal_uInt16 l = 0;
     249         943 :     sal_uInt16 r = capacity() - 1;
     250         943 :     sal_uInt16 c = capacity();
     251             : 
     252        6449 :     while ((l < r) && (r < c))
     253             :     {
     254        5017 :         sal_uInt16 m = (l + r) / 2;
     255        5017 :         if (m_pHash[m] == nHash)
     256         454 :             return m;
     257             : 
     258        4563 :         if (m_pHash[m] < nHash)
     259        3831 :             l = m + 1;
     260             :         else
     261         732 :             r = m - 1;
     262             :     }
     263         489 :     return l;
     264             : }
     265             : 
     266             : /*
     267             :  * move.
     268             :  */
     269         452 : void INetURLHistory_Impl::move (sal_uInt16 nSI, sal_uInt16 nDI)
     270             : {
     271         452 :     hash_entry e = m_pHash[nSI];
     272         452 :     if (nSI < nDI)
     273             :     {
     274             :         // shift left.
     275             :         memmove (
     276         452 :             &m_pHash[nSI    ],
     277         452 :             &m_pHash[nSI + 1],
     278        1356 :             (nDI - nSI) * sizeof(hash_entry));
     279             :     }
     280         452 :     if (nSI > nDI)
     281             :     {
     282             :         // shift right.
     283             :         memmove (
     284           0 :             &m_pHash[nDI + 1],
     285           0 :             &m_pHash[nDI    ],
     286           0 :             (nSI - nDI) * sizeof(hash_entry));
     287             :     }
     288         452 :     m_pHash[nDI] = e;
     289         452 : }
     290             : 
     291             : /*
     292             :  * putUrl.
     293             :  */
     294         456 : void INetURLHistory_Impl::putUrl (const OUString &rUrl)
     295             : {
     296         456 :     sal_uInt32 h = crc32 (rUrl);
     297         456 :     sal_uInt16 k = find (h);
     298         456 :     if ((k < capacity()) && (m_pHash[k] == h))
     299             :     {
     300             :         // Cache hit.
     301           4 :         sal_uInt16 nMRU = m_pHash[k].m_nLru;
     302           4 :         if (nMRU != m_aHead.m_nNext)
     303             :         {
     304             :             // Update LRU chain.
     305           0 :             unlink (nMRU);
     306           0 :             backlink (m_aHead.m_nNext, nMRU);
     307             : 
     308             :             // Rotate LRU chain.
     309           0 :             m_aHead.m_nNext = m_pList[m_aHead.m_nNext].m_nPrev;
     310             :         }
     311             :     }
     312             :     else
     313             :     {
     314             :         // Cache miss. Obtain least recently used.
     315         452 :         sal_uInt16 nLRU = m_pList[m_aHead.m_nNext].m_nPrev;
     316             : 
     317         452 :         sal_uInt16 nSI = find (m_pList[nLRU].m_nHash);
     318         452 :         if (!(nLRU == m_pHash[nSI].m_nLru))
     319             :         {
     320             :             // Update LRU chain.
     321         452 :             nLRU = m_pHash[nSI].m_nLru;
     322         452 :             unlink (nLRU);
     323         452 :             backlink (m_aHead.m_nNext, nLRU);
     324             :         }
     325             : 
     326             :         // Rotate LRU chain.
     327         452 :         m_aHead.m_nNext = m_pList[m_aHead.m_nNext].m_nPrev;
     328             : 
     329             :         // Check source and destination.
     330         452 :         sal_uInt16 nDI = std::min (k, sal_uInt16(capacity() - 1));
     331         452 :         if (nSI < nDI)
     332             :         {
     333         452 :             if (!(m_pHash[nDI] < h))
     334         212 :                 nDI -= 1;
     335             :         }
     336         452 :         if (nDI < nSI)
     337             :         {
     338           0 :             if (m_pHash[nDI] < h)
     339           0 :                 nDI += 1;
     340             :         }
     341             : 
     342             :         // Assign data.
     343         452 :         m_pList[m_aHead.m_nNext].m_nHash = m_pHash[nSI].m_nHash = h;
     344         452 :         move (nSI, nDI);
     345             :     }
     346         456 : }
     347             : 
     348             : /*
     349             :  * queryUrl.
     350             :  */
     351          35 : sal_Bool INetURLHistory_Impl::queryUrl (const OUString &rUrl)
     352             : {
     353          35 :     sal_uInt32 h = crc32 (rUrl);
     354          35 :     sal_uInt16 k = find (h);
     355          35 :     if ((k < capacity()) && (m_pHash[k] == h))
     356             :     {
     357             :         // Cache hit.
     358           0 :         return sal_True;
     359             :     }
     360             :     else
     361             :     {
     362             :         // Cache miss.
     363          35 :         return sal_False;
     364             :     }
     365             : }
     366             : 
     367             : /*========================================================================
     368             :  *
     369             :  * INetURLHistory::StaticInstance implementation.
     370             :  *
     371             :  *======================================================================*/
     372          35 : INetURLHistory * INetURLHistory::StaticInstance::operator ()()
     373             : {
     374          35 :     static INetURLHistory g_aInstance;
     375          35 :     return &g_aInstance;
     376             : }
     377             : 
     378             : /*========================================================================
     379             :  *
     380             :  * INetURLHistory implementation.
     381             :  *
     382             :  *======================================================================*/
     383             : /*
     384             :  * INetURLHistory.
     385             :  */
     386          35 : INetURLHistory::INetURLHistory() : m_pImpl (new INetURLHistory_Impl())
     387             : {
     388          35 : }
     389             : 
     390             : /*
     391             :  * ~INetURLHistory.
     392             :  */
     393          70 : INetURLHistory::~INetURLHistory()
     394             : {
     395          35 :     DELETEZ (m_pImpl);
     396          35 : }
     397             : 
     398             : /*
     399             :  * GetOrCreate.
     400             :  */
     401         597 : INetURLHistory* INetURLHistory::GetOrCreate()
     402             : {
     403             :     return rtl_Instance<
     404             :         INetURLHistory, StaticInstance,
     405             :         osl::MutexGuard, osl::GetGlobalMutex >::create (
     406         597 :             StaticInstance(), osl::GetGlobalMutex());
     407             : }
     408             : 
     409             : /*
     410             :  * NormalizeUrl_Impl.
     411             :  */
     412         491 : void INetURLHistory::NormalizeUrl_Impl (INetURLObject &rUrl)
     413             : {
     414         491 :     switch (rUrl.GetProtocol())
     415             :     {
     416             :         case INET_PROT_FILE:
     417         456 :             if (!rUrl.IsCaseSensitive())
     418             :             {
     419           0 :                 OUString aPath (rUrl.GetURLPath(INetURLObject::NO_DECODE).toAsciiLowerCase());
     420           0 :                 rUrl.SetURLPath (aPath, INetURLObject::NOT_CANONIC);
     421             :             }
     422         456 :             break;
     423             : 
     424             :         case INET_PROT_FTP:
     425           0 :             if (!rUrl.HasPort())
     426           0 :                 rUrl.SetPort (INETHIST_DEF_FTP_PORT);
     427           0 :             break;
     428             : 
     429             :         case INET_PROT_HTTP:
     430          35 :             if (!rUrl.HasPort())
     431          35 :                 rUrl.SetPort (INETHIST_DEF_HTTP_PORT);
     432          35 :             if (!rUrl.HasURLPath())
     433           0 :                 rUrl.SetURLPath (OString("/"));
     434          35 :             break;
     435             : 
     436             :         case INET_PROT_HTTPS:
     437           0 :             if (!rUrl.HasPort())
     438           0 :                 rUrl.SetPort (INETHIST_DEF_HTTPS_PORT);
     439           0 :             if (!rUrl.HasURLPath())
     440           0 :                 rUrl.SetURLPath (OString("/"));
     441           0 :             break;
     442             : 
     443             :         default:
     444           0 :             break;
     445             :     }
     446         491 : }
     447             : 
     448             : /*
     449             :  * PutUrl_Impl.
     450             :  */
     451         456 : void INetURLHistory::PutUrl_Impl (const INetURLObject &rUrl)
     452             : {
     453             :     DBG_ASSERT (m_pImpl, "PutUrl_Impl(): no Implementation");
     454         456 :     if (m_pImpl)
     455             :     {
     456         456 :         INetURLObject aHistUrl (rUrl);
     457         456 :         NormalizeUrl_Impl (aHistUrl);
     458             : 
     459         456 :         m_pImpl->putUrl (aHistUrl.GetMainURL(INetURLObject::NO_DECODE));
     460         456 :         Broadcast (INetURLHistoryHint (&rUrl));
     461             : 
     462         456 :         if (aHistUrl.HasMark())
     463             :         {
     464             :             aHistUrl.SetURL (aHistUrl.GetURLNoMark(INetURLObject::NO_DECODE),
     465           0 :                              INetURLObject::NOT_CANONIC);
     466             : 
     467           0 :             m_pImpl->putUrl (aHistUrl.GetMainURL(INetURLObject::NO_DECODE));
     468           0 :             Broadcast (INetURLHistoryHint (&aHistUrl));
     469         456 :         }
     470             :     }
     471         456 : }
     472             : 
     473             : /*
     474             :  * QueryUrl_Impl.
     475             :  */
     476          35 : sal_Bool INetURLHistory::QueryUrl_Impl (const INetURLObject &rUrl)
     477             : {
     478             :     DBG_ASSERT (m_pImpl, "QueryUrl_Impl(): no Implementation");
     479          35 :     if (m_pImpl)
     480             :     {
     481          35 :         INetURLObject aHistUrl (rUrl);
     482          35 :         NormalizeUrl_Impl (aHistUrl);
     483             : 
     484          35 :         return m_pImpl->queryUrl (aHistUrl.GetMainURL(INetURLObject::NO_DECODE));
     485             :     }
     486           0 :     return sal_False;
     487             : }
     488             : 
     489             : 
     490             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10