#ifndef ds_Nestable_h
#define ds_Nestable_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
namespace js {
template <typename Concrete>
class MOZ_STACK_CLASS Nestable {
Concrete** stack_;
Concrete* enclosing_;
protected:
explicit Nestable(Concrete** stack) : stack_(stack), enclosing_(*stack) {
*stack_ = static_cast<Concrete*>(this);
}
Concrete* enclosing() const { return enclosing_; }
template <typename Predicate >
static Concrete* findNearest(Concrete* it, Predicate predicate) {
while (it && !predicate(it)) {
it = it->enclosing();
}
return it;
}
template <typename T>
static T* findNearest(Concrete* it) {
while (it && !it->template is<T>()) {
it = it->enclosing();
}
return it ? &it->template as<T>() : nullptr;
}
template <typename T, typename Predicate >
static T* findNearest(Concrete* it, Predicate predicate) {
while (it && (!it->template is<T>() || !predicate(&it->template as<T>()))) {
it = it->enclosing();
}
return it ? &it->template as<T>() : nullptr;
}
public:
~Nestable() {
MOZ_ASSERT(*stack_ == static_cast<Concrete*>(this));
*stack_ = enclosing_;
}
};
}
#endif