tor-browser

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

AccAttributes.cpp (13549B)


      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 "AccAttributes.h"
      7 #include "StyleInfo.h"
      8 #include "mozilla/ToString.h"
      9 #include "nsAtom.h"
     10 
     11 namespace mozilla::a11y {
     12 
     13 bool AccAttributes::GetAttribute(nsAtom* aAttrName,
     14                                 nsAString& aAttrValue) const {
     15  if (auto value = mData.Lookup(aAttrName)) {
     16    StringFromValueAndName(aAttrName, *value, aAttrValue);
     17    return true;
     18  }
     19 
     20  return false;
     21 }
     22 
     23 void AccAttributes::StringFromValueAndName(nsAtom* aAttrName,
     24                                           const AttrValueType& aValue,
     25                                           nsAString& aValueString) {
     26  aValueString.Truncate();
     27 
     28  aValue.match(
     29      [&aValueString](const bool& val) {
     30        aValueString.Assign(val ? u"true" : u"false");
     31      },
     32      [&aValueString](const float& val) {
     33        aValueString.AppendFloat(val * 100);
     34        aValueString.Append(u"%");
     35      },
     36      [&aValueString](const double& val) { aValueString.AppendFloat(val); },
     37      [&aValueString](const int32_t& val) { aValueString.AppendInt(val); },
     38      [&aValueString](const RefPtr<nsAtom>& val) {
     39        val->ToString(aValueString);
     40      },
     41      [&aValueString](const nsTArray<int32_t>& val) {
     42        if (const size_t len = val.Length()) {
     43          for (size_t i = 0; i < len - 1; i++) {
     44            aValueString.AppendInt(val[i]);
     45            aValueString.Append(u", ");
     46          }
     47          aValueString.AppendInt(val[len - 1]);
     48        } else {
     49          // The array is empty
     50          NS_WARNING(
     51              "Hmm, should we have used a DeleteEntry() for this instead?");
     52          aValueString.Append(u"[ ]");
     53        }
     54      },
     55      [&aValueString](const CSSCoord& val) {
     56        aValueString.AppendFloat(val);
     57        aValueString.Append(u"px");
     58      },
     59      [&aValueString](const FontSize& val) {
     60        aValueString.AppendInt(val.mValue);
     61        aValueString.Append(u"pt");
     62      },
     63      [&aValueString](const Color& val) {
     64        StyleInfo::FormatColor(val.mValue, aValueString);
     65      },
     66      [&aValueString](const DeleteEntry& val) {
     67        aValueString.Append(u"-delete-entry-");
     68      },
     69      [&aValueString](const UniquePtr<nsString>& val) {
     70        aValueString.Assign(*val);
     71      },
     72      [&aValueString](const RefPtr<AccAttributes>& val) {
     73        if (val) {
     74          aValueString.AppendPrintf("AccAttributes: %s",
     75                                    ToString(*val).c_str());
     76        } else {
     77          aValueString.AssignASCII("<null>");
     78        }
     79      },
     80      [&aValueString](const uint64_t& val) { aValueString.AppendInt(val); },
     81      [&aValueString](const UniquePtr<AccGroupInfo>& val) {
     82        aValueString.Assign(u"AccGroupInfo{...}");
     83      },
     84      [&aValueString](const UniquePtr<gfx::Matrix4x4>& val) {
     85        aValueString.AppendPrintf("Matrix4x4=%s", ToString(*val).c_str());
     86      },
     87      [&aValueString](const UniquePtr<nsRect>& val) {
     88        aValueString.AppendPrintf("nsRect=%s", ToString(*val).c_str());
     89      },
     90      [&aValueString](const nsTArray<uint64_t>& val) {
     91        if (const size_t len = val.Length()) {
     92          for (size_t i = 0; i < len - 1; i++) {
     93            aValueString.AppendInt(val[i]);
     94            aValueString.Append(u", ");
     95          }
     96          aValueString.AppendInt(val[len - 1]);
     97        } else {
     98          // The array is empty
     99          NS_WARNING(
    100              "Hmm, should we have used a DeleteEntry() for this instead?");
    101          aValueString.Append(u"[ ]");
    102        }
    103      },
    104      [&aValueString](const nsTArray<TextOffsetAttribute>& val) {
    105        if (const size_t len = val.Length()) {
    106          for (size_t i = 0; i < len - 1; i++) {
    107            aValueString.AppendPrintf("(%d, %d, ", val[i].mStartOffset,
    108                                      val[i].mEndOffset);
    109            aValueString.Append(nsAtomString(val[i].mAttribute));
    110            aValueString.Append(u"), ");
    111          }
    112          aValueString.AppendPrintf("(%d, %d, ", val[len - 1].mStartOffset,
    113                                    val[len - 1].mEndOffset);
    114          aValueString.Append(nsAtomString(val[len - 1].mAttribute));
    115          aValueString += ')';
    116        } else {
    117          // The array is empty
    118          NS_WARNING(
    119              "Hmm, should we have used a DeleteEntry() for this instead?");
    120          aValueString.Append(u"[ ]");
    121        }
    122      },
    123      [&aValueString](const WritingMode& val) {
    124        aValueString.AppendPrintf("WritingModes: %x", val.GetBits());
    125      },
    126      [&aValueString](const nsTArray<RefPtr<nsAtom>>& val) {
    127        if (const size_t len = val.Length()) {
    128          for (size_t i = 0; i < len - 1; i++) {
    129            aValueString.Append(val[i]->GetUTF16String());
    130            aValueString.Append(u" ");
    131          }
    132          aValueString.Append(val[len - 1]->GetUTF16String());
    133        } else {
    134          // The array is empty
    135          NS_WARNING(
    136              "Hmm, should we have used a DeleteEntry() for this instead?");
    137          aValueString.Append(u"");
    138        }
    139      });
    140 }
    141 
    142 void AccAttributes::Update(AccAttributes* aOther) {
    143  for (auto iter = aOther->mData.Iter(); !iter.Done(); iter.Next()) {
    144    if (iter.Data().is<DeleteEntry>()) {
    145      mData.Remove(iter.Key());
    146    } else {
    147      mData.InsertOrUpdate(iter.Key(), std::move(iter.Data()));
    148    }
    149    iter.Remove();
    150  }
    151 }
    152 
    153 void AccAttributes::RemoveIdentical(const AccAttributes* aOther) {
    154  for (auto iter = mData.Iter(); !iter.Done(); iter.Next()) {
    155    if (const auto otherEntry = aOther->mData.Lookup(iter.Key())) {
    156      if (iter.Data().is<UniquePtr<nsString>>()) {
    157        // Because we store nsString in a UniquePtr, we must handle it specially
    158        // so we compare the string and not the pointer.
    159        if (!otherEntry->is<UniquePtr<nsString>>()) {
    160          continue;
    161        }
    162        const auto& thisStr = iter.Data().as<UniquePtr<nsString>>();
    163        const auto& otherStr = otherEntry->as<UniquePtr<nsString>>();
    164        if (*thisStr != *otherStr) {
    165          continue;
    166        }
    167      } else if (iter.Data() != otherEntry.Data()) {
    168        continue;
    169      }
    170 
    171      iter.Remove();
    172    }
    173  }
    174 }
    175 
    176 bool AccAttributes::Equal(const AccAttributes* aOther) const {
    177  if (Count() != aOther->Count()) {
    178    return false;
    179  }
    180  for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) {
    181    const auto otherEntry = aOther->mData.Lookup(iter.Key());
    182    if (!otherEntry) {
    183      return false;
    184    }
    185    if (iter.Data().is<UniquePtr<nsString>>()) {
    186      // Because we store nsString in a UniquePtr, we must handle it specially
    187      // so we compare the string and not the pointer.
    188      if (!otherEntry->is<UniquePtr<nsString>>()) {
    189        return false;
    190      }
    191      const auto& thisStr = iter.Data().as<UniquePtr<nsString>>();
    192      const auto& otherStr = otherEntry->as<UniquePtr<nsString>>();
    193      if (*thisStr != *otherStr) {
    194        return false;
    195      }
    196    } else if (iter.Data() != otherEntry.Data()) {
    197      return false;
    198    }
    199  }
    200  return true;
    201 }
    202 
    203 void AccAttributes::CopyTo(AccAttributes* aDest, bool aOnlyMissing) const {
    204  for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) {
    205    if (aOnlyMissing && aDest->HasAttribute(iter.Key())) {
    206      continue;
    207    }
    208 
    209    iter.Data().match(
    210        [&iter, &aDest](const bool& val) {
    211          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    212        },
    213        [&iter, &aDest](const float& val) {
    214          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    215        },
    216        [&iter, &aDest](const double& val) {
    217          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    218        },
    219        [&iter, &aDest](const int32_t& val) {
    220          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    221        },
    222        [&iter, &aDest](const RefPtr<nsAtom>& val) {
    223          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    224        },
    225        [](const nsTArray<int32_t>& val) {
    226          // We don't copy arrays.
    227          MOZ_ASSERT_UNREACHABLE(
    228              "Trying to copy an AccAttributes containing an array");
    229        },
    230        [&iter, &aDest](const CSSCoord& val) {
    231          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    232        },
    233        [&iter, &aDest](const FontSize& val) {
    234          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    235        },
    236        [&iter, &aDest](const Color& val) {
    237          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    238        },
    239        [](const DeleteEntry& val) {
    240          // We don't copy DeleteEntry.
    241          MOZ_ASSERT_UNREACHABLE(
    242              "Trying to copy an AccAttributes containing a DeleteEntry");
    243        },
    244        [&iter, &aDest](const UniquePtr<nsString>& val) {
    245          aDest->SetAttributeStringCopy(iter.Key(), *val);
    246        },
    247        [](const RefPtr<AccAttributes>& val) {
    248          // We don't copy nested AccAttributes.
    249          MOZ_ASSERT_UNREACHABLE(
    250              "Trying to copy an AccAttributes containing an AccAttributes");
    251        },
    252        [&iter, &aDest](const uint64_t& val) {
    253          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    254        },
    255        [](const UniquePtr<AccGroupInfo>& val) {
    256          MOZ_ASSERT_UNREACHABLE(
    257              "Trying to copy an AccAttributes containing an AccGroupInfo");
    258        },
    259        [](const UniquePtr<gfx::Matrix4x4>& val) {
    260          MOZ_ASSERT_UNREACHABLE(
    261              "Trying to copy an AccAttributes containing a matrix");
    262        },
    263        [](const UniquePtr<nsRect>& val) {
    264          MOZ_ASSERT_UNREACHABLE(
    265              "Trying to copy an AccAttributes containing a nsrect");
    266        },
    267        [](const nsTArray<uint64_t>& val) {
    268          // We don't copy arrays.
    269          MOZ_ASSERT_UNREACHABLE(
    270              "Trying to copy an AccAttributes containing an array");
    271        },
    272        [](const nsTArray<TextOffsetAttribute>& val) {
    273          // We don't copy arrays.
    274          MOZ_ASSERT_UNREACHABLE(
    275              "Trying to copy an AccAttributes containing an array");
    276        },
    277        [&iter, &aDest](const WritingMode& val) {
    278          aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val));
    279        },
    280        [](const nsTArray<RefPtr<nsAtom>>& val) {
    281          // We don't copy arrays.
    282          MOZ_ASSERT_UNREACHABLE(
    283              "Trying to copy an AccAttributes containing an array");
    284        });
    285  }
    286 }
    287 
    288 #ifdef A11Y_LOG
    289 void AccAttributes::DebugPrint(const char* aPrefix,
    290                               const AccAttributes& aAttributes) {
    291  printf("%s %s\n", aPrefix, ToString(aAttributes).c_str());
    292 }
    293 #endif
    294 
    295 size_t AccAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
    296  size_t size =
    297      aMallocSizeOf(this) + mData.ShallowSizeOfExcludingThis(aMallocSizeOf);
    298 
    299  for (auto iter : *this) {
    300    size += iter.SizeOfExcludingThis(aMallocSizeOf);
    301  }
    302 
    303  return size;
    304 }
    305 
    306 size_t AccAttributes::Entry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) {
    307  size_t size = 0;
    308 
    309  // We don't count the size of Name() since it's counted by the atoms table
    310  // memory reporter.
    311 
    312  if (mValue->is<nsTArray<int32_t>>()) {
    313    size += mValue->as<nsTArray<int32_t>>().ShallowSizeOfExcludingThis(
    314        aMallocSizeOf);
    315  } else if (mValue->is<UniquePtr<nsString>>()) {
    316    // String data will never be shared.
    317    size += mValue->as<UniquePtr<nsString>>()->SizeOfIncludingThisIfUnshared(
    318        aMallocSizeOf);
    319  } else if (mValue->is<RefPtr<AccAttributes>>()) {
    320    size +=
    321        mValue->as<RefPtr<AccAttributes>>()->SizeOfIncludingThis(aMallocSizeOf);
    322  } else if (mValue->is<UniquePtr<AccGroupInfo>>()) {
    323    size += mValue->as<UniquePtr<AccGroupInfo>>()->SizeOfIncludingThis(
    324        aMallocSizeOf);
    325  } else if (mValue->is<UniquePtr<gfx::Matrix4x4>>()) {
    326    size += aMallocSizeOf(mValue->as<UniquePtr<gfx::Matrix4x4>>().get());
    327  } else if (mValue->is<UniquePtr<nsRect>>()) {
    328    size += aMallocSizeOf(mValue->as<UniquePtr<nsRect>>().get());
    329  } else if (mValue->is<nsTArray<uint64_t>>()) {
    330    size += mValue->as<nsTArray<uint64_t>>().ShallowSizeOfExcludingThis(
    331        aMallocSizeOf);
    332  } else if (mValue->is<nsTArray<RefPtr<nsAtom>>>()) {
    333    size += mValue->as<nsTArray<RefPtr<nsAtom>>>().ShallowSizeOfExcludingThis(
    334        aMallocSizeOf);
    335  } else {
    336    // This type is stored directly and already counted or is an atom and
    337    // stored and counted in the atoms table.
    338    // Assert that we have exhausted all the remaining variant types.
    339    MOZ_ASSERT(mValue->is<RefPtr<nsAtom>>() || mValue->is<bool>() ||
    340               mValue->is<float>() || mValue->is<double>() ||
    341               mValue->is<int32_t>() || mValue->is<uint64_t>() ||
    342               mValue->is<CSSCoord>() || mValue->is<FontSize>() ||
    343               mValue->is<Color>() || mValue->is<DeleteEntry>());
    344  }
    345 
    346  return size;
    347 }
    348 
    349 std::ostream& operator<<(std::ostream& aStream,
    350                         const AccAttributes& aAttributes) {
    351  if (aAttributes.Count() == 0) {
    352    aStream << "{ empty }";
    353    return aStream;
    354  }
    355  aStream << "{\n";
    356  nsAutoStringN<2> separator{};
    357  nsAutoString scratch;
    358  for (const AccAttributes::Entry entry : aAttributes) {
    359    aStream << separator << "  ";
    360    entry.NameAsString(scratch);
    361    aStream << scratch << ": ";
    362    entry.ValueAsString(scratch);
    363    aStream << scratch;
    364    separator.AssignASCII(",\n");
    365  }
    366  aStream << "\n}";
    367  return aStream;
    368 }
    369 
    370 }  // namespace mozilla::a11y