LCOV - code coverage report
Current view: top level - parser/htmlparser - nsHTMLTags.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 96 102 94.1 %
Date: 2017-07-14 16:53:18 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "nsHTMLTags.h"
       7             : #include "nsCRT.h"
       8             : #include "nsReadableUtils.h"
       9             : #include "nsString.h"
      10             : #include "nsStaticAtom.h"
      11             : #include "nsUnicharUtils.h"
      12             : #include "mozilla/HashFunctions.h"
      13             : #include <algorithm>
      14             : 
      15             : using namespace mozilla;
      16             : 
      17             : // static array of unicode tag names
      18             : #define HTML_TAG(_tag, _classname, _interfacename) (u"" #_tag),
      19             : #define HTML_OTHER(_tag)
      20             : const char16_t* const nsHTMLTags::sTagUnicodeTable[] = {
      21             : #include "nsHTMLTagList.h"
      22             : };
      23             : #undef HTML_TAG
      24             : #undef HTML_OTHER
      25             : 
      26             : // static array of tag atoms
      27             : nsIAtom* nsHTMLTags::sTagAtomTable[eHTMLTag_userdefined - 1];
      28             : 
      29             : int32_t nsHTMLTags::gTableRefCount;
      30             : PLHashTable* nsHTMLTags::gTagTable;
      31             : PLHashTable* nsHTMLTags::gTagAtomTable;
      32             : 
      33             : 
      34             : // char16_t* -> id hash
      35             : static PLHashNumber
      36        1100 : HTMLTagsHashCodeUCPtr(const void *key)
      37             : {
      38        1100 :   return HashString(static_cast<const char16_t*>(key));
      39             : }
      40             : 
      41             : static int
      42         822 : HTMLTagsKeyCompareUCPtr(const void *key1, const void *key2)
      43             : {
      44         822 :   const char16_t *str1 = (const char16_t *)key1;
      45         822 :   const char16_t *str2 = (const char16_t *)key2;
      46             : 
      47         822 :   return nsCRT::strcmp(str1, str2) == 0;
      48             : }
      49             : 
      50             : // nsIAtom* -> id hash
      51             : static PLHashNumber
      52         626 : HTMLTagsHashCodeAtom(const void *key)
      53             : {
      54         626 :   return NS_PTR_TO_INT32(key) >> 2;
      55             : }
      56             : 
      57             : #define NS_HTMLTAG_NAME_MAX_LENGTH 10
      58             : 
      59             : // static
      60             : void
      61           3 : nsHTMLTags::RegisterAtoms(void)
      62             : {
      63             : #define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
      64             : #define HTML_OTHER(_tag)
      65             : #include "nsHTMLTagList.h"
      66             : #undef HTML_TAG
      67             : #undef HTML_OTHER
      68             : 
      69             : // static array of tag StaticAtom structs
      70             : #define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
      71             : #define HTML_OTHER(_tag)
      72             :   static const nsStaticAtom sTagAtoms_info[] = {
      73             : #include "nsHTMLTagList.h"
      74             :   };
      75             : #undef HTML_TAG
      76             : #undef HTML_OTHER
      77             : 
      78             :   // Fill in our static atom pointers
      79           3 :   NS_RegisterStaticAtoms(sTagAtoms_info);
      80             : 
      81             : 
      82             : #if defined(DEBUG)
      83             :   {
      84             :     // let's verify that all names in the the table are lowercase...
      85         414 :     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
      86         822 :       nsAutoString temp1((char16_t*)sTagAtoms_info[i].mStringBuffer->Data());
      87         822 :       nsAutoString temp2((char16_t*)sTagAtoms_info[i].mStringBuffer->Data());
      88         411 :       ToLowerCase(temp1);
      89         411 :       NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
      90             :     }
      91             : 
      92             :     // let's verify that all names in the unicode strings above are
      93             :     // correct.
      94         414 :     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
      95         822 :       nsAutoString temp1(sTagUnicodeTable[i]);
      96         822 :       nsAutoString temp2((char16_t*)sTagAtoms_info[i].mStringBuffer->Data());
      97         411 :       NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!");
      98             :     }
      99             : 
     100             :     // let's verify that NS_HTMLTAG_NAME_MAX_LENGTH is correct
     101           3 :     uint32_t maxTagNameLength = 0;
     102         414 :     for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
     103         411 :       uint32_t len = NS_strlen(sTagUnicodeTable[i]);
     104         411 :       maxTagNameLength = std::max(len, maxTagNameLength);
     105             :     }
     106           3 :     NS_ASSERTION(maxTagNameLength == NS_HTMLTAG_NAME_MAX_LENGTH,
     107             :                  "NS_HTMLTAG_NAME_MAX_LENGTH not set correctly!");
     108             :   }
     109             : #endif
     110           3 : }
     111             : 
     112             : // static
     113             : nsresult
     114           4 : nsHTMLTags::AddRefTable(void)
     115             : {
     116           4 :   if (gTableRefCount++ == 0) {
     117           2 :     NS_ASSERTION(!gTagTable && !gTagAtomTable, "pre existing hash!");
     118             : 
     119           2 :     gTagTable = PL_NewHashTable(64, HTMLTagsHashCodeUCPtr,
     120             :                                 HTMLTagsKeyCompareUCPtr, PL_CompareValues,
     121             :                                 nullptr, nullptr);
     122           2 :     NS_ENSURE_TRUE(gTagTable, NS_ERROR_OUT_OF_MEMORY);
     123             : 
     124           2 :     gTagAtomTable = PL_NewHashTable(64, HTMLTagsHashCodeAtom,
     125             :                                     PL_CompareValues, PL_CompareValues,
     126             :                                     nullptr, nullptr);
     127           2 :     NS_ENSURE_TRUE(gTagAtomTable, NS_ERROR_OUT_OF_MEMORY);
     128             : 
     129             :     // Fill in gTagTable with the above static char16_t strings as
     130             :     // keys and the value of the corresponding enum as the value in
     131             :     // the table.
     132             : 
     133             :     int32_t i;
     134         276 :     for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
     135         274 :       PL_HashTableAdd(gTagTable, sTagUnicodeTable[i],
     136         548 :                       NS_INT32_TO_PTR(i + 1));
     137             : 
     138         274 :       PL_HashTableAdd(gTagAtomTable, sTagAtomTable[i],
     139         548 :                       NS_INT32_TO_PTR(i + 1));
     140             :     }
     141             :   }
     142             : 
     143           4 :   return NS_OK;
     144             : }
     145             : 
     146             : // static
     147             : void
     148           2 : nsHTMLTags::ReleaseTable(void)
     149             : {
     150           2 :   if (0 == --gTableRefCount) {
     151           0 :     if (gTagTable) {
     152             :       // Nothing to delete/free in this table, just destroy the table.
     153             : 
     154           0 :       PL_HashTableDestroy(gTagTable);
     155           0 :       PL_HashTableDestroy(gTagAtomTable);
     156           0 :       gTagTable = nullptr;
     157           0 :       gTagAtomTable = nullptr;
     158             :     }
     159             :   }
     160           2 : }
     161             : 
     162             : // static
     163             : nsHTMLTag
     164         552 : nsHTMLTags::LookupTag(const nsAString& aTagName)
     165             : {
     166         552 :   uint32_t length = aTagName.Length();
     167             : 
     168         552 :   if (length > NS_HTMLTAG_NAME_MAX_LENGTH) {
     169           0 :     return eHTMLTag_userdefined;
     170             :   }
     171             : 
     172             :   char16_t buf[NS_HTMLTAG_NAME_MAX_LENGTH + 1];
     173             : 
     174         552 :   nsAString::const_iterator iter;
     175         552 :   uint32_t i = 0;
     176             :   char16_t c;
     177             : 
     178         552 :   aTagName.BeginReading(iter);
     179             : 
     180             :   // Fast lowercasing-while-copying of ASCII characters into a
     181             :   // char16_t buffer
     182             : 
     183        5632 :   while (i < length) {
     184        2540 :     c = *iter;
     185             : 
     186        2540 :     if (c <= 'Z' && c >= 'A') {
     187        1252 :       c |= 0x20; // Lowercase the ASCII character.
     188             :     }
     189             : 
     190        2540 :     buf[i] = c; // Copy ASCII character.
     191             : 
     192        2540 :     ++i;
     193        2540 :     ++iter;
     194             :   }
     195             : 
     196         552 :   buf[i] = 0;
     197             : 
     198         552 :   return CaseSensitiveLookupTag(buf);
     199             : }
     200             : 
     201             : #ifdef DEBUG
     202             : void
     203           2 : nsHTMLTags::TestTagTable()
     204             : {
     205             :      const char16_t *tag;
     206             :      nsHTMLTag id;
     207           4 :      nsCOMPtr<nsIAtom> atom;
     208             : 
     209           2 :      nsHTMLTags::AddRefTable();
     210             :      // Make sure we can find everything we are supposed to
     211         276 :      for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
     212         274 :        tag = sTagUnicodeTable[i];
     213         274 :        id = LookupTag(nsDependentString(tag));
     214         274 :        NS_ASSERTION(id != eHTMLTag_userdefined, "can't find tag id");
     215         274 :        const char16_t* check = GetStringValue(id);
     216         274 :        NS_ASSERTION(0 == nsCRT::strcmp(check, tag), "can't map id back to tag");
     217             : 
     218         548 :        nsAutoString uname(tag);
     219         274 :        ToUpperCase(uname);
     220         274 :        NS_ASSERTION(id == LookupTag(uname), "wrong id");
     221             : 
     222         274 :        NS_ASSERTION(id == CaseSensitiveLookupTag(tag), "wrong id");
     223             : 
     224         274 :        atom = NS_Atomize(tag);
     225         274 :        NS_ASSERTION(id == CaseSensitiveLookupTag(atom), "wrong id");
     226         274 :        NS_ASSERTION(atom == GetAtom(id), "can't map id back to atom");
     227             :      }
     228             : 
     229             :      // Make sure we don't find things that aren't there
     230           2 :      id = LookupTag(NS_LITERAL_STRING("@"));
     231           2 :      NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
     232           2 :      id = LookupTag(NS_LITERAL_STRING("zzzzz"));
     233           2 :      NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
     234             : 
     235           2 :      atom = NS_Atomize("@");
     236           2 :      id = CaseSensitiveLookupTag(atom);
     237           2 :      NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
     238           2 :      atom = NS_Atomize("zzzzz");
     239           2 :      id = CaseSensitiveLookupTag(atom);
     240           2 :      NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
     241             : 
     242           2 :      tag = GetStringValue((nsHTMLTag) 0);
     243           2 :      NS_ASSERTION(!tag, "found enum 0");
     244           2 :      tag = GetStringValue((nsHTMLTag) -1);
     245           2 :      NS_ASSERTION(!tag, "found enum -1");
     246           2 :      tag = GetStringValue((nsHTMLTag) (NS_HTML_TAG_MAX + 1));
     247           2 :      NS_ASSERTION(!tag, "found past max enum");
     248             : 
     249           2 :      atom = GetAtom((nsHTMLTag) 0);
     250           2 :      NS_ASSERTION(!atom, "found enum 0");
     251           2 :      atom = GetAtom((nsHTMLTag) -1);
     252           2 :      NS_ASSERTION(!atom, "found enum -1");
     253           2 :      atom = GetAtom((nsHTMLTag) (NS_HTML_TAG_MAX + 1));
     254           2 :      NS_ASSERTION(!atom, "found past max enum");
     255             : 
     256           2 :      ReleaseTable();
     257           2 : }
     258             : 
     259             : #endif // DEBUG

Generated by: LCOV version 1.13