/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AccAttributes.h" #include "StyleInfo.h" #include "mozilla/ToString.h" #include "nsAtom.h" namespace mozilla::a11y { bool AccAttributes::GetAttribute(nsAtom* aAttrName, nsAString& aAttrValue) const { if (auto value = mData.Lookup(aAttrName)) { StringFromValueAndName(aAttrName, *value, aAttrValue); return true; } return false; } void AccAttributes::StringFromValueAndName(nsAtom* aAttrName, const AttrValueType& aValue, nsAString& aValueString) { aValueString.Truncate(); aValue.match( [&aValueString](const bool& val) { aValueString.Assign(val ? u"true" : u"false"); }, [&aValueString](const float& val) { aValueString.AppendFloat(val * 100); aValueString.Append(u"%"); }, [&aValueString](const double& val) { aValueString.AppendFloat(val); }, [&aValueString](const int32_t& val) { aValueString.AppendInt(val); }, [&aValueString](const RefPtr& val) { val->ToString(aValueString); }, [&aValueString](const nsTArray& val) { if (const size_t len = val.Length()) { for (size_t i = 0; i < len - 1; i++) { aValueString.AppendInt(val[i]); aValueString.Append(u", "); } aValueString.AppendInt(val[len - 1]); } else { // The array is empty NS_WARNING( "Hmm, should we have used a DeleteEntry() for this instead?"); aValueString.Append(u"[ ]"); } }, [&aValueString](const CSSCoord& val) { aValueString.AppendFloat(val); aValueString.Append(u"px"); }, [&aValueString](const FontSize& val) { aValueString.AppendInt(val.mValue); aValueString.Append(u"pt"); }, [&aValueString](const Color& val) { StyleInfo::FormatColor(val.mValue, aValueString); }, [&aValueString](const DeleteEntry& val) { aValueString.Append(u"-delete-entry-"); }, [&aValueString](const UniquePtr& val) { aValueString.Assign(*val); }, [&aValueString](const RefPtr& val) { if (val) { aValueString.AppendPrintf("AccAttributes: %s", ToString(*val).c_str()); } else { aValueString.AssignASCII(""); } }, [&aValueString](const uint64_t& val) { aValueString.AppendInt(val); }, [&aValueString](const UniquePtr& val) { aValueString.Assign(u"AccGroupInfo{...}"); }, [&aValueString](const UniquePtr& val) { aValueString.AppendPrintf("Matrix4x4=%s", ToString(*val).c_str()); }, [&aValueString](const nsTArray& val) { if (const size_t len = val.Length()) { for (size_t i = 0; i < len - 1; i++) { aValueString.AppendInt(val[i]); aValueString.Append(u", "); } aValueString.AppendInt(val[len - 1]); } else { // The array is empty NS_WARNING( "Hmm, should we have used a DeleteEntry() for this instead?"); aValueString.Append(u"[ ]"); } }, [&aValueString](const nsTArray& val) { if (const size_t len = val.Length()) { for (size_t i = 0; i < len - 1; i++) { aValueString.AppendPrintf("(%d, %d, ", val[i].mStartOffset, val[i].mEndOffset); aValueString.Append(nsAtomString(val[i].mAttribute)); aValueString.Append(u"), "); } aValueString.AppendPrintf("(%d, %d, ", val[len - 1].mStartOffset, val[len - 1].mEndOffset); aValueString.Append(nsAtomString(val[len - 1].mAttribute)); aValueString += ')'; } else { // The array is empty NS_WARNING( "Hmm, should we have used a DeleteEntry() for this instead?"); aValueString.Append(u"[ ]"); } }); } void AccAttributes::Update(AccAttributes* aOther) { for (auto iter = aOther->mData.Iter(); !iter.Done(); iter.Next()) { if (iter.Data().is()) { mData.Remove(iter.Key()); } else { mData.InsertOrUpdate(iter.Key(), std::move(iter.Data())); } iter.Remove(); } } bool AccAttributes::Equal(const AccAttributes* aOther) const { if (Count() != aOther->Count()) { return false; } for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) { const auto otherEntry = aOther->mData.Lookup(iter.Key()); if (!otherEntry) { return false; } if (iter.Data().is>()) { // Because we store nsString in a UniquePtr, we must handle it specially // so we compare the string and not the pointer. if (!otherEntry->is>()) { return false; } const auto& thisStr = iter.Data().as>(); const auto& otherStr = otherEntry->as>(); if (*thisStr != *otherStr) { return false; } } else if (iter.Data() != otherEntry.Data()) { return false; } } return true; } void AccAttributes::CopyTo(AccAttributes* aDest) const { for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) { iter.Data().match( [&iter, &aDest](const bool& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const float& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const double& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const int32_t& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const RefPtr& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [](const nsTArray& val) { // We don't copy arrays. MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing an array"); }, [&iter, &aDest](const CSSCoord& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const FontSize& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [&iter, &aDest](const Color& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [](const DeleteEntry& val) { // We don't copy DeleteEntry. MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing a DeleteEntry"); }, [&iter, &aDest](const UniquePtr& val) { aDest->SetAttributeStringCopy(iter.Key(), *val); }, [](const RefPtr& val) { // We don't copy nested AccAttributes. MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing an AccAttributes"); }, [&iter, &aDest](const uint64_t& val) { aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); }, [](const UniquePtr& val) { MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing an AccGroupInfo"); }, [](const UniquePtr& val) { MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing a matrix"); }, [](const nsTArray& val) { // We don't copy arrays. MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing an array"); }, [](const nsTArray& val) { // We don't copy arrays. MOZ_ASSERT_UNREACHABLE( "Trying to copy an AccAttributes containing an array"); }); } } #ifdef A11Y_LOG void AccAttributes::DebugPrint(const char* aPrefix, const AccAttributes& aAttributes) { printf("%s %s\n", aPrefix, ToString(aAttributes).c_str()); } #endif size_t AccAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { size_t size = aMallocSizeOf(this) + mData.ShallowSizeOfExcludingThis(aMallocSizeOf); for (auto iter : *this) { size += iter.SizeOfExcludingThis(aMallocSizeOf); } return size; } size_t AccAttributes::Entry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) { size_t size = 0; // We don't count the size of Name() since it's counted by the atoms table // memory reporter. if (mValue->is>()) { size += mValue->as>().ShallowSizeOfExcludingThis( aMallocSizeOf); } else if (mValue->is>()) { // String data will never be shared. size += mValue->as>()->SizeOfIncludingThisIfUnshared( aMallocSizeOf); } else if (mValue->is>()) { size += mValue->as>()->SizeOfIncludingThis(aMallocSizeOf); } else if (mValue->is>()) { size += mValue->as>()->SizeOfIncludingThis( aMallocSizeOf); } else if (mValue->is>()) { size += aMallocSizeOf(mValue->as>().get()); } else if (mValue->is>()) { size += mValue->as>().ShallowSizeOfExcludingThis( aMallocSizeOf); } else { // This type is stored directly and already counted or is an atom and // stored and counted in the atoms table. // Assert that we have exhausted all the remaining variant types. MOZ_ASSERT(mValue->is>() || mValue->is() || mValue->is() || mValue->is() || mValue->is() || mValue->is() || mValue->is() || mValue->is() || mValue->is() || mValue->is()); } return size; } std::ostream& operator<<(std::ostream& aStream, const AccAttributes& aAttributes) { if (aAttributes.Count() == 0) { aStream << "{ empty }"; return aStream; } aStream << "{\n"; nsAutoStringN<2> separator{}; nsAutoString scratch; for (const AccAttributes::Entry entry : aAttributes) { aStream << separator << " "; entry.NameAsString(scratch); aStream << scratch << ": "; entry.ValueAsString(scratch); aStream << scratch; separator.AssignASCII(",\n"); } aStream << "\n}"; return aStream; } } // namespace mozilla::a11y