//===--- TransformArrayRef.h ------------------------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// /// /// \file /// /// This file defines TransformArrayRef, a template class that provides a /// transformed view of an ArrayRef. The difference from ArrayRefView is that /// ArrayRefView takes its transform as a template argument, while /// TransformArrayRef only takes a type as its template argument. This means it /// can be used to define types used with forward declaration pointers without /// needing to define the relevant function in headers. /// //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_TRANSFORMARRAYREF_H #define SWIFT_BASIC_TRANSFORMARRAYREF_H #include "swift/Basic/STLExtras.h" #include "llvm/ADT/ArrayRef.h" namespace swift { /// A transformation of an ArrayRef using a function of type FuncTy. This is /// different than ArrayRefView since the underlying function is stored instead /// of used as a template parameter. This allows it to be used in declarations /// where the underlying function is not known. This is useful when defining the /// underlying function would require forward declarations to need to be /// defined. template class TransformArrayRef { public: using FunctionTraits = function_traits; using Orig = typename std::tuple_element<0, typename FunctionTraits::argument_types>::type; using Projected = typename FunctionTraits::result_type; private: llvm::ArrayRef Array; FuncTy Func; public: TransformArrayRef(llvm::ArrayRef array, FuncTy func) : Array(array), Func(func) {} class iterator { friend class TransformArrayRef; const Orig *Ptr; FuncTy Func; iterator(const Orig *ptr, FuncTy func) : Ptr(ptr), Func(func) {} public: typedef Projected value_type; typedef Projected reference; typedef void pointer; typedef ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; Projected operator*() const { return Func(*Ptr); } iterator &operator++() { Ptr++; return *this; } iterator operator++(int) { return iterator(Ptr++, Func); } iterator &operator--() { --Ptr; return *this; } iterator operator--(int) { return iterator(Ptr--, Func); } bool operator==(iterator rhs) const { return Ptr == rhs.Ptr; } bool operator!=(iterator rhs) const { return Ptr != rhs.Ptr; } iterator &operator+=(difference_type i) { Ptr += i; return *this; } iterator operator+(difference_type i) const { return iterator(Ptr + i, Func); } friend iterator operator+(difference_type i, iterator base) { return iterator(base.Ptr + i, base.Func); } iterator &operator-=(difference_type i) { Ptr -= i; return *this; } iterator operator-(difference_type i) const { return iterator(Ptr - i, Func); } difference_type operator-(iterator rhs) const { return Ptr - rhs.Ptr; } Projected operator[](difference_type i) const { return Func(Ptr[i]); } bool operator<(iterator rhs) const { return Ptr < rhs.Ptr; } bool operator<=(iterator rhs) const { return Ptr <= rhs.Ptr; } bool operator>(iterator rhs) const { return Ptr > rhs.Ptr; } bool operator>=(iterator rhs) const { return Ptr >= rhs.Ptr; } }; iterator begin() const { return iterator(Array.begin(), Func); } iterator end() const { return iterator(Array.end(), Func); } bool empty() const { return Array.empty(); } size_t size() const { return Array.size(); } Projected operator[](unsigned i) const { return Func(Array[i]); } Projected front() const { return Func(Array.front()); } Projected back() const { return Func(Array.back()); } TransformArrayRef slice(unsigned start) const { return TransformArrayRef(Array.slice(start), Func); } TransformArrayRef slice(unsigned start, unsigned length) const { return TransformArrayRef(Array.slice(start, length), Func); } }; template TransformArrayRef> makeTransformArrayRef(llvm::ArrayRef Array, std::function Func) { return TransformArrayRef(Array, Func); } } // namespace swift #endif