1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <memory> 20 #include <vector> 21 22 #include <thrift/compiler/ast/detail/view.h> 23 24 namespace apache { 25 namespace thrift { 26 namespace compiler { 27 28 // The type to use to hold a list of nodes of type T. 29 template <typename T> 30 using node_list = std::vector<std::unique_ptr<T>>; 31 32 // A view of a node_list of nodes of type T. 33 // 34 // If T is const, only provides const access to the nodes in the 35 // node_list. 36 // 37 // Like std::ranges::view, std::span and std::string_view, this class provides 38 // access to memory it does not own and must not be accessed after the 39 // associated node_list is destroyed. 40 // 41 // TODO(afuller): When c++20 can be used, switch to using 42 // std::ranges::transform_view instead. 43 template <typename T> 44 class node_list_view : public ast_detail::base_view<node_list_view<T>, T*> { 45 using base = ast_detail::base_view<node_list_view<T>, T*>; 46 using node_list_type = node_list<std::remove_cv_t<T>>; 47 48 public: 49 using size_type = typename node_list_type::size_type; 50 using difference_type = typename node_list_type::difference_type; 51 52 // Return by reference. 53 using value_type = std::remove_const_t<T>; 54 using pointer = T*; 55 using reference = T&; 56 57 class iterator { 58 friend class node_list_view; 59 using itr_type = typename node_list_type::const_iterator; iterator(itr_type itr)60 /* implicit */ constexpr iterator(itr_type itr) : itr_(std::move(itr)) {} 61 62 public: 63 using iterator_category = typename itr_type::iterator_category; 64 using difference_type = typename itr_type::difference_type; 65 using value_type = node_list_view::value_type; 66 using pointer = node_list_view::pointer; 67 using reference = node_list_view::reference; 68 69 reference operator*() const noexcept { return itr_->operator*(); } 70 reference operator[](difference_type n) const noexcept { return *itr_[n]; } 71 72 iterator operator++(int) noexcept { return {itr_++}; } 73 iterator& operator++() noexcept { 74 ++itr_; 75 return *this; 76 } 77 iterator& operator+=(difference_type n) noexcept { 78 itr_ += n; 79 return *this; 80 } 81 iterator& operator-=(difference_type n) noexcept { 82 itr_ -= n; 83 return *this; 84 } 85 86 friend iterator operator-( 87 const iterator& a, const difference_type& n) noexcept { 88 return {a.itr_ - n}; 89 } 90 friend iterator operator+( 91 const iterator& a, const difference_type& n) noexcept { 92 return {a.itr_ + n}; 93 } 94 friend iterator operator+( 95 const difference_type& n, const iterator& b) noexcept { 96 return {n + b.itr_}; 97 } 98 99 private: 100 itr_type itr_; 101 102 #define __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(op) \ 103 friend auto operator op(const iterator& a, const iterator& b) { \ 104 return a.itr_ op b.itr_; \ 105 } 106 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(-) 107 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(==) 108 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(!=) 109 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(<) 110 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(<=) 111 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(>) 112 __FBTHRIFT_NODE_SPAN_ITR_FWD_OP(>=) 113 #undef __FBTHRIFT_NODE_SPAN_ITR_FWD_OP 114 }; 115 using reverse_iterator = std::reverse_iterator<iterator>; 116 node_list_view(const node_list_type & list)117 /* implicit */ constexpr node_list_view(const node_list_type& list) noexcept 118 : list_(&list) {} 119 120 constexpr node_list_view(const node_list_view&) noexcept = default; 121 constexpr node_list_view& operator=(const node_list_view&) noexcept = default; 122 front()123 constexpr reference front() const { return *list_->front(); } back()124 constexpr reference back() const { return *list_->back(); } 125 constexpr reference operator[](std::size_t pos) const { return at(pos); } begin()126 constexpr iterator begin() const noexcept { return list_->begin(); } end()127 constexpr iterator end() const noexcept { return list_->end(); } size()128 constexpr std::size_t size() const noexcept { return list_->size(); } 129 130 // Create an std::vector with the same contents as this span. copy()131 constexpr std::vector<T*> copy() const noexcept { 132 std::vector<T*> result; 133 for (auto& ptr : *list_) { 134 result.emplace_back(ptr.get()); 135 } 136 return result; 137 } 138 139 // Provided for backwards compatibility with std::vector API. 140 using const_iterator = iterator; 141 using const_reference = reference; 142 using const_pointer = pointer; cbegin()143 constexpr iterator cbegin() const noexcept { return list_->cbegin(); } cend()144 constexpr iterator cend() const noexcept { return list_->cend(); } at(std::size_t pos)145 constexpr reference at(std::size_t pos) const { return *list_->at(pos); } 146 147 private: 148 const node_list_type* list_; 149 }; 150 151 } // namespace compiler 152 } // namespace thrift 153 } // namespace apache 154