tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsHTMLTags.cpp (4796B)


      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 "nsElementTable.h"
      9 #include "nsReadableUtils.h"
     10 #include "nsString.h"
     11 #include "nsUnicharUtils.h"
     12 #include <algorithm>
     13 
     14 using namespace mozilla;
     15 
     16 // static array of unicode tag names
     17 #define HTML_TAG(_tag, _classname, _interfacename) (u"" #_tag),
     18 #define HTML_OTHER(_tag)
     19 const char16_t* const nsHTMLTags::sTagNames[] = {
     20 #include "nsHTMLTagList.h"
     21 };
     22 #undef HTML_TAG
     23 #undef HTML_OTHER
     24 
     25 int32_t nsHTMLTags::gTableRefCount;
     26 nsHTMLTags::TagStringHash* nsHTMLTags::gTagTable;
     27 nsHTMLTags::TagAtomHash* nsHTMLTags::gTagAtomTable;
     28 
     29 #define NS_HTMLTAG_NAME_MAX_LENGTH 10
     30 
     31 // static
     32 nsresult nsHTMLTags::AddRefTable(void) {
     33  if (gTableRefCount++ == 0) {
     34    NS_ASSERTION(!gTagTable && !gTagAtomTable, "pre existing hash!");
     35 
     36    gTagTable = new TagStringHash(64);
     37    gTagAtomTable = new TagAtomHash(64);
     38 
     39    // Fill in gTagTable with the above static char16_t strings as
     40    // keys and the value of the corresponding enum as the value in
     41    // the table.
     42 
     43    for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
     44      const char16_t* tagName = sTagNames[i];
     45      const nsHTMLTag tagValue = static_cast<nsHTMLTag>(i + 1);
     46 
     47      // We use AssignLiteral here to avoid a string copy. This is okay
     48      // because this is truly static data.
     49      nsString tmp;
     50      tmp.AssignLiteral(tagName, nsString::char_traits::length(tagName));
     51      gTagTable->InsertOrUpdate(tmp, tagValue);
     52 
     53      // All the HTML tag names are static atoms within nsGkAtoms, and they are
     54      // registered before this code is reached.
     55      nsStaticAtom* atom = NS_GetStaticAtom(tmp);
     56      MOZ_ASSERT(atom);
     57      gTagAtomTable->InsertOrUpdate(atom, tagValue);
     58    }
     59 
     60 #ifdef DEBUG
     61    // Check all tagNames are lowercase, and that NS_HTMLTAG_NAME_MAX_LENGTH is
     62    // correct.
     63    uint32_t maxTagNameLength = 0;
     64    for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
     65      const char16_t* tagName = sTagNames[i];
     66 
     67      nsAutoString lowerTagName(tagName);
     68      ToLowerCase(lowerTagName);
     69      MOZ_ASSERT(lowerTagName.Equals(tagName));
     70 
     71      maxTagNameLength = std::max(NS_strlen(tagName), maxTagNameLength);
     72    }
     73 
     74    MOZ_ASSERT(maxTagNameLength == NS_HTMLTAG_NAME_MAX_LENGTH);
     75 
     76    CheckElementTable();
     77    TestTagTable();
     78 #endif
     79  }
     80 
     81  return NS_OK;
     82 }
     83 
     84 // static
     85 void nsHTMLTags::ReleaseTable(void) {
     86  if (0 == --gTableRefCount) {
     87    delete gTagTable;
     88    delete gTagAtomTable;
     89    gTagTable = nullptr;
     90    gTagAtomTable = nullptr;
     91  }
     92 }
     93 
     94 // static
     95 nsHTMLTag nsHTMLTags::StringTagToId(const nsAString& aTagName) {
     96  uint32_t length = aTagName.Length();
     97 
     98  if (length > NS_HTMLTAG_NAME_MAX_LENGTH) {
     99    return eHTMLTag_userdefined;
    100  }
    101 
    102  // Setup a stack allocated string buffer with the appropriate length.
    103  nsAutoString lowerCase;
    104  lowerCase.SetLength(length);
    105 
    106  // Operate on the raw buffers to avoid bounds checks.
    107  auto src = aTagName.BeginReading();
    108  auto dst = lowerCase.BeginWriting();
    109 
    110  // Fast lowercasing-while-copying of ASCII characters into a
    111  // nsString buffer.
    112 
    113  for (uint32_t i = 0; i < length; i++) {
    114    char16_t c = src[i];
    115 
    116    if (c <= 'Z' && c >= 'A') {
    117      c |= 0x20;  // Lowercase the ASCII character.
    118    }
    119 
    120    dst[i] = c;  // Copy ASCII character.
    121  }
    122 
    123  return CaseSensitiveStringTagToId(lowerCase);
    124 }
    125 
    126 #ifdef DEBUG
    127 void nsHTMLTags::TestTagTable() {
    128  const char16_t* tag;
    129  nsHTMLTag id;
    130  RefPtr<nsAtom> atom;
    131 
    132  nsHTMLTags::AddRefTable();
    133  // Make sure we can find everything we are supposed to
    134  for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
    135    tag = sTagNames[i];
    136    const nsAString& tagString = nsDependentString(tag);
    137    id = StringTagToId(tagString);
    138    NS_ASSERTION(id != eHTMLTag_userdefined, "can't find tag id");
    139 
    140    nsAutoString uname(tagString);
    141    ToUpperCase(uname);
    142    NS_ASSERTION(id == StringTagToId(uname), "wrong id");
    143 
    144    NS_ASSERTION(id == CaseSensitiveStringTagToId(tagString), "wrong id");
    145 
    146    atom = NS_Atomize(tag);
    147    NS_ASSERTION(id == CaseSensitiveAtomTagToId(atom), "wrong id");
    148  }
    149 
    150  // Make sure we don't find things that aren't there
    151  id = StringTagToId(u"@"_ns);
    152  NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
    153  id = StringTagToId(u"zzzzz"_ns);
    154  NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
    155 
    156  atom = NS_Atomize("@");
    157  id = CaseSensitiveAtomTagToId(atom);
    158  NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
    159  atom = NS_Atomize("zzzzz");
    160  id = CaseSensitiveAtomTagToId(atom);
    161  NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
    162 
    163  ReleaseTable();
    164 }
    165 
    166 #endif  // DEBUG