1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef RUNTIME_INCLUDE_TAIHE_ARRAY_HPP_ 16 #define RUNTIME_INCLUDE_TAIHE_ARRAY_HPP_ 17 // NOLINTBEGIN 18 19 #include <taihe/array.abi.h> 20 #include <taihe/common.hpp> 21 22 #include <array> 23 #include <cstddef> 24 #include <cstdlib> 25 #include <memory> 26 #include <stdexcept> 27 #include <type_traits> 28 #include <utility> 29 #include <vector> 30 31 namespace taihe { 32 template <typename cpp_owner_t> 33 struct array_view; 34 35 template <typename cpp_owner_t> 36 struct array; 37 38 template <typename cpp_owner_t> 39 struct array_view { 40 using value_type = cpp_owner_t; 41 using size_type = std::size_t; 42 using reference = value_type &; 43 using const_reference = value_type const &; 44 using pointer = value_type *; 45 using const_pointer = value_type const *; 46 using iterator = value_type *; 47 using const_iterator = value_type const *; 48 using reverse_iterator = std::reverse_iterator<iterator>; 49 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 50 array_viewtaihe::array_view51 array_view(pointer data, size_type size) noexcept : m_size(size), m_data(data) {} // main constructor 52 array_viewtaihe::array_view53 array_view() noexcept : m_size(0), m_data(nullptr) {} 54 55 template <typename C, size_type N> array_viewtaihe::array_view56 array_view(C (&value)[N]) noexcept : array_view(value, N) 57 { 58 } 59 60 template <typename C> array_viewtaihe::array_view61 array_view(std::vector<C> &value) noexcept : array_view(value.data(), static_cast<size_type>(value.size())) 62 { 63 } 64 65 template <typename C> array_viewtaihe::array_view66 array_view(std::vector<C> const &value) noexcept : array_view(value.data(), static_cast<size_type>(value.size())) 67 { 68 } 69 70 template <typename C, std::size_t N> array_viewtaihe::array_view71 array_view(std::array<C, N> &value) noexcept : array_view(value.data(), static_cast<size_type>(value.size())) 72 { 73 } 74 75 template <typename C, std::size_t N> array_viewtaihe::array_view76 array_view(std::array<C, N> const &value) noexcept : array_view(value.data(), static_cast<size_type>(value.size())) 77 { 78 } 79 80 template <typename C> array_viewtaihe::array_view81 array_view(array_view<C> const &other) noexcept : array_view(other.data(), other.size()) 82 { 83 } 84 85 template <typename C> array_viewtaihe::array_view86 array_view(array<C> const &other) noexcept : array_view(other.data(), other.size()) 87 { 88 } 89 operator []taihe::array_view90 reference operator[](size_type const pos) const noexcept 91 { 92 TH_ASSERT(pos < size(), "Pos should be less than array's size"); 93 return m_data[pos]; 94 } 95 attaihe::array_view96 reference at(size_type const pos) const 97 { 98 if (size() <= pos) { 99 TH_THROW(std::out_of_range, "Invalid array subscript"); 100 } 101 return m_data[pos]; 102 } 103 fronttaihe::array_view104 reference front() const noexcept 105 { 106 TH_ASSERT(m_size > 0, "Array's size should be greater than 0"); 107 return *m_data; 108 } 109 backtaihe::array_view110 reference back() const noexcept 111 { 112 TH_ASSERT(m_size > 0, "Array's size should be greater than 0"); 113 return m_data[m_size - 1]; 114 } 115 datataihe::array_view116 pointer data() const noexcept 117 { 118 return m_data; 119 } 120 emptytaihe::array_view121 bool empty() const noexcept 122 { 123 return m_size == 0; 124 } 125 sizetaihe::array_view126 size_type size() const noexcept 127 { 128 return m_size; 129 } 130 begintaihe::array_view131 iterator begin() const noexcept 132 { 133 return m_data; 134 } 135 endtaihe::array_view136 iterator end() const noexcept 137 { 138 return m_data + m_size; 139 } 140 rbegintaihe::array_view141 reverse_iterator rbegin() const noexcept 142 { 143 return m_data + m_size; 144 } 145 rendtaihe::array_view146 reverse_iterator rend() const noexcept 147 { 148 return m_data; 149 } 150 cbegintaihe::array_view151 const_iterator cbegin() const noexcept 152 { 153 return m_data; 154 } 155 cendtaihe::array_view156 const_iterator cend() const noexcept 157 { 158 return m_data + m_size; 159 } 160 crbegintaihe::array_view161 const_reverse_iterator crbegin() const noexcept 162 { 163 return m_data + m_size; 164 } 165 crendtaihe::array_view166 const_reverse_iterator crend() const noexcept 167 { 168 return m_data; 169 } 170 operator ==(array_view left,array_view right)171 friend bool operator==(array_view left, array_view right) noexcept 172 { 173 return std::equal(left.begin(), left.end(), right.begin(), right.end()); 174 } 175 operator !=(array_view left,array_view right)176 friend bool operator!=(array_view left, array_view right) noexcept 177 { 178 return !(left == right); 179 } 180 operator <(array_view left,array_view right)181 friend bool operator<(array_view left, array_view right) noexcept 182 { 183 return std::lexicographical_compare(left.begin(), left.end(), right.begin(), right.end()); 184 } 185 operator >(array_view left,array_view right)186 friend bool operator>(array_view left, array_view right) noexcept 187 { 188 return right < left; 189 } 190 operator <=(array_view left,array_view right)191 friend bool operator<=(array_view left, array_view right) noexcept 192 { 193 return !(right < left); 194 } 195 operator >=(array_view left,array_view right)196 friend bool operator>=(array_view left, array_view right) noexcept 197 { 198 return !(left < right); 199 } 200 201 protected: 202 std::size_t m_size; 203 cpp_owner_t *m_data; 204 }; 205 206 struct copy_data_t {}; 207 208 constexpr inline copy_data_t copy_data; 209 210 struct move_data_t {}; 211 212 constexpr inline move_data_t move_data; 213 214 template <typename cpp_owner_t> 215 struct array : public array_view<cpp_owner_t> { 216 using typename array_view<cpp_owner_t>::pointer; 217 using typename array_view<cpp_owner_t>::size_type; 218 arraytaihe::array219 explicit array(pointer data, size_type size) noexcept : array_view<cpp_owner_t>(data, size) {} // main constructor 220 221 template <typename Iterator> arraytaihe::array222 array(copy_data_t, Iterator begin, size_type size) noexcept 223 : array_view<cpp_owner_t>(reinterpret_cast<cpp_owner_t *>(malloc(size * sizeof(cpp_owner_t))), size) 224 { 225 std::uninitialized_copy_n(begin, size, this->m_data); 226 } 227 228 template <typename Iterator> arraytaihe::array229 array(move_data_t, Iterator begin, size_type size) noexcept 230 : array_view<cpp_owner_t>(reinterpret_cast<cpp_owner_t *>(malloc(size * sizeof(cpp_owner_t))), size) 231 { 232 std::uninitialized_move_n(begin, size, this->m_data); 233 } 234 arraytaihe::array235 explicit array(size_type size) : array(reinterpret_cast<cpp_owner_t *>(malloc(size * sizeof(cpp_owner_t))), size) 236 { 237 std::uninitialized_default_construct_n(this->m_data, size); 238 } 239 arraytaihe::array240 explicit array(size_type size, cpp_owner_t const &value) 241 : array(reinterpret_cast<cpp_owner_t *>(malloc(size * sizeof(cpp_owner_t))), size) 242 { 243 std::uninitialized_fill_n(this->m_data, size, value); 244 } 245 maketaihe::array246 static array make(size_type size) 247 { 248 return array(size); 249 } 250 maketaihe::array251 static array make(size_type size, cpp_owner_t const &value) 252 { 253 return array(size, value); 254 } 255 arraytaihe::array256 array(std::initializer_list<cpp_owner_t> value) noexcept : array(copy_data, value.begin(), value.size()) {} 257 arraytaihe::array258 array(array_view<cpp_owner_t> const &other) : array(copy_data, other.data(), other.size()) {} 259 arraytaihe::array260 array(array<cpp_owner_t> const &other) : array(copy_data, other.data(), other.size()) {} 261 arraytaihe::array262 array(array<cpp_owner_t> &&other) : array(std::exchange(other.m_data, nullptr), std::exchange(other.m_size, 0)) {} 263 operator =taihe::array264 array &operator=(array other) 265 { 266 std::swap(this->m_size, other.m_size); 267 std::swap(this->m_data, other.m_data); 268 return *this; 269 } 270 ~arraytaihe::array271 ~array() 272 { 273 if (this->m_data) { 274 std::destroy_n(this->m_data, this->m_size); 275 free(this->m_data); 276 this->m_size = 0; 277 this->m_data = nullptr; 278 } 279 } 280 }; 281 282 template <typename cpp_owner_t> 283 struct as_abi<array_view<cpp_owner_t>> { 284 using type = TArray; 285 }; 286 287 template <typename cpp_owner_t> 288 struct as_abi<array<cpp_owner_t>> { 289 using type = TArray; 290 }; 291 292 template <typename cpp_owner_t> 293 struct as_param<array<cpp_owner_t>> { 294 using type = array_view<cpp_owner_t>; 295 }; 296 } // namespace taihe 297 298 template <typename cpp_owner_t> 299 struct std::hash<taihe::array<cpp_owner_t>> { operator ()std::hash300 std::size_t operator()(taihe::array_view<cpp_owner_t> val) const 301 { 302 std::size_t seed = 0; 303 static constexpr std::size_t GOLDEN_RATIO_CONSTANT = 0x9e3779b9; 304 static constexpr std::size_t LEFT_SHIFT_BITS = 6; 305 static constexpr std::size_t RIGHT_SHIFT_BITS = 2; 306 for (std::size_t i = 0; i < val.size(); i++) { 307 seed ^= (seed << LEFT_SHIFT_BITS) + (seed >> RIGHT_SHIFT_BITS) + GOLDEN_RATIO_CONSTANT + 308 std::hash<cpp_owner_t>()(val[i]); 309 } 310 return seed; 311 } 312 }; 313 // NOLINTEND 314 #endif // RUNTIME_INCLUDE_TAIHE_ARRAY_HPP_