tor-browser

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

Nestable.h (2173B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef ds_Nestable_h
      8 #define ds_Nestable_h
      9 
     10 #include "mozilla/Assertions.h"
     11 
     12 namespace js {
     13 
     14 // A base class for nestable structures.
     15 //
     16 // This subclasses of this class must follow a LIFO destruction order, The
     17 // easiest way to ensure that is adding MOZ_STACK_CLASS to the subclasses.
     18 // This class doesn't have the MOZ_STACK_CLASS annotation in order to allow
     19 // specific cases where the subclasses can be allocated on heap for reduced
     20 // stack usage and other implementation specific reasons, but even in such
     21 // cases the subclasses must follow a LIFO destruction order.
     22 template <typename Concrete>
     23 class Nestable {
     24  Concrete** stack_;
     25  Concrete* enclosing_;
     26 
     27 protected:
     28  explicit Nestable(Concrete** stack) : stack_(stack), enclosing_(*stack) {
     29    *stack_ = static_cast<Concrete*>(this);
     30  }
     31 
     32  // These method are protected. Some derived classes, such as ParseContext,
     33  // do not expose the ability to walk the stack.
     34  Concrete* enclosing() const { return enclosing_; }
     35 
     36  template <typename Predicate /* (Concrete*) -> bool */>
     37  static Concrete* findNearest(Concrete* it, Predicate predicate) {
     38    while (it && !predicate(it)) {
     39      it = it->enclosing();
     40    }
     41    return it;
     42  }
     43 
     44  template <typename T>
     45  static T* findNearest(Concrete* it) {
     46    while (it && !it->template is<T>()) {
     47      it = it->enclosing();
     48    }
     49    return it ? &it->template as<T>() : nullptr;
     50  }
     51 
     52  template <typename T, typename Predicate /* (T*) -> bool */>
     53  static T* findNearest(Concrete* it, Predicate predicate) {
     54    while (it && (!it->template is<T>() || !predicate(&it->template as<T>()))) {
     55      it = it->enclosing();
     56    }
     57    return it ? &it->template as<T>() : nullptr;
     58  }
     59 
     60 public:
     61  ~Nestable() {
     62    MOZ_ASSERT(*stack_ == static_cast<Concrete*>(this));
     63    *stack_ = enclosing_;
     64  }
     65 };
     66 
     67 }  // namespace js
     68 
     69 #endif /* ds_Nestable_h */