parser/htmlparser/src/nsHTMLEntities.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/ArrayUtils.h"
     8 #include "nsHTMLEntities.h"
    12 #include "nsString.h"
    13 #include "nsCRT.h"
    14 #include "pldhash.h"
    16 using namespace mozilla;
    18 struct EntityNode {
    19   const char* mStr; // never owns buffer
    20   int32_t       mUnicode;
    21 };
    23 struct EntityNodeEntry : public PLDHashEntryHdr
    24 {
    25   const EntityNode* node;
    26 }; 
    28 static bool
    29   matchNodeString(PLDHashTable*, const PLDHashEntryHdr* aHdr,
    30                   const void* key)
    31 {
    32   const EntityNodeEntry* entry = static_cast<const EntityNodeEntry*>(aHdr);
    33   const char* str = static_cast<const char*>(key);
    34   return (nsCRT::strcmp(entry->node->mStr, str) == 0);
    35 }
    37 static bool
    38   matchNodeUnicode(PLDHashTable*, const PLDHashEntryHdr* aHdr,
    39                    const void* key)
    40 {
    41   const EntityNodeEntry* entry = static_cast<const EntityNodeEntry*>(aHdr);
    42   const int32_t ucode = NS_PTR_TO_INT32(key);
    43   return (entry->node->mUnicode == ucode);
    44 }
    46 static PLDHashNumber
    47   hashUnicodeValue(PLDHashTable*, const void* key)
    48 {
    49   // key is actually the unicode value
    50   return PLDHashNumber(NS_PTR_TO_INT32(key));
    51   }
    54 static const PLDHashTableOps EntityToUnicodeOps = {
    55   PL_DHashAllocTable,
    56   PL_DHashFreeTable,
    57   PL_DHashStringKey,
    58   matchNodeString,
    59   PL_DHashMoveEntryStub,
    60   PL_DHashClearEntryStub,
    61   PL_DHashFinalizeStub,
    62   nullptr,
    63 }; 
    65 static const PLDHashTableOps UnicodeToEntityOps = {
    66   PL_DHashAllocTable,
    67   PL_DHashFreeTable,
    68   hashUnicodeValue,
    69   matchNodeUnicode,
    70   PL_DHashMoveEntryStub,
    71   PL_DHashClearEntryStub,
    72   PL_DHashFinalizeStub,
    73   nullptr,
    74 };
    76 static PLDHashTable gEntityToUnicode = { 0 };
    77 static PLDHashTable gUnicodeToEntity = { 0 };
    78 static nsrefcnt gTableRefCnt = 0;
    80 #define HTML_ENTITY(_name, _value) { #_name, _value },
    81 static const EntityNode gEntityArray[] = {
    82 #include "nsHTMLEntityList.h"
    83 };
    84 #undef HTML_ENTITY
    86 #define NS_HTML_ENTITY_COUNT ((int32_t)ArrayLength(gEntityArray))
    88 nsresult
    89 nsHTMLEntities::AddRefTable(void) 
    90 {
    91   if (!gTableRefCnt) {
    92     if (!PL_DHashTableInit(&gEntityToUnicode, &EntityToUnicodeOps,
    93                            nullptr, sizeof(EntityNodeEntry),
    94                            uint32_t(NS_HTML_ENTITY_COUNT / 0.75),
    95                            fallible_t())) {
    96       gEntityToUnicode.ops = nullptr;
    97       return NS_ERROR_OUT_OF_MEMORY;
    98     }
    99     if (!PL_DHashTableInit(&gUnicodeToEntity, &UnicodeToEntityOps,
   100                            nullptr, sizeof(EntityNodeEntry),
   101                            uint32_t(NS_HTML_ENTITY_COUNT / 0.75),
   102                            fallible_t())) {
   103       PL_DHashTableFinish(&gEntityToUnicode);
   104       gEntityToUnicode.ops = gUnicodeToEntity.ops = nullptr;
   105       return NS_ERROR_OUT_OF_MEMORY;
   106     }
   107     for (const EntityNode *node = gEntityArray,
   108                  *node_end = ArrayEnd(gEntityArray);
   109          node < node_end; ++node) {
   111       // add to Entity->Unicode table
   112       EntityNodeEntry* entry =
   113         static_cast<EntityNodeEntry*>
   114                    (PL_DHashTableOperate(&gEntityToUnicode,
   115                                             node->mStr,
   116                                             PL_DHASH_ADD));
   117       NS_ASSERTION(entry, "Error adding an entry");
   118       // Prefer earlier entries when we have duplication.
   119       if (!entry->node)
   120         entry->node = node;
   122       // add to Unicode->Entity table
   123       entry = static_cast<EntityNodeEntry*>
   124                          (PL_DHashTableOperate(&gUnicodeToEntity,
   125                                                   NS_INT32_TO_PTR(node->mUnicode),
   126                                                   PL_DHASH_ADD));
   127       NS_ASSERTION(entry, "Error adding an entry");
   128       // Prefer earlier entries when we have duplication.
   129       if (!entry->node)
   130         entry->node = node;
   131     }
   132 #ifdef DEBUG
   133     PL_DHashMarkTableImmutable(&gUnicodeToEntity);
   134     PL_DHashMarkTableImmutable(&gEntityToUnicode);
   135 #endif
   136   }
   137   ++gTableRefCnt;
   138   return NS_OK;
   139 }
   141 void
   142 nsHTMLEntities::ReleaseTable(void) 
   143 {
   144   if (--gTableRefCnt != 0)
   145     return;
   147   if (gEntityToUnicode.ops) {
   148     PL_DHashTableFinish(&gEntityToUnicode);
   149     gEntityToUnicode.ops = nullptr;
   150   }
   151   if (gUnicodeToEntity.ops) {
   152     PL_DHashTableFinish(&gUnicodeToEntity);
   153     gUnicodeToEntity.ops = nullptr;
   154   }
   156 }
   158 int32_t 
   159 nsHTMLEntities::EntityToUnicode(const nsCString& aEntity)
   160 {
   161   NS_ASSERTION(gEntityToUnicode.ops, "no lookup table, needs addref");
   162   if (!gEntityToUnicode.ops)
   163     return -1;
   165     //this little piece of code exists because entities may or may not have the terminating ';'.
   166     //if we see it, strip if off for this test...
   168     if(';'==aEntity.Last()) {
   169       nsAutoCString temp(aEntity);
   170       temp.Truncate(aEntity.Length()-1);
   171       return EntityToUnicode(temp);
   172     }
   174   EntityNodeEntry* entry = 
   175     static_cast<EntityNodeEntry*>
   176                (PL_DHashTableOperate(&gEntityToUnicode, aEntity.get(), PL_DHASH_LOOKUP));
   178   if (!entry || PL_DHASH_ENTRY_IS_FREE(entry))
   179   return -1;
   181   return entry->node->mUnicode;
   182 }
   185 int32_t 
   186 nsHTMLEntities::EntityToUnicode(const nsAString& aEntity) {
   187   nsAutoCString theEntity; theEntity.AssignWithConversion(aEntity);
   188   if(';'==theEntity.Last()) {
   189     theEntity.Truncate(theEntity.Length()-1);
   190   }
   192   return EntityToUnicode(theEntity);
   193 }
   196 const char*
   197 nsHTMLEntities::UnicodeToEntity(int32_t aUnicode)
   198 {
   199   NS_ASSERTION(gUnicodeToEntity.ops, "no lookup table, needs addref");
   200   EntityNodeEntry* entry =
   201     static_cast<EntityNodeEntry*>
   202                (PL_DHashTableOperate(&gUnicodeToEntity, NS_INT32_TO_PTR(aUnicode), PL_DHASH_LOOKUP));
   204   if (!entry || PL_DHASH_ENTRY_IS_FREE(entry))
   205   return nullptr;
   207   return entry->node->mStr;
   208 }
   210 #ifdef DEBUG
   211 #include <stdio.h>
   213 class nsTestEntityTable {
   214 public:
   215    nsTestEntityTable() {
   216      int32_t value;
   217      nsHTMLEntities::AddRefTable();
   219      // Make sure we can find everything we are supposed to
   220      for (int i = 0; i < NS_HTML_ENTITY_COUNT; ++i) {
   221        nsAutoString entity; entity.AssignWithConversion(gEntityArray[i].mStr);
   223        value = nsHTMLEntities::EntityToUnicode(entity);
   224        NS_ASSERTION(value != -1, "can't find entity");
   225        NS_ASSERTION(value == gEntityArray[i].mUnicode, "bad unicode value");
   227        entity.AssignWithConversion(nsHTMLEntities::UnicodeToEntity(value));
   228        NS_ASSERTION(entity.EqualsASCII(gEntityArray[i].mStr), "bad entity name");
   229      }
   231      // Make sure we don't find things that aren't there
   232      value = nsHTMLEntities::EntityToUnicode(nsAutoCString("@"));
   233      NS_ASSERTION(value == -1, "found @");
   234      value = nsHTMLEntities::EntityToUnicode(nsAutoCString("zzzzz"));
   235      NS_ASSERTION(value == -1, "found zzzzz");
   236      nsHTMLEntities::ReleaseTable();
   237    }
   238 };
   239 //nsTestEntityTable validateEntityTable;
   240 #endif

mercurial