LCOV - code coverage report
Current view: directory - parser/htmlparser/src - nsHTMLEntities.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 67 50 74.6 %
Date: 2012-06-02 Functions: 8 7 87.5 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "mozilla/Util.h"
      39                 : 
      40                 : #include "nsHTMLEntities.h"
      41                 : 
      42                 : 
      43                 : 
      44                 : #include "nsString.h"
      45                 : #include "nsCRT.h"
      46                 : #include "prtypes.h"
      47                 : #include "pldhash.h"
      48                 : 
      49                 : using namespace mozilla;
      50                 : 
      51                 : struct EntityNode {
      52                 :   const char* mStr; // never owns buffer
      53                 :   PRInt32       mUnicode;
      54                 : };
      55                 : 
      56                 : struct EntityNodeEntry : public PLDHashEntryHdr
      57                 : {
      58                 :   const EntityNode* node;
      59                 : }; 
      60                 : 
      61                 : static bool
      62              11 :   matchNodeString(PLDHashTable*, const PLDHashEntryHdr* aHdr,
      63                 :                   const void* key)
      64                 : {
      65              11 :   const EntityNodeEntry* entry = static_cast<const EntityNodeEntry*>(aHdr);
      66              11 :   const char* str = static_cast<const char*>(key);
      67              11 :   return (nsCRT::strcmp(entry->node->mStr, str) == 0);
      68                 : }
      69                 : 
      70                 : static bool
      71            1578 :   matchNodeUnicode(PLDHashTable*, const PLDHashEntryHdr* aHdr,
      72                 :                    const void* key)
      73                 : {
      74            1578 :   const EntityNodeEntry* entry = static_cast<const EntityNodeEntry*>(aHdr);
      75            1578 :   const PRInt32 ucode = NS_PTR_TO_INT32(key);
      76            1578 :   return (entry->node->mUnicode == ucode);
      77                 : }
      78                 : 
      79                 : static PLDHashNumber
      80           68117 :   hashUnicodeValue(PLDHashTable*, const void* key)
      81                 : {
      82                 :   // key is actually the unicode value
      83           68117 :   return PLDHashNumber(NS_PTR_TO_INT32(key));
      84                 :   }
      85                 : 
      86                 : 
      87                 : static const PLDHashTableOps EntityToUnicodeOps = {
      88                 :   PL_DHashAllocTable,
      89                 :   PL_DHashFreeTable,
      90                 :   PL_DHashStringKey,
      91                 :   matchNodeString,
      92                 :   PL_DHashMoveEntryStub,
      93                 :   PL_DHashClearEntryStub,
      94                 :   PL_DHashFinalizeStub,
      95                 :   nsnull,
      96                 : }; 
      97                 : 
      98                 : static const PLDHashTableOps UnicodeToEntityOps = {
      99                 :   PL_DHashAllocTable,
     100                 :   PL_DHashFreeTable,
     101                 :   hashUnicodeValue,
     102                 :   matchNodeUnicode,
     103                 :   PL_DHashMoveEntryStub,
     104                 :   PL_DHashClearEntryStub,
     105                 :   PL_DHashFinalizeStub,
     106                 :   nsnull,
     107                 : };
     108                 : 
     109                 : static PLDHashTable gEntityToUnicode = { 0 };
     110                 : static PLDHashTable gUnicodeToEntity = { 0 };
     111                 : static nsrefcnt gTableRefCnt = 0;
     112                 : 
     113                 : #define HTML_ENTITY(_name, _value) { #_name, _value },
     114                 : static const EntityNode gEntityArray[] = {
     115                 : #include "nsHTMLEntityList.h"
     116                 : };
     117                 : #undef HTML_ENTITY
     118                 : 
     119                 : #define NS_HTML_ENTITY_COUNT ((PRInt32)ArrayLength(gEntityArray))
     120                 : 
     121                 : nsresult
     122             263 : nsHTMLEntities::AddRefTable(void) 
     123                 : {
     124             263 :   if (!gTableRefCnt) {
     125             263 :     if (!PL_DHashTableInit(&gEntityToUnicode, &EntityToUnicodeOps,
     126                 :                            nsnull, sizeof(EntityNodeEntry),
     127             263 :                            PRUint32(NS_HTML_ENTITY_COUNT / 0.75))) {
     128               0 :       gEntityToUnicode.ops = nsnull;
     129               0 :       return NS_ERROR_OUT_OF_MEMORY;
     130                 :     }
     131             263 :     if (!PL_DHashTableInit(&gUnicodeToEntity, &UnicodeToEntityOps,
     132                 :                            nsnull, sizeof(EntityNodeEntry),
     133             263 :                            PRUint32(NS_HTML_ENTITY_COUNT / 0.75))) {
     134               0 :       PL_DHashTableFinish(&gEntityToUnicode);
     135               0 :       gEntityToUnicode.ops = gUnicodeToEntity.ops = nsnull;
     136               0 :       return NS_ERROR_OUT_OF_MEMORY;
     137                 :     }
     138           68643 :     for (const EntityNode *node = gEntityArray,
     139             263 :                  *node_end = ArrayEnd(gEntityArray);
     140                 :          node < node_end; ++node) {
     141                 : 
     142                 :       // add to Entity->Unicode table
     143                 :       EntityNodeEntry* entry =
     144                 :         static_cast<EntityNodeEntry*>
     145                 :                    (PL_DHashTableOperate(&gEntityToUnicode,
     146                 :                                             node->mStr,
     147           68117 :                                             PL_DHASH_ADD));
     148           68117 :       NS_ASSERTION(entry, "Error adding an entry");
     149                 :       // Prefer earlier entries when we have duplication.
     150           68117 :       if (!entry->node)
     151           68117 :         entry->node = node;
     152                 : 
     153                 :       // add to Unicode->Entity table
     154                 :       entry = static_cast<EntityNodeEntry*>
     155                 :                          (PL_DHashTableOperate(&gUnicodeToEntity,
     156                 :                                                   NS_INT32_TO_PTR(node->mUnicode),
     157           68117 :                                                   PL_DHASH_ADD));
     158           68117 :       NS_ASSERTION(entry, "Error adding an entry");
     159                 :       // Prefer earlier entries when we have duplication.
     160           68117 :       if (!entry->node)
     161           66539 :         entry->node = node;
     162                 :     }
     163                 : #ifdef DEBUG
     164             263 :     PL_DHashMarkTableImmutable(&gUnicodeToEntity);
     165             263 :     PL_DHashMarkTableImmutable(&gEntityToUnicode);
     166                 : #endif
     167                 :   }
     168             263 :   ++gTableRefCnt;
     169             263 :   return NS_OK;
     170                 : }
     171                 : 
     172                 : void
     173             263 : nsHTMLEntities::ReleaseTable(void) 
     174                 : {
     175             263 :   if (--gTableRefCnt != 0)
     176               0 :     return;
     177                 : 
     178             263 :   if (gEntityToUnicode.ops) {
     179             263 :     PL_DHashTableFinish(&gEntityToUnicode);
     180             263 :     gEntityToUnicode.ops = nsnull;
     181                 :   }
     182             263 :   if (gUnicodeToEntity.ops) {
     183             263 :     PL_DHashTableFinish(&gUnicodeToEntity);
     184             263 :     gUnicodeToEntity.ops = nsnull;
     185                 :   }
     186                 : 
     187                 : }
     188                 : 
     189                 : PRInt32 
     190              11 : nsHTMLEntities::EntityToUnicode(const nsCString& aEntity)
     191                 : {
     192              11 :   NS_ASSERTION(gEntityToUnicode.ops, "no lookup table, needs addref");
     193              11 :   if (!gEntityToUnicode.ops)
     194               0 :     return -1;
     195                 : 
     196                 :     //this little piece of code exists because entities may or may not have the terminating ';'.
     197                 :     //if we see it, strip if off for this test...
     198                 : 
     199              11 :     if(';'==aEntity.Last()) {
     200               0 :       nsCAutoString temp(aEntity);
     201               0 :       temp.Truncate(aEntity.Length()-1);
     202               0 :       return EntityToUnicode(temp);
     203                 :     }
     204                 :       
     205                 :   EntityNodeEntry* entry = 
     206                 :     static_cast<EntityNodeEntry*>
     207              11 :                (PL_DHashTableOperate(&gEntityToUnicode, aEntity.get(), PL_DHASH_LOOKUP));
     208                 : 
     209              11 :   if (!entry || PL_DHASH_ENTRY_IS_FREE(entry))
     210               0 :   return -1;
     211                 :         
     212              11 :   return entry->node->mUnicode;
     213                 : }
     214                 : 
     215                 : 
     216                 : PRInt32 
     217              11 : nsHTMLEntities::EntityToUnicode(const nsAString& aEntity) {
     218              22 :   nsCAutoString theEntity; theEntity.AssignWithConversion(aEntity);
     219              11 :   if(';'==theEntity.Last()) {
     220              11 :     theEntity.Truncate(theEntity.Length()-1);
     221                 :   }
     222                 : 
     223              11 :   return EntityToUnicode(theEntity);
     224                 : }
     225                 : 
     226                 : 
     227                 : const char*
     228               0 : nsHTMLEntities::UnicodeToEntity(PRInt32 aUnicode)
     229                 : {
     230               0 :   NS_ASSERTION(gUnicodeToEntity.ops, "no lookup table, needs addref");
     231                 :   EntityNodeEntry* entry =
     232                 :     static_cast<EntityNodeEntry*>
     233               0 :                (PL_DHashTableOperate(&gUnicodeToEntity, NS_INT32_TO_PTR(aUnicode), PL_DHASH_LOOKUP));
     234                 :                    
     235               0 :   if (!entry || PL_DHASH_ENTRY_IS_FREE(entry))
     236               0 :   return nsnull;
     237                 :     
     238               0 :   return entry->node->mStr;
     239                 : }
     240                 : 
     241                 : #ifdef NS_DEBUG
     242                 : #include <stdio.h>
     243                 : 
     244                 : class nsTestEntityTable {
     245                 : public:
     246                 :    nsTestEntityTable() {
     247                 :      PRInt32 value;
     248                 :      nsHTMLEntities::AddRefTable();
     249                 : 
     250                 :      // Make sure we can find everything we are supposed to
     251                 :      for (int i = 0; i < NS_HTML_ENTITY_COUNT; ++i) {
     252                 :        nsAutoString entity; entity.AssignWithConversion(gEntityArray[i].mStr);
     253                 : 
     254                 :        value = nsHTMLEntities::EntityToUnicode(entity);
     255                 :        NS_ASSERTION(value != -1, "can't find entity");
     256                 :        NS_ASSERTION(value == gEntityArray[i].mUnicode, "bad unicode value");
     257                 : 
     258                 :        entity.AssignWithConversion(nsHTMLEntities::UnicodeToEntity(value));
     259                 :        NS_ASSERTION(entity.EqualsASCII(gEntityArray[i].mStr), "bad entity name");
     260                 :      }
     261                 : 
     262                 :      // Make sure we don't find things that aren't there
     263                 :      value = nsHTMLEntities::EntityToUnicode(nsCAutoString("@"));
     264                 :      NS_ASSERTION(value == -1, "found @");
     265                 :      value = nsHTMLEntities::EntityToUnicode(nsCAutoString("zzzzz"));
     266                 :      NS_ASSERTION(value == -1, "found zzzzz");
     267                 :      nsHTMLEntities::ReleaseTable();
     268                 :    }
     269                 : };
     270                 : //nsTestEntityTable validateEntityTable;
     271                 : #endif
     272                 : 

Generated by: LCOV version 1.7