yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
43d0c2100
master
1/* 2This is an implementation of C++20's std::span 3http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf 4*/ 5 6// Copyright Tristan Brindle 2018. 7// Distributed under the Boost Software License, Version 1.0. 8// (See accompanying file ../../LICENSE_1_0.txt or copy at 9// https://www.boost.org/LICENSE_1_0.txt) 10 11#pragma once 12 13#include <array> 14#include <cstddef> 15#include <cstdint> 16#include <type_traits> 17 18#ifndef TCB_SPAN_NO_EXCEPTIONS 19// Attempt to discover whether we're being compiled with exception support 20#if !(defined(__cpp_exceptions )|| defined(__EXCEPTIONS )|| defined(_CPPUNWIND )) 21#define TCB_SPAN_NO_EXCEPTIONS 22#endif 23#endif 24 25#ifndef TCB_SPAN_NO_EXCEPTIONS 26#include <cstdio> 27#include <stdexcept> 28#endif 29 30// Various feature test macros 31 32#ifndef TCB_SPAN_NAMESPACE_NAME 33#define TCB_SPAN_NAMESPACE_NAME rhi 34#endif 35 36#if __cplusplus >=201703L || (defined(_MSVC_LANG )&& _MSVC_LANG >=201703L ) 37#define TCB_SPAN_HAVE_CPP17 38#endif 39 40#if __cplusplus >=201402L || (defined(_MSVC_LANG )&& _MSVC_LANG >=201402L ) 41#define TCB_SPAN_HAVE_CPP14 42#endif 43 44namespace TCB_SPAN_NAMESPACE_NAME 45{ 46 47// Establish default contract checking behavior 48#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION )&& \ 49 !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION )&& !defined(TCB_SPAN_NO_CONTRACT_CHECKING ) 50#if defined(NDEBUG )|| !defined(TCB_SPAN_HAVE_CPP14 ) 51#define TCB_SPAN_NO_CONTRACT_CHECKING 52#else 53#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION 54#endif 55#endif 56 57#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION ) 58struct contract_violation_error :std ::logic_error 59{ 60explicit contract_violation_error (const char * msg ) 61 :std ::logic_error (msg ) 62 { 63 } 64}; 65 66inline void contract_violation (const char * msg ) 67{ 68throw contract_violation_error (msg ); 69} 70 71#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION ) 72[[noreturn ]]inline void contract_violation (const char * /*unused*/ ) 73{ 74std ::terminate (); 75} 76#endif 77 78#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING ) 79#define TCB_SPAN_STRINGIFY (cond ) #cond 80#define TCB_SPAN_EXPECT (cond ) \ 81 cond ? (void)0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond)) 82#else 83#define TCB_SPAN_EXPECT (cond ) 84#endif 85 86#if defined(TCB_SPAN_HAVE_CPP17 )|| defined(__cpp_inline_variables ) 87#define TCB_SPAN_INLINE_VAR inline 88#else 89#define TCB_SPAN_INLINE_VAR 90#endif 91 92#if defined(TCB_SPAN_HAVE_CPP14 )|| (defined(__cpp_constexpr )&& __cpp_constexpr >=201304 ) 93#define TCB_SPAN_HAVE_CPP14_CONSTEXPR 94#endif 95 96#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR ) 97#define TCB_SPAN_CONSTEXPR14 constexpr 98#else 99#define TCB_SPAN_CONSTEXPR14 100#endif 101 102#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR )&& (!defined(_MSC_VER )|| _MSC_VER > 1900 ) 103#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr 104#else 105#define TCB_SPAN_CONSTEXPR_ASSIGN 106#endif 107 108#if defined(TCB_SPAN_NO_CONTRACT_CHECKING ) 109#define TCB_SPAN_CONSTEXPR11 constexpr 110#else 111#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14 112#endif 113 114#if defined(TCB_SPAN_HAVE_CPP17 )|| defined(__cpp_deduction_guides ) 115#define TCB_SPAN_HAVE_DEDUCTION_GUIDES 116#endif 117 118#if defined(TCB_SPAN_HAVE_CPP17 )|| defined(__cpp_lib_byte ) 119#define TCB_SPAN_HAVE_STD_BYTE 120#endif 121 122#if defined(TCB_SPAN_HAVE_CPP17 )|| defined(__cpp_lib_array_constexpr ) 123#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC 124#endif 125 126#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC ) 127#define TCB_SPAN_ARRAY_CONSTEXPR constexpr 128#else 129#define TCB_SPAN_ARRAY_CONSTEXPR 130#endif 131 132#ifdef TCB_SPAN_HAVE_STD_BYTE 133using slang_byte = std ::byte ; 134#else 135using slang_byte = unsigned char ; 136#endif 137 138#if defined(TCB_SPAN_HAVE_CPP17 ) 139#define TCB_SPAN_NODISCARD [[nodiscard]] 140#else 141#define TCB_SPAN_NODISCARD 142#endif 143 144TCB_SPAN_INLINE_VAR constexprstd ::size_t dynamic_extent = SIZE_MAX ; 145 146template < typename ElementType ,std ::size_t Extent = dynamic_extent > 147class span ; 148 149namespace detail 150{ 151 152template < typename E ,std ::size_t S > 153struct span_storage 154{ 155 constexprspan_storage () noexcept = default ; 156 157constexpr span_storage (E * p_ptr , std ::size_t /*unused*/ ) noexcept 158: ptr (p_ptr) 159{ 160} 161 162E * ptr = nullptr ; 163static constexpr std::size_t size = S ; 164}; 165 166template < typename E > 167struct span_storage < E , dynamic_extent > 168{ 169constexpr span_storage () noexcept = default ; 170 171constexpr span_storage (E * p_ptr , std ::size_t p_size ) noexcept 172: ptr (p_ptr), size (p_size) 173{ 174} 175 176E * ptr = nullptr ; 177std ::size_t size = 0 ; 178}; 179 180// Reimplementation of C++17 std::size() and std::data() 181#if defined( TCB_SPAN_HAVE_CPP17 ) || defined( __cpp_lib_nonmember_container_access ) 182using std :: data ; 183using std :: size ; 184#else 185template < class C > 186constexpr auto size ( const C & c ) -> decltype (c. size ()) 187{ 188return c . size (); 189} 190 191template < class T , std ::size_t N > 192constexpr std ::size_t size ( const T ( & )[ N ]) noexcept 193{ 194return N ; 195} 196 197template < class C > 198constexpr auto data ( C & c ) -> decltype ( c . data ()) 199{ 200return c . data (); 201} 202 203template < class C > 204constexpr auto data ( const C & c ) -> decltype (c. data ()) 205{ 206return c . data (); 207} 208 209template < class T , std ::size_t N > 210constexpr T * data ( T ( & array )[ N ]) noexcept 211{ 212return array ; 213} 214 215template < class E > 216constexpr const E * data (std:: initializer_list < E > il ) noexcept 217{ 218return il . begin (); 219} 220#endif // TCB_SPAN_HAVE_CPP17 221 222#if defined( TCB_SPAN_HAVE_CPP17 ) || defined( __cpp_lib_void_t ) 223using std :: void_t ; 224#else 225template < typename ... > 226using void_t = void ; 227#endif 228 229template < typename T > 230using uncvref_t = typename std :: remove_cv < typename std :: remove_reference < T > :: type > :: type ; 231 232template < typename > 233struct is_span : std :: false_type 234{ 235}; 236 237template < typename T , std ::size_t S > 238struct is_span < span < T , S >> : std :: true_type 239{ 240}; 241 242template < typename > 243struct is_std_array : std :: false_type 244{ 245}; 246 247template < typename T , std ::size_t N > 248struct is_std_array < std :: array < T , N >> : std :: true_type 249{ 250}; 251 252template < typename , typename = void > 253struct has_size_and_data : std :: false_type 254{ 255}; 256 257template < typename T > 258struct has_size_and_data < 259T , 260void_t < decltype ( detail :: size ( std :: declval < T > ( ))), decltype ( detail :: data ( std ::declval < T > ()))>> 261: std ::true_type 262{ 263}; 264 265template < typename C , typename U = uncvref_t < C >> 266struct is_container 267{ 268static constexpr bool value = !is_span < U > ::value && !is_std_array < U > ::value && 269!std::is_array < U > ::value && has_size_and_data < C > ::value; 270}; 271 272template < typename T > 273using remove_pointer_t = typename std::remove_pointer < T > ::type ; 274 275template < typename , typename , typename = void > 276struct is_container_element_type_compatible : std :: false_type 277{ 278}; 279 280template < typename T , typename E > 281struct is_container_element_type_compatible < 282T , 283E , 284typename std :: enable_if < 285! std :: is_same < 286typename std :: remove_cv < decltype ( detail :: data ( std :: declval < T >( ))) > ::type, 287void > ::value && 288std::is_convertible < 289remove_pointer_t < decltype ( detail :: data ( std ::declval < T > ())) > ( * )[], 290E ( * )[] > ::value > ::type > : std::true_type 291{ 292}; 293 294template < typename, typename = size_t > 295struct is_complete : std ::false_type 296{ 297}; 298 299template < typename T > 300struct is_complete < T , decltype ( sizeof ( T )) > : std::true_type 301{ 302}; 303 304} // namespace detail 305 306template < typename ElementType, std:: size_t Extent > 307class span 308{ 309static_assert ( 310std ::is_object < ElementType > ::value, 311"A span's ElementType must be an object type (not a " 312"reference type or void)" ); 313static_assert ( 314detail ::is_complete < ElementType > ::value, 315"A span's ElementType must be a complete type (not a forward " 316"declaration)" ); 317static_assert ( 318!std::is_abstract < ElementType > ::value, 319"A span's ElementType cannot be an abstract class type" ); 320 321using storage_type = detail::span_storage < ElementType, Extent > ; 322 323public : 324// constants and types 325using element_type = ElementType; 326using value_type = typename std ::remove_cv < ElementType > ::type; 327using size_type = std:: size_t ; 328using difference_type = std:: ptrdiff_t ; 329using pointer = element_type * ; 330using const_pointer = const element_type * ; 331using reference = element_type & ; 332using const_reference = const element_type & ; 333using iterator = pointer; 334using reverse_iterator = std::reverse_iterator < iterator > ; 335 336static constexpr size_type extent = Extent; 337 338// [span.cons], span constructors, copy, assignment, and destructor 339template < 340std:: size_t E = Extent, 341typename std::enable_if < ( E == dynamic_extent || E <= 0 ), int > ::type = 0 > 342constexpr span () noexcept 343{ 344} 345 346TCB_SPAN_CONSTEXPR11 span ( pointer ptr, size_type count) 347: storage_ (ptr, count) 348{ 349TCB_SPAN_EXPECT (extent == dynamic_extent || count == extent); 350} 351 352TCB_SPAN_CONSTEXPR11 span ( pointer first_elem, pointer last_elem) 353: storage_ (first_elem, last_elem - first_elem) 354{ 355TCB_SPAN_EXPECT ( 356extent == dynamic_extent || 357last_elem - first_elem == static_cast < std:: ptrdiff_t > (extent)); 358} 359 360template < 361std:: size_t N , 362std:: size_t E = Extent, 363typename std::enable_if < 364( E == dynamic_extent || N == E ) && 365detail::is_container_element_type_compatible < element_type ( & )[ N ], ElementType > :: 366value, 367int > ::type = 0 > 368constexpr span ( element_type ( & arr)[ N ]) noexcept 369: storage_ (arr, N ) 370{ 371} 372 373template < 374typename T , 375std:: size_t N , 376std:: size_t E = Extent, 377typename std::enable_if < 378( E == dynamic_extent || N == E ) && 379detail::is_container_element_type_compatible < std::array < T , N >& , ElementType > ::value, 380int > ::type = 0 > 381TCB_SPAN_ARRAY_CONSTEXPR span ( std ::array < T , N >& arr) noexcept 382: storage_ (arr. data (), N ) 383{ 384} 385 386template < 387typename T , 388std:: size_t N , 389std:: size_t E = Extent, 390typename std::enable_if < 391( E == dynamic_extent || N == E ) && 392detail::is_container_element_type_compatible < const std::array < T , N >& , ElementType > :: 393value, 394int > ::type = 0 > 395TCB_SPAN_ARRAY_CONSTEXPR span ( const std ::array < T , N >& arr) noexcept 396: storage_ (arr. data (), N ) 397{ 398} 399 400template < 401typename Container, 402std:: size_t E = Extent, 403typename std::enable_if < 404E == dynamic_extent && detail::is_container < Container > ::value && 405detail::is_container_element_type_compatible < Container & , ElementType > ::value, 406int > ::type = 0 > 407constexpr span (Container & cont) 408: storage_ (detail:: data (cont), detail:: size (cont)) 409{ 410} 411 412template < 413typename Container, 414std:: size_t E = Extent, 415typename std::enable_if < 416E == dynamic_extent && detail::is_container < Container > ::value && 417detail::is_container_element_type_compatible < const Container & , ElementType > ::value, 418int > ::type = 0 > 419constexpr span( const Container & cont) 420: storage_ ( detail :: data ( cont ), detail :: size ( cont )) 421{ 422} 423 424constexpr span( const span & other) noexcept = default; 425 426template < 427typename OtherElementType, 428std:: size_t OtherExtent, 429typename std::enable_if < 430( Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) && 431std::is_convertible < OtherElementType ( * )[], ElementType ( * )[] > ::value, 432int > ::type = 0 > 433constexpr span( const span < OtherElementType, OtherExtent >& other) noexcept 434: storage_ (other. data (), other. size ()) 435{ 436} 437 438~ span () noexcept = default; 439 440TCB_SPAN_CONSTEXPR_ASSIGN span & operator = ( const span & other) noexcept = default; 441 442// [span.sub], span subviews 443template < std:: size_t Count > 444TCB_SPAN_CONSTEXPR11 span < element_type, Count > first () const 445{ 446TCB_SPAN_EXPECT (Count <= size ()); 447return { data (), Count}; 448} 449 450template < std:: size_t Count > 451TCB_SPAN_CONSTEXPR11 span < element_type, Count > last () const 452{ 453TCB_SPAN_EXPECT (Count <= size ()); 454return { data () + ( size () - Count), Count}; 455} 456 457template < std:: size_t Offset, std:: size_t Count = dynamic_extent > 458using subspan_return_t = span < 459ElementType, 460Count != dynamic_extent ? Count 461: (Extent != dynamic_extent ? Extent - Offset : dynamic_extent) > ; 462 463template < std:: size_t Offset, std:: size_t Count = dynamic_extent > 464TCB_SPAN_CONSTEXPR11 subspan_return_t < Offset, Count > subspan () const 465{ 466TCB_SPAN_EXPECT (Offset <= size () && (Count == dynamic_extent || Offset + Count <= size ())); 467return { data () + Offset, Count != dynamic_extent ? Count : size () - Offset}; 468} 469 470TCB_SPAN_CONSTEXPR11 span < element_type, dynamic_extent > first ( size_type count) const 471{ 472TCB_SPAN_EXPECT ( count <= size ()); 473return { data (), count}; 474} 475 476TCB_SPAN_CONSTEXPR11 span < element_type, dynamic_extent > last ( size_type count) const 477{ 478TCB_SPAN_EXPECT ( count <= size ()); 479return { data () + ( size () - count), count}; 480} 481 482TCB_SPAN_CONSTEXPR11 span < element_type, dynamic_extent > subspan ( 483size_type offset, 484size_type count = dynamic_extent) const 485{ 486TCB_SPAN_EXPECT (offset <= size () && (count == dynamic_extent || offset + count <= size ())); 487return { data () + offset, count == dynamic_extent ? size () - offset : count}; 488} 489 490// [span.obs], span observers 491constexpr size_type size () const noexcept { return storage_. size ; } 492 493constexpr size_type size_bytes () const noexcept { return size () * sizeof ( element_type ); } 494 495TCB_SPAN_NODISCARD constexpr bool empty () const noexcept { return size () == 0 ; } 496 497// [span.elem], span element access 498TCB_SPAN_CONSTEXPR11 reference operator[]( size_type idx) const 499{ 500TCB_SPAN_EXPECT (idx < size ()); 501return * ( data () + idx); 502} 503 504TCB_SPAN_CONSTEXPR11 reference front () const 505{ 506TCB_SPAN_EXPECT (! empty ()); 507return * data (); 508} 509 510TCB_SPAN_CONSTEXPR11 reference back () const 511{ 512TCB_SPAN_EXPECT (! empty ()); 513return * ( data () + ( size () - 1 )); 514} 515 516constexpr pointer data () const noexcept { return storage_. ptr ; } 517 518// [span.iterators], span iterator support 519constexpr iterator begin () const noexcept { return data (); } 520 521constexpr iterator end () const noexcept { return data () + size (); } 522 523TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin () const noexcept 524{ 525return reverse_iterator ( end ()); 526} 527 528TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend () const noexcept 529{ 530return reverse_iterator ( begin ()); 531} 532 533private : 534storage_type storage_{}; 535}; 536 537#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES 538 539/* Deduction Guides */ 540template < class T , size_t N > 541span ( T ( & )[ N ]) -> span < T , N > ; 542 543template < class T , size_t N > 544span (std::array < T , N >& ) -> span < T , N > ; 545 546template < class T , size_t N > 547span (const std::array < T , N >& ) -> span < const T , N > ; 548 549template < class Container > 550span (Container & ) -> span < 551typename std ::remove_reference < decltype ( * detail:: data (std::declval < Container &> ())) > ::type > ; 552 553template < class Container > 554span (const Container & ) -> span < const typename Container::value_type > ; 555 556#endif // TCB_HAVE_DEDUCTION_GUIDES 557 558template < typename ElementType, std:: size_t Extent > 559constexpr span < ElementType, Extent > make_span ( span < ElementType, Extent > s) noexcept 560{ 561return s; 562} 563 564template < typename T , std:: size_t N > 565constexpr span < T , N > make_span ( T ( & arr )[ N ]) noexcept 566{ 567return {arr}; 568} 569 570template < typename T , std:: size_t N > 571TCB_SPAN_ARRAY_CONSTEXPR span < T , N > make_span (std::array < T , N >& arr) noexcept 572{ 573return {arr}; 574} 575 576template < typename T , std:: size_t N > 577TCB_SPAN_ARRAY_CONSTEXPR span < const T , N > make_span (const std::array < T , N >& arr) noexcept 578{ 579return {arr}; 580} 581 582template < typename Container > 583constexpr span < 584typename std::remove_reference < decltype ( * detail:: data (std::declval < Container &> ())) > ::type > 585make_span (Container & cont) 586{ 587return {cont}; 588} 589 590template < typename Container > 591constexpr span < const typename Container::value_type > make_span (const Container & cont) 592{ 593return {cont}; 594} 595 596template < typename ElementType, std:: size_t Extent > 597span < const slang_byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof (ElementType) * Extent) > 598as_bytes (span < ElementType, Extent > s) noexcept 599{ 600return {reinterpret_cast < const slang_byte *> (s. data ()), s. size_bytes ()}; 601} 602 603template < 604class ElementType, 605size_t Extent, 606typename std::enable_if < !std::is_const < ElementType > ::value, int > ::type = 0 > 607span < slang_byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof (ElementType) * Extent) > 608as_writable_bytes (span < ElementType, Extent > s) noexcept 609{ 610return {reinterpret_cast < slang_byte *> (s. data ()), s. size_bytes ()}; 611} 612 613template < std:: size_t N , typename E , std:: size_t S > 614constexpr auto get( span < E , S > s) -> decltype ( s [ N ]) 615{ 616return s[ N ]; 617} 618 619} // namespace TCB_SPAN_NAMESPACE_NAME 620 621namespace std 622{ 623 624template < typename ElementType, size_t Extent > 625class tuple_size < TCB_SPAN_NAMESPACE_NAME ::span < ElementType, Extent>> 626: public integral_constant < size_t, Extent > 627{ 628}; 629 630template < typename ElementType > 631class tuple_size < 632TCB_SPAN_NAMESPACE_NAME ::span < ElementType, TCB_SPAN_NAMESPACE_NAME ::dynamic_extent>>; // not 633// defined 634 635template < size_t I , typename ElementType, size_t Extent > 636class tuple_element < I , TCB_SPAN_NAMESPACE_NAME ::span < ElementType, Extent>> 637{ 638public : 639static_assert (Extent != TCB_SPAN_NAMESPACE_NAME ::dynamic_extent && I < Extent, "" ); 640using type = ElementType; 641}; 642 643} // end namespace std