зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset e2d3d7bb9d1f (bug 1457728) for build bustages at build\build\src\xpcom\ds\nsTArray.h(807) on a CLOSED TREE
This commit is contained in:
Родитель
8751f930ce
Коммит
be1d77cb98
|
@ -28,6 +28,21 @@ CompareIIDs(const nsIID& aA, const nsIID &aB)
|
|||
return memcmp((void*)&aA.m0, (void*)&aB.m0, IID_SIZE);
|
||||
}
|
||||
|
||||
struct IIDComparator
|
||||
{
|
||||
bool
|
||||
LessThan(const nsIID& aA, const nsIID &aB) const
|
||||
{
|
||||
return CompareIIDs(aA, aB) < 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Equals(const nsIID& aA, const nsIID &aB) const
|
||||
{
|
||||
return aA.Equals(aB);
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
MozQueryInterface*
|
||||
ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningStringOrIID>& aInterfaces, ErrorResult& aRv)
|
||||
|
@ -83,10 +98,10 @@ ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningString
|
|||
ifaces.AppendElement(*iid->GetID());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!ifaces.Contains(NS_GET_IID(nsISupports), CompareIIDs));
|
||||
MOZ_ASSERT(!ifaces.Contains(NS_GET_IID(nsISupports), IIDComparator()));
|
||||
ifaces.AppendElement(NS_GET_IID(nsISupports));
|
||||
|
||||
ifaces.Sort(CompareIIDs);
|
||||
ifaces.Sort(IIDComparator());
|
||||
|
||||
return new MozQueryInterface(std::move(ifaces));
|
||||
}
|
||||
|
@ -94,7 +109,12 @@ ChromeUtils::GenerateQI(const GlobalObject& aGlobal, const Sequence<OwningString
|
|||
bool
|
||||
MozQueryInterface::QueriesTo(const nsIID& aIID) const
|
||||
{
|
||||
return mInterfaces.ContainsSorted(aIID, CompareIIDs);
|
||||
// We use BinarySearchIf here because nsTArray::ContainsSorted requires
|
||||
// twice as many comparisons.
|
||||
size_t result;
|
||||
return BinarySearchIf(mInterfaces, 0, mInterfaces.Length(),
|
||||
[&] (const nsIID& aOther) { return CompareIIDs(aIID, aOther); },
|
||||
&result);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -772,93 +772,43 @@ struct nsTArray_TypedBase<JS::Heap<E>, Derived>
|
|||
|
||||
namespace detail {
|
||||
|
||||
// These helpers allow us to differentiate between tri-state comparator
|
||||
// functions and classes with LessThan() and Equal() methods. If an object, when
|
||||
// called as a function with two instances of our element type, returns an int,
|
||||
// we treat it as a tri-state comparator.
|
||||
//
|
||||
// T is the type of the comparator object we want to check. U is the array
|
||||
// element type that we'll be comparing.
|
||||
//
|
||||
// V is never passed, and is only used to allow us to specialize on the return
|
||||
// value of the comparator function.
|
||||
template <typename T, typename U, typename V = int>
|
||||
struct IsCompareMethod : mozilla::FalseType {};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct IsCompareMethod<T, U, decltype(mozilla::DeclVal<T>()(mozilla::DeclVal<U>(), mozilla::DeclVal<U>()))>
|
||||
: mozilla::TrueType {};
|
||||
|
||||
// These two wrappers allow us to use either a tri-state comparator, or an
|
||||
// object with Equals() and LessThan() methods interchangeably. They provide a
|
||||
// tri-state Compare() method, and Equals() method, and a LessThan() method.
|
||||
//
|
||||
// Depending on the type of the underlying comparator, they either pass these
|
||||
// through directly, or synthesize them from the methods available on the
|
||||
// comparator.
|
||||
//
|
||||
// Callers should always use the most-specific of these methods that match their
|
||||
// purpose.
|
||||
|
||||
// Comparator wrapper for a tri-state comparator function
|
||||
template <typename T, typename U, bool IsCompare = IsCompareMethod<T, U>::value>
|
||||
struct CompareWrapper
|
||||
template<class Item, class Comparator>
|
||||
struct ItemComparatorEq
|
||||
{
|
||||
MOZ_IMPLICIT CompareWrapper(const T& aComparator)
|
||||
: mComparator(aComparator)
|
||||
const Item& mItem;
|
||||
const Comparator& mComp;
|
||||
ItemComparatorEq(const Item& aItem, const Comparator& aComp)
|
||||
: mItem(aItem)
|
||||
, mComp(aComp)
|
||||
{}
|
||||
|
||||
template <typename A, typename B>
|
||||
int Compare(A& aLeft, B& aRight) const
|
||||
{
|
||||
return mComparator(aLeft, aRight);
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
bool Equals(A& aLeft, B& aRight) const
|
||||
{
|
||||
return Compare(aLeft, aRight) == 0;
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
bool LessThan(A& aLeft, B& aRight) const
|
||||
{
|
||||
return Compare(aLeft, aRight) < 0;
|
||||
}
|
||||
|
||||
const T& mComparator;
|
||||
};
|
||||
|
||||
// Comparator wrapper for a class with Equals() and LessThan() methods.
|
||||
template <typename T, typename U>
|
||||
struct CompareWrapper<T, U, false>
|
||||
{
|
||||
MOZ_IMPLICIT CompareWrapper(const T& aComparator)
|
||||
: mComparator(aComparator)
|
||||
{}
|
||||
|
||||
template <typename A, typename B>
|
||||
int Compare(A& aLeft, B& aRight) const
|
||||
{
|
||||
if (Equals(aLeft, aRight)) {
|
||||
template<class T>
|
||||
int operator()(const T& aElement) const {
|
||||
if (mComp.Equals(aElement, mItem)) {
|
||||
return 0;
|
||||
}
|
||||
return LessThan(aLeft, aRight) ? -1 : 1;
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
bool Equals(A& aLeft, B& aRight) const
|
||||
{
|
||||
return mComparator.Equals(aLeft, aRight);
|
||||
return mComp.LessThan(aElement, mItem) ? 1 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename A, typename B>
|
||||
bool LessThan(A& aLeft, B& aRight) const
|
||||
{
|
||||
return mComparator.LessThan(aLeft, aRight);
|
||||
template<class Item, class Comparator>
|
||||
struct ItemComparatorFirstElementGT
|
||||
{
|
||||
const Item& mItem;
|
||||
const Comparator& mComp;
|
||||
ItemComparatorFirstElementGT(const Item& aItem, const Comparator& aComp)
|
||||
: mItem(aItem)
|
||||
, mComp(aComp)
|
||||
{}
|
||||
template<class T>
|
||||
int operator()(const T& aElement) const {
|
||||
if (mComp.LessThan(aElement, mItem) ||
|
||||
mComp.Equals(aElement, mItem)) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const T& mComparator;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -1217,12 +1167,10 @@ public:
|
|||
index_type IndexOf(const Item& aItem, index_type aStart,
|
||||
const Comparator& aComp) const
|
||||
{
|
||||
::detail::CompareWrapper<Comparator, Item> comp(aComp);
|
||||
|
||||
const elem_type* iter = Elements() + aStart;
|
||||
const elem_type* iend = Elements() + Length();
|
||||
for (; iter != iend; ++iter) {
|
||||
if (comp.Equals(*iter, aItem)) {
|
||||
if (aComp.Equals(*iter, aItem)) {
|
||||
return index_type(iter - Elements());
|
||||
}
|
||||
}
|
||||
|
@ -1252,13 +1200,11 @@ public:
|
|||
index_type LastIndexOf(const Item& aItem, index_type aStart,
|
||||
const Comparator& aComp) const
|
||||
{
|
||||
::detail::CompareWrapper<Comparator, Item> comp(aComp);
|
||||
|
||||
size_type endOffset = aStart >= Length() ? Length() : aStart + 1;
|
||||
const elem_type* iend = Elements() - 1;
|
||||
const elem_type* iter = iend + endOffset;
|
||||
for (; iter != iend; --iter) {
|
||||
if (comp.Equals(*iter, aItem)) {
|
||||
if (aComp.Equals(*iter, aItem)) {
|
||||
return index_type(iter - Elements());
|
||||
}
|
||||
}
|
||||
|
@ -1290,20 +1236,10 @@ public:
|
|||
index_type BinaryIndexOf(const Item& aItem, const Comparator& aComp) const
|
||||
{
|
||||
using mozilla::BinarySearchIf;
|
||||
::detail::CompareWrapper<Comparator, Item> comp(aComp);
|
||||
typedef ::detail::ItemComparatorEq<Item, Comparator> Cmp;
|
||||
|
||||
size_t index;
|
||||
bool found = BinarySearchIf(
|
||||
*this, 0, Length(),
|
||||
// Note: We pass the Compare() args here in reverse order and negate the
|
||||
// results for compatibility reasons. Some existing callers use Equals()
|
||||
// functions with first arguments which match aElement but not aItem, or
|
||||
// second arguments that match aItem but not aElement. To accommodate
|
||||
// those callers, we preserve the argument order of the older version of
|
||||
// this API. These callers, however, should be fixed, and this special
|
||||
// case removed.
|
||||
[&] (const elem_type& aElement) { return -comp.Compare(aElement, aItem); },
|
||||
&index);
|
||||
bool found = BinarySearchIf(*this, 0, Length(), Cmp(aItem, aComp), &index);
|
||||
return found ? index : NoIndex;
|
||||
}
|
||||
|
||||
|
@ -1598,12 +1534,10 @@ public:
|
|||
const Comparator& aComp) const
|
||||
{
|
||||
using mozilla::BinarySearchIf;
|
||||
::detail::CompareWrapper<Comparator, Item> comp(aComp);
|
||||
typedef ::detail::ItemComparatorFirstElementGT<Item, Comparator> Cmp;
|
||||
|
||||
size_t index;
|
||||
BinarySearchIf(*this, 0, Length(),
|
||||
[&] (const elem_type& aElement) { return comp.Compare(aElement, aItem) <= 0 ? 1 : -1; },
|
||||
&index);
|
||||
BinarySearchIf(*this, 0, Length(), Cmp(aItem, aComp), &index);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -2099,7 +2033,7 @@ public:
|
|||
const Comparator* c = reinterpret_cast<const Comparator*>(aData);
|
||||
const elem_type* a = static_cast<const elem_type*>(aE1);
|
||||
const elem_type* b = static_cast<const elem_type*>(aE2);
|
||||
return c->Compare(*a, *b);
|
||||
return c->LessThan(*a, *b) ? -1 : (c->Equals(*a, *b) ? 0 : 1);
|
||||
}
|
||||
|
||||
// This method sorts the elements of the array. It uses the LessThan
|
||||
|
@ -2108,10 +2042,8 @@ public:
|
|||
template<class Comparator>
|
||||
void Sort(const Comparator& aComp)
|
||||
{
|
||||
::detail::CompareWrapper<Comparator, elem_type> comp(aComp);
|
||||
|
||||
NS_QuickSort(Elements(), Length(), sizeof(elem_type),
|
||||
Compare<decltype(comp)>, &comp);
|
||||
Compare<Comparator>, const_cast<Comparator*>(&aComp));
|
||||
}
|
||||
|
||||
// A variation on the Sort method defined above that assumes that
|
||||
|
|
|
@ -1039,51 +1039,4 @@ TEST(TArray, test_SetLengthAndRetainStorage_no_ctor) {
|
|||
#undef RPAREN
|
||||
}
|
||||
|
||||
template <typename Comparator>
|
||||
bool
|
||||
TestCompareMethods(const Comparator& aComp)
|
||||
{
|
||||
nsTArray<int> ary({57, 4, 16, 17, 3, 5, 96, 12});
|
||||
|
||||
ary.Sort(aComp);
|
||||
|
||||
const int sorted[] = {3, 4, 5, 12, 16, 17, 57, 96 };
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sorted); i++) {
|
||||
if (sorted[i] != ary[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ary.ContainsSorted(5, aComp)) {
|
||||
return false;
|
||||
}
|
||||
if (ary.ContainsSorted(42, aComp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ary.BinaryIndexOf(16, aComp) != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct IntComparator
|
||||
{
|
||||
bool Equals(int aLeft, int aRight) const
|
||||
{
|
||||
return aLeft == aRight;
|
||||
}
|
||||
|
||||
bool LessThan(int aLeft, int aRight) const
|
||||
{
|
||||
return aLeft < aRight;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TArray, test_comparator_objects) {
|
||||
ASSERT_TRUE(TestCompareMethods(IntComparator()));
|
||||
ASSERT_TRUE(TestCompareMethods([] (int aLeft, int aRight) { return aLeft - aRight; }));
|
||||
}
|
||||
|
||||
} // namespace TestTArray
|
||||
|
|
Загрузка…
Ссылка в новой задаче