// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef SANDBOX_LINUX_BPF_DSL_CONS_H_ #define SANDBOX_LINUX_BPF_DSL_CONS_H_ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "sandbox/sandbox_export.h" namespace sandbox { namespace cons { // Namespace cons provides an abstraction for immutable "cons list" // data structures as commonly provided in functional programming // languages like Lisp or Haskell. // // A cons list is a linked list consisting of "cells", each of which // have a "head" and a "tail" element. A cell's head element contains // a user specified value, while the tail element contains a (possibly // null) pointer to another cell. // // An empty list (idiomatically referred to as "nil") can be // constructed as "cons::List<Foo>()" or simply as "nullptr" if Foo // can be inferred from context (e.g., calling a function that has a // "cons::List<Foo>" parameter). // // Existing lists (including empty lists) can be extended by // prepending new values to the front using the "Cons(head, tail)" // function, which will allocate a new cons cell. Notably, cons lists // support creating multiple lists that share a common tail sequence. // // Lastly, lists support iteration via C++11's range-based for loop // construct. // // Examples: // // // basic construction // const cons::List<char> kNil = nullptr; // cons::List<char> ba = Cons('b', Cons('a', kNil)); // // // common tail sequence // cons::List<char> cba = Cons('c', ba); // cons::List<char> dba = Cons('d', ba); // // // iteration // for (const char& ch : cba) { // // iterates 'c', 'b', 'a' // } // for (const char& ch : dba) { // // iterates 'd', 'b', 'a' // } // Forward declarations. template <typename T> class Cell; template <typename T> class ListIterator; // List represents a (possibly null) pointer to a cons cell. template <typename T> using List = scoped_refptr<const Cell<T>>; // Cons extends a cons list by prepending a new value to the front. template <typename T> List<T> Cons(const T& head, const List<T>& tail) { return List<T>(new const Cell<T>(head, tail)); } // Cell represents an individual "cons cell" within a cons list. template <typename T> class Cell : public base::RefCounted<Cell<T>> { public: Cell(const T& head, const List<T>& tail) : head_(head), tail_(tail) {} // Head returns this cell's head element. const T& head() const { return head_; } // Tail returns this cell's tail element. const List<T>& tail() const { return tail_; } private: virtual ~Cell() {} T head_; List<T> tail_; friend class base::RefCounted<Cell<T>>; DISALLOW_COPY_AND_ASSIGN(Cell); }; // Begin returns a list iterator pointing to the first element of the // cons list. It's provided to support range-based for loops. template <typename T> ListIterator<T> begin(const List<T>& list) { return ListIterator<T>(list); } // End returns a list iterator pointing to the "past-the-end" element // of the cons list (i.e., nil). It's provided to support range-based // for loops. template <typename T> ListIterator<T> end(const List<T>& list) { return ListIterator<T>(); } // ListIterator provides C++ forward iterator semantics for traversing // a cons list. template <typename T> class ListIterator { public: ListIterator() : list_() {} explicit ListIterator(const List<T>& list) : list_(list) {} const T& operator*() const { return list_->head(); } ListIterator& operator++() { list_ = list_->tail(); return *this; } friend bool operator==(const ListIterator& lhs, const ListIterator& rhs) { return lhs.list_ == rhs.list_; } private: List<T> list_; }; template <typename T> bool operator!=(const ListIterator<T>& lhs, const ListIterator<T>& rhs) { return !(lhs == rhs); } } // namespace cons } // namespace sandbox #endif // SANDBOX_LINUX_BPF_DSL_CONS_H_