yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
4d517794e
master
1#include "slang-rtti-util.h" 2 3namespace Slang 4{ 5 6/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RttiTypeFuncs Impls 7* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 8 9struct ListFuncs 10{ 11static void ctorArray ( 12RttiTypeFuncsMap * typeMap , 13const RttiInfo * rttiInfo , 14void * inDst , 15Index count ) 16 { 17SLANG_UNUSED (typeMap ); 18SLANG_UNUSED (rttiInfo ); 19SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 20 21// We don't care about the element type, as we can just initialize them all as List<Byte> 22// const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo); 23typedef List < Byte > Type ; 24 25Type * dst = (Type * )inDst ; 26 27for (Index i = 0 ;i < count ;++ i ) 28 { 29new (dst + i )Type ; 30 } 31 } 32 33static void copyArray ( 34RttiTypeFuncsMap * typeMap , 35const RttiInfo * rttiInfo , 36void * inDst , 37const void * inSrc , 38Index count ) 39 { 40SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 41const ListRttiInfo * listRttiInfo = static_cast < const ListRttiInfo *> (rttiInfo ); 42const auto elementType = listRttiInfo -> m_elementType ; 43 44// We need to get the type funcs 45auto typeFuncs = typeMap -> getFuncsForType (elementType ); 46SLANG_ASSERT (typeFuncs .isValid ()); 47 48// We need a type that we can get information from the list from - List<Byte> gives us the 49// functions we need. 50typedef List < Byte > Type ; 51 52Type * dst = (Type * )inDst ; 53const Type * src = (const Type * )inSrc ; 54 55for (Index i = 0 ;i < count ;++ i ) 56 { 57auto & dstList = dst [i ]; 58auto & srcList = src [i ]; 59 60const Index srcCount = srcList .getCount (); 61 62if (srcCount > dstList .getCount ()) 63 { 64// Allocate new memory 65const Index dstCapacity = dstList .getCapacity (); 66void * oldBuffer = dstList .detachBuffer (); 67 68void * newBuffer = ::malloc (count * elementType -> m_size ); 69// Initialize it all first 70typeFuncs .ctorArray (typeMap ,elementType ,newBuffer ,count ); 71typeFuncs .copyArray (typeMap ,elementType ,newBuffer ,oldBuffer ,count ); 72 73// Attach the new buffer 74dstList .attachBuffer ((Byte * )newBuffer ,count ,count ); 75 76// Free the old buffer 77if (oldBuffer ) 78 { 79typeFuncs .dtorArray (typeMap ,elementType ,oldBuffer ,dstCapacity ); 80 81 ::free (oldBuffer ); 82 } 83 } 84else 85 { 86typeFuncs .copyArray ( 87typeMap , 88elementType , 89dstList .getBuffer (), 90srcList .getBuffer (), 91srcCount ); 92dstList .unsafeShrinkToCount (srcCount ); 93 } 94 } 95 } 96 97static void dtorArray ( 98RttiTypeFuncsMap * typeMap , 99const RttiInfo * rttiInfo , 100void * inDst , 101Index count ) 102 { 103SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 104const ListRttiInfo * listRttiInfo = static_cast < const ListRttiInfo *> (rttiInfo ); 105 106const auto elementType = listRttiInfo -> m_elementType ; 107 108// We need to get the type funcs 109auto typeFuncs = typeMap -> getFuncsForType (elementType ); 110SLANG_ASSERT (typeFuncs .isValid ()); 111 112typedef List < Byte > Type ; 113Type * dst = (Type * )inDst ; 114 115for (Index i = 0 ;i < count ;++ i ) 116 { 117auto & dstList = dst [i ]; 118 119const Index capacity = dstList .getCapacity (); 120Byte * buffer = dstList .detachBuffer (); 121 122if (buffer ) 123 { 124typeFuncs .dtorArray (typeMap ,elementType ,buffer ,capacity ); 125 ::free (buffer ); 126 } 127 } 128 } 129 130static RttiTypeFuncs getFuncs () 131 { 132RttiTypeFuncs funcs ; 133funcs .copyArray = & copyArray ; 134funcs .dtorArray = & dtorArray ; 135funcs .ctorArray = & ctorArray ; 136return funcs ; 137 } 138}; 139 140struct StructFuncs 141{ 142static void ctorArray ( 143RttiTypeFuncsMap * typeMap , 144const RttiInfo * rttiInfo , 145void * inDst , 146Index count ) 147 { 148SLANG_UNUSED (typeMap ); 149SLANG_UNUSED (rttiInfo ); 150SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 151 152// We don't care about the element type, as we can just initialize them all as List<Byte> 153// const ListRttiInfo* listRttiInfo = static_cast<const ListRttiInfo*>(rttiInfo); 154typedef List < Byte > Type ; 155 156Type * dst = (Type * )inDst ; 157 158for (Index i = 0 ;i < count ;++ i ) 159 { 160new (dst + i )Type ; 161 } 162 } 163static void copyArray ( 164RttiTypeFuncsMap * typeMap , 165const RttiInfo * rttiInfo , 166void * inDst , 167const void * inSrc , 168Index count ) 169 { 170SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 171const ListRttiInfo * listRttiInfo = static_cast < const ListRttiInfo *> (rttiInfo ); 172const auto elementType = listRttiInfo -> m_elementType ; 173 174// We need to get the type funcs 175auto typeFuncs = typeMap -> getFuncsForType (elementType ); 176SLANG_ASSERT (typeFuncs .isValid ()); 177 178// We need a type that we can get information from the list from - List<Byte> gives us the 179// functions we need. 180typedef List < Byte > Type ; 181 182Type * dst = (Type * )inDst ; 183const Type * src = (const Type * )inSrc ; 184 185for (Index i = 0 ;i < count ;++ i ) 186 { 187auto & dstList = dst [i ]; 188auto & srcList = src [i ]; 189 190const Index srcCount = srcList .getCount (); 191 192if (srcCount > dstList .getCount ()) 193 { 194// Allocate new memory 195const Index dstCapacity = dstList .getCapacity (); 196void * oldBuffer = dstList .detachBuffer (); 197 198void * newBuffer = ::malloc (count * elementType -> m_size ); 199// Initialize it all first 200typeFuncs .ctorArray (typeMap ,elementType ,newBuffer ,count ); 201typeFuncs .copyArray (typeMap ,elementType ,newBuffer ,oldBuffer ,count ); 202 203// Attach the new buffer 204dstList .attachBuffer ((Byte * )newBuffer ,count ,count ); 205 206// Free the old buffer 207if (oldBuffer ) 208 { 209typeFuncs .dtorArray (typeMap ,elementType ,oldBuffer ,dstCapacity ); 210 211 ::free (oldBuffer ); 212 } 213 } 214else 215 { 216typeFuncs .copyArray ( 217typeMap , 218elementType , 219dstList .getBuffer (), 220srcList .getBuffer (), 221srcCount ); 222dstList .unsafeShrinkToCount (srcCount ); 223 } 224 } 225 } 226 227static void dtorArray ( 228RttiTypeFuncsMap * typeMap , 229const RttiInfo * rttiInfo , 230void * inDst , 231Index count ) 232 { 233SLANG_ASSERT (rttiInfo -> m_kind == RttiInfo ::Kind ::List ); 234const ListRttiInfo * listRttiInfo = static_cast < const ListRttiInfo *> (rttiInfo ); 235 236const auto elementType = listRttiInfo -> m_elementType ; 237 238// We need to get the type funcs 239auto typeFuncs = typeMap -> getFuncsForType (elementType ); 240SLANG_ASSERT (typeFuncs .isValid ()); 241 242typedef List < Byte > Type ; 243Type * dst = (Type * )inDst ; 244 245for (Index i = 0 ;i < count ;++ i ) 246 { 247auto & dstList = dst [i ]; 248 249const Index capacity = dstList .getCapacity (); 250Byte * buffer = dstList .detachBuffer (); 251 252if (buffer ) 253 { 254typeFuncs .dtorArray (typeMap ,elementType ,buffer ,capacity ); 255 ::free (buffer ); 256 } 257 } 258 } 259 260static RttiTypeFuncs getFuncs () 261 { 262RttiTypeFuncs funcs ; 263funcs .copyArray = & copyArray ; 264funcs .dtorArray = & dtorArray ; 265funcs .ctorArray = & ctorArray ; 266return funcs ; 267 } 268}; 269 270struct StructArrayFuncs 271{ 272static void ctorArray ( 273RttiTypeFuncsMap * typeMap , 274const RttiInfo * rttiInfo , 275void * inDst , 276Index count ) 277 { 278return RttiUtil ::ctorArray (typeMap ,rttiInfo ,inDst ,rttiInfo -> m_size ,count ); 279 } 280 281static void copyArray ( 282RttiTypeFuncsMap * typeMap , 283const RttiInfo * rttiInfo , 284void * inDst , 285const void * inSrc , 286Index count ) 287 { 288return RttiUtil ::copyArray (typeMap ,rttiInfo ,inDst ,inSrc ,rttiInfo -> m_size ,count ); 289 } 290 291static void dtorArray ( 292RttiTypeFuncsMap * typeMap , 293const RttiInfo * rttiInfo , 294void * inDst , 295Index count ) 296 { 297return RttiUtil ::dtorArray (typeMap ,rttiInfo ,inDst ,rttiInfo -> m_size ,count ); 298 } 299 300static RttiTypeFuncs getFuncs () 301 { 302RttiTypeFuncs funcs ; 303funcs .copyArray = copyArray ; 304funcs .dtorArray = dtorArray ; 305funcs .ctorArray = ctorArray ; 306return funcs ; 307 } 308}; 309 310/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RttiUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 311 312RttiTypeFuncs RttiUtil ::getDefaultTypeFuncs (const RttiInfo * rttiInfo ) 313{ 314if (rttiInfo -> isBuiltIn ()) 315 { 316switch (rttiInfo -> m_size ) 317 { 318case 1 : 319return GetRttiTypeFuncsForZeroPod < uint8_t > ::getFuncs (); 320case 2 : 321return GetRttiTypeFuncsForZeroPod < uint16_t > ::getFuncs (); 322case 4 : 323return GetRttiTypeFuncsForZeroPod < uint32_t > ::getFuncs (); 324case 8 : 325return GetRttiTypeFuncsForZeroPod < uint64_t > ::getFuncs (); 326 } 327return RttiTypeFuncs ::makeEmpty (); 328 } 329 330switch (rttiInfo -> m_kind ) 331 { 332case RttiInfo ::Kind ::String : 333return GetRttiTypeFuncs < String > ::getFuncs (); 334case RttiInfo ::Kind ::UnownedStringSlice : 335return GetRttiTypeFuncs < UnownedStringSlice > ::getFuncs (); 336case RttiInfo ::Kind ::List : 337return ListFuncs ::getFuncs (); 338case RttiInfo ::Kind ::Struct : 339case RttiInfo ::Kind ::Optional : 340return StructArrayFuncs ::getFuncs (); 341default : 342break ; 343 } 344 345return RttiTypeFuncs ::makeEmpty (); 346} 347 348/* static */ SlangResult RttiUtil ::setInt (int64_t value ,const RttiInfo * rttiInfo ,void * dst ) 349{ 350SLANG_ASSERT (rttiInfo -> isIntegral ()); 351 352// We could check ranges are appropriate, but for now we just write. 353// Passing in rttiInfo allows for other more complex types to be econverted 354switch (rttiInfo -> m_kind ) 355 { 356case RttiInfo ::Kind ::I32 : 357* (int32_t * )dst = int32_t (value ); 358break ; 359case RttiInfo ::Kind ::U32 : 360* (uint32_t * )dst = uint32_t (value ); 361break ; 362case RttiInfo ::Kind ::I64 : 363* (int64_t * )dst = int64_t (value ); 364break ; 365case RttiInfo ::Kind ::U64 : 366* (uint64_t * )dst = uint64_t (value ); 367break ; 368default : 369return SLANG_FAIL ; 370 } 371return SLANG_OK ; 372} 373 374/* static */ int64_t RttiUtil ::getInt64 (const RttiInfo * rttiInfo ,const void * src ) 375{ 376SLANG_ASSERT (rttiInfo -> isIntegral ()); 377 378switch (rttiInfo -> m_kind ) 379 { 380case RttiInfo ::Kind ::I32 : 381return * (const int32_t * )src ; 382case RttiInfo ::Kind ::U32 : 383return * (const uint32_t * )src ; 384case RttiInfo ::Kind ::I64 : 385return * (const int64_t * )src ; 386case RttiInfo ::Kind ::U64 : 387return * (const uint64_t * )src ; 388default : 389break ; 390 } 391 392SLANG_ASSERT (!"Not integral!" ); 393return -1 ; 394} 395 396/* static */ double RttiUtil ::asDouble (const RttiInfo * rttiInfo ,const void * src ) 397{ 398if (rttiInfo -> isIntegral ()) 399 { 400return (double )getInt64 (rttiInfo ,src ); 401 } 402else if (rttiInfo -> isFloat ()) 403 { 404switch (rttiInfo -> m_kind ) 405 { 406case RttiInfo ::Kind ::F32 : 407return * (const float * )src ; 408case RttiInfo ::Kind ::F64 : 409return * (const double * )src ; 410default : 411break ; 412 } 413 } 414 415SLANG_ASSERT (!"Cannot convert to float" ); 416return 0.0 ; 417} 418 419/* static */ SlangResult RttiUtil ::setFromDouble (double v ,const RttiInfo * rttiInfo ,void * dst ) 420{ 421if (rttiInfo -> isIntegral ()) 422 { 423return setInt (int64_t (v ),rttiInfo ,dst ); 424 } 425else if (rttiInfo -> isFloat ()) 426 { 427switch (rttiInfo -> m_kind ) 428 { 429case RttiInfo ::Kind ::F32 : 430* (float * )dst = float (v ); 431return SLANG_OK ; 432case RttiInfo ::Kind ::F64 : 433* (double * )dst = v ; 434return SLANG_OK ; 435default : 436break ; 437 } 438 } 439 440return SLANG_FAIL ; 441} 442 443/* static */ bool RttiUtil ::asBool (const RttiInfo * rttiInfo ,const void * src ) 444{ 445if (rttiInfo -> m_kind == RttiInfo ::Kind ::Bool ) 446 { 447return * (const bool * )src ; 448 } 449 450if (rttiInfo -> isIntegral ()) 451 { 452return getInt64 (rttiInfo ,src )!= 0 ; 453 } 454else if (rttiInfo -> isFloat ()) 455 { 456return asDouble (rttiInfo ,src )!= 0.0 ; 457 } 458 459SLANG_ASSERT (!"Cannot convert to bool" ); 460return false; 461} 462 463static int64_t _getIntDefaultValue (RttiDefaultValue value ) 464{ 465switch (value ) 466 { 467default : 468case RttiDefaultValue ::Normal : 469return 0 ; 470case RttiDefaultValue ::One : 471return 1 ; 472case RttiDefaultValue ::MinusOne : 473return -1 ; 474 } 475} 476 477static bool _isStructDefault (const StructRttiInfo * type ,const void * src ) 478{ 479if (type -> m_super ) 480 { 481if (!_isStructDefault (type -> m_super ,src )) 482 { 483return false; 484 } 485 } 486 487const Byte * base = (const Byte * )src ; 488 489const Index count = type -> m_fieldCount ; 490for (Index i = 0 ;i < count ;++ i ) 491 { 492const auto & field = type -> m_fields [i ]; 493 494const RttiDefaultValue defaultValue = 495RttiDefaultValue (field .m_flags & uint8_t (RttiDefaultValue ::Mask )); 496 497if (!RttiUtil ::isDefault (defaultValue ,field .m_type ,base + field .m_offset )) 498 { 499return false; 500 } 501 } 502 503return true; 504} 505 506/* static */ bool RttiUtil ::isDefault ( 507RttiDefaultValue defaultValue , 508const RttiInfo * rttiInfo , 509const void * src ) 510{ 511if (rttiInfo -> isIntegral ()) 512 { 513const auto value = getInt64 (rttiInfo ,src ); 514return _getIntDefaultValue (defaultValue )== value ; 515 } 516else if (rttiInfo -> isFloat ()) 517 { 518const auto value = asDouble (rttiInfo ,src ); 519return _getIntDefaultValue (defaultValue )== value ; 520 } 521 522switch (rttiInfo -> m_kind ) 523 { 524case RttiInfo ::Kind ::Invalid : 525return true; 526case RttiInfo ::Kind ::Bool : 527return * (const bool * )src == (_getIntDefaultValue (defaultValue )!= 0 ); 528case RttiInfo ::Kind ::String : 529 { 530return ((const String * )src )-> getLength ()== 0 ; 531 } 532case RttiInfo ::Kind ::UnownedStringSlice : 533 { 534return ((const UnownedStringSlice * )src )-> getLength ()== 0 ; 535 } 536case RttiInfo ::Kind ::Struct : 537 { 538return _isStructDefault (static_cast < const StructRttiInfo *> (rttiInfo ),src ); 539 } 540case RttiInfo ::Kind ::Enum : 541 { 542SLANG_ASSERT (!"Not implemented yet" ); 543return false; 544 } 545case RttiInfo ::Kind ::List : 546 { 547const auto & v = * (const List < Byte >* )src ; 548return v .getCount ()== 0 ; 549 } 550case RttiInfo ::Kind ::Dictionary : 551 { 552const auto & v = * (const Dictionary < Byte ,Byte >* )src ; 553return v .getCount ()== 0 ; 554 } 555case RttiInfo ::Kind ::Other : 556 { 557const OtherRttiInfo * otherRttiInfo = static_cast < const OtherRttiInfo *> (rttiInfo ); 558return otherRttiInfo -> m_isDefaultFunc && otherRttiInfo -> m_isDefaultFunc (rttiInfo ,src ); 559 } 560case RttiInfo ::Kind ::Optional : 561 { 562return * (const bool * )src == (_getIntDefaultValue (defaultValue )!= 0 ); 563 } 564default : 565 { 566return false; 567 } 568 } 569} 570 571/* static */ SlangResult RttiUtil ::setListCount ( 572RttiTypeFuncsMap * typeMap , 573const RttiInfo * elementType , 574void * dst , 575Index count ) 576{ 577// NOTE! The following only works because List<T> has capacity initialized members, and 578// setting the count if it is <= capacity just sets the count (ie things aren't released(!)). 579 580List < Byte >& dstList = * (List < Byte >* )dst ; 581const Index oldCount = dstList .getCount (); 582if (oldCount == count ) 583 { 584return SLANG_OK ; 585 } 586if (count < oldCount ) 587 { 588dstList .unsafeShrinkToCount (count ); 589return SLANG_OK ; 590 } 591 592const auto typeFuncs = typeMap -> getFuncsForType (elementType ); 593SLANG_ASSERT (typeFuncs .isValid ()); 594 595const Index dstCapacity = dstList .getCapacity (); 596void * oldBuffer = dstList .detachBuffer (); 597 598void * newBuffer = ::malloc (count * elementType -> m_size ); 599// Initialize it all first 600typeFuncs .ctorArray (typeMap ,elementType ,newBuffer ,count ); 601 602typeFuncs .copyArray (typeMap ,elementType ,newBuffer ,oldBuffer ,oldCount ); 603 604// Attach the new buffer 605dstList .attachBuffer ((Byte * )newBuffer ,count ,count ); 606 607// Free the old buffer 608if (oldBuffer ) 609 { 610typeFuncs .dtorArray (typeMap ,elementType ,oldBuffer ,dstCapacity ); 611 ::free (oldBuffer ); 612 } 613 614return SLANG_OK ; 615} 616 617/* static */ bool RttiUtil ::canMemCpy (const RttiInfo * type ) 618{ 619switch (type -> m_kind ) 620 { 621case RttiInfo ::Kind ::RefPtr : 622case RttiInfo ::Kind ::String : 623case RttiInfo ::Kind ::Invalid : 624 { 625return false; 626 } 627case RttiInfo ::Kind ::UnownedStringSlice : 628case RttiInfo ::Kind ::Ptr : 629case RttiInfo ::Kind ::Enum : 630 { 631return true; 632 } 633case RttiInfo ::Kind ::FixedArray : 634 { 635const FixedArrayRttiInfo * fixedArrayRttiInfo = 636static_cast < const FixedArrayRttiInfo *> (type ); 637return canMemCpy (fixedArrayRttiInfo -> m_elementType ); 638 } 639case RttiInfo ::Kind ::Other : 640case RttiInfo ::Kind ::List : 641case RttiInfo ::Kind ::Dictionary : 642 { 643return false; 644 } 645case RttiInfo ::Kind ::Struct : 646 { 647const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (type ); 648 649do 650 { 651// If all the fields can be zero inited, struct can be 652const auto fieldCount = structRttiInfo -> m_fieldCount ; 653const auto fields = structRttiInfo -> m_fields ; 654 655for (Index i = 0 ;i < fieldCount ;++ i ) 656 { 657const auto & field = fields [i ]; 658if (!canMemCpy (field .m_type )) 659 { 660return false; 661 } 662 } 663structRttiInfo = structRttiInfo -> m_super ; 664 }while (structRttiInfo ); 665 666return true; 667 } 668case RttiInfo ::Kind ::Optional : 669 { 670const OptionalRttiInfo * optionalRttiInfo = static_cast < const OptionalRttiInfo *> (type ); 671return canMemCpy (optionalRttiInfo -> m_elementType ); 672 } 673default : 674 { 675return type -> isBuiltIn (); 676 } 677 } 678} 679 680/* static */ bool RttiUtil ::canZeroInit (const RttiInfo * type ) 681{ 682switch (type -> m_kind ) 683 { 684case RttiInfo ::Kind ::Invalid : 685 { 686return true; 687 } 688case RttiInfo ::Kind ::String : 689 { 690// As it stands we can zero init String, but if impl changes that might not 691// be true 692return true; 693 } 694case RttiInfo ::Kind ::UnownedStringSlice : 695case RttiInfo ::Kind ::Ptr : 696case RttiInfo ::Kind ::RefPtr : 697case RttiInfo ::Kind ::Enum : 698 { 699return true; 700 } 701case RttiInfo ::Kind ::FixedArray : 702 { 703const FixedArrayRttiInfo * fixedArrayRttiInfo = 704static_cast < const FixedArrayRttiInfo *> (type ); 705return canZeroInit (fixedArrayRttiInfo -> m_elementType ); 706 } 707case RttiInfo ::Kind ::Other : 708case RttiInfo ::Kind ::List : 709case RttiInfo ::Kind ::Dictionary : 710 { 711return false; 712 } 713case RttiInfo ::Kind ::Struct : 714 { 715const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (type ); 716 717do 718 { 719// If all the fields can be zero inited, struct can be 720const auto fieldCount = structRttiInfo -> m_fieldCount ; 721const auto fields = structRttiInfo -> m_fields ; 722 723for (Index i = 0 ;i < fieldCount ;++ i ) 724 { 725const auto & field = fields [i ]; 726if (!canZeroInit (field .m_type )) 727 { 728return false; 729 } 730 } 731structRttiInfo = structRttiInfo -> m_super ; 732 }while (structRttiInfo ); 733 734return true; 735 } 736case RttiInfo ::Kind ::Optional : 737 { 738const OptionalRttiInfo * optionalRttiInfo = static_cast < const OptionalRttiInfo *> (type ); 739return canZeroInit (optionalRttiInfo -> m_elementType ); 740 } 741default : 742 { 743return type -> isBuiltIn (); 744 } 745 } 746} 747 748/* static */ bool RttiUtil ::hasDtor (const RttiInfo * type ) 749{ 750switch (type -> m_kind ) 751 { 752case RttiInfo ::Kind ::Invalid : 753 { 754return false; 755 } 756case RttiInfo ::Kind ::String : 757case RttiInfo ::Kind ::RefPtr : 758 { 759return true; 760 } 761case RttiInfo ::Kind ::UnownedStringSlice : 762case RttiInfo ::Kind ::Ptr : 763case RttiInfo ::Kind ::Enum : 764 { 765return false; 766 } 767case RttiInfo ::Kind ::FixedArray : 768 { 769const FixedArrayRttiInfo * fixedArrayRttiInfo = 770static_cast < const FixedArrayRttiInfo *> (type ); 771return hasDtor (fixedArrayRttiInfo -> m_elementType ); 772 } 773case RttiInfo ::Kind ::Other : 774case RttiInfo ::Kind ::List : 775case RttiInfo ::Kind ::Dictionary : 776 { 777return true; 778 } 779case RttiInfo ::Kind ::Struct : 780 { 781const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (type ); 782 783do 784 { 785// If all the fields can be zero inited, struct can be 786const auto fieldCount = structRttiInfo -> m_fieldCount ; 787const auto fields = structRttiInfo -> m_fields ; 788 789for (Index i = 0 ;i < fieldCount ;++ i ) 790 { 791const auto & field = fields [i ]; 792if (hasDtor (field .m_type )) 793 { 794return true; 795 } 796 } 797structRttiInfo = structRttiInfo -> m_super ; 798 }while (structRttiInfo ); 799return false; 800 } 801case RttiInfo ::Kind ::Optional : 802 { 803const OptionalRttiInfo * optionalRttiInfo = static_cast < const OptionalRttiInfo *> (type ); 804return hasDtor (optionalRttiInfo -> m_elementType ); 805 } 806default : 807 { 808return !type -> isBuiltIn (); 809 } 810 } 811} 812 813/* static */ void RttiUtil ::ctorArray ( 814RttiTypeFuncsMap * typeMap , 815const RttiInfo * rttiInfo , 816void * inDst , 817ptrdiff_t stride , 818Index count ) 819{ 820if (count <=0 ) 821 { 822return ; 823 } 824 825Byte * dst = (Byte * )inDst ; 826if (canZeroInit (rttiInfo )) 827 { 828if (stride == rttiInfo -> m_size ) 829 { 830 ::memset (dst ,0 ,count * stride ); 831 } 832else 833 { 834const size_t size = rttiInfo -> m_size ; 835for (Index i = 0 ;i < count ;++ i ,dst += stride ) 836 { 837 ::memset (dst ,0 ,size ); 838 } 839 } 840return ; 841 } 842 843switch (rttiInfo -> m_kind ) 844 { 845case RttiInfo ::Kind ::FixedArray : 846 { 847const FixedArrayRttiInfo * fixedArrayRttiInfo = 848static_cast < const FixedArrayRttiInfo *> (rttiInfo ); 849 850if (fixedArrayRttiInfo -> m_size == stride ) 851 { 852// It's contiguous do in one go 853ctorArray ( 854typeMap , 855fixedArrayRttiInfo -> m_elementType , 856dst , 857fixedArrayRttiInfo -> m_elementType -> m_size , 858fixedArrayRttiInfo -> m_elementCount * count ); 859 } 860else 861 { 862// Do it in array runs 863for (Index i = 0 ;i < count ;++ i ,dst += stride ) 864 { 865ctorArray ( 866typeMap , 867fixedArrayRttiInfo -> m_elementType , 868dst , 869fixedArrayRttiInfo -> m_elementType -> m_size , 870fixedArrayRttiInfo -> m_elementCount ); 871 } 872 } 873return ; 874 } 875case RttiInfo ::Kind ::List : 876case RttiInfo ::Kind ::Dictionary : 877case RttiInfo ::Kind ::Other : 878 { 879auto funcs = typeMap -> getFuncsForType (rttiInfo ); 880SLANG_ASSERT (funcs .isValid ()); 881 882const OtherRttiInfo * otherRttiInfo = static_cast < const OtherRttiInfo *> (rttiInfo ); 883if (otherRttiInfo -> m_size == stride ) 884 { 885funcs .ctorArray (typeMap ,rttiInfo ,dst ,count ); 886 } 887else 888 { 889// Do it in array runs 890for (Index i = 0 ;i < count ;++ i ,dst += stride ) 891 { 892funcs .ctorArray (typeMap ,rttiInfo ,dst ,1 ); 893 } 894 } 895return ; 896 } 897case RttiInfo ::Kind ::Struct : 898 { 899const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (rttiInfo ); 900 901do 902 { 903// If all the fields can be zero inited, struct can be 904const auto fieldCount = structRttiInfo -> m_fieldCount ; 905const auto fields = structRttiInfo -> m_fields ; 906 907for (Index i = 0 ;i < fieldCount ;++ i ) 908 { 909const auto & field = fields [i ]; 910ctorArray (typeMap ,field .m_type ,dst + field .m_offset ,stride ,count ); 911 } 912structRttiInfo = structRttiInfo -> m_super ; 913 }while (structRttiInfo ); 914 915return ; 916 } 917case RttiInfo ::Kind ::Optional : 918 { 919const OptionalRttiInfo * optionalRttiInfo = 920static_cast < const OptionalRttiInfo *> (rttiInfo ); 921ctorArray (typeMap ,GetRttiInfo < bool > ::get (),dst ,stride ,count ); 922ctorArray ( 923typeMap , 924optionalRttiInfo -> m_elementType , 925dst + optionalRttiInfo -> m_valueOffset , 926stride , 927count ); 928return ; 929 } 930 } 931 932SLANG_ASSERT (!"Unexpected" ); 933} 934 935/* static */ void RttiUtil ::copyArray ( 936RttiTypeFuncsMap * typeMap , 937const RttiInfo * rttiInfo , 938void * inDst , 939const void * inSrc , 940ptrdiff_t stride , 941Index count ) 942{ 943if (count <=0 ) 944 { 945return ; 946 } 947 948const size_t size = rttiInfo -> m_size ; 949 950Byte * dst = (Byte * )inDst ; 951const Byte * src = (const Byte * )inSrc ; 952if (canMemCpy (rttiInfo )) 953 { 954if (stride == ptrdiff_t (size )) 955 { 956 ::memcpy (dst ,src ,count * stride ); 957 } 958else 959 { 960 961for (Index i = 0 ;i < count ;++ i ,dst += stride ,src += stride ) 962 { 963 ::memcpy (dst ,src ,size ); 964 } 965 } 966return ; 967 } 968 969switch (rttiInfo -> m_kind ) 970 { 971case RttiInfo ::Kind ::FixedArray : 972 { 973const FixedArrayRttiInfo * fixedArrayRttiInfo = 974static_cast < const FixedArrayRttiInfo *> (rttiInfo ); 975const auto elementType = fixedArrayRttiInfo -> m_elementType ; 976const auto elementSize = elementType -> m_size ; 977const auto elementCount = fixedArrayRttiInfo -> m_elementCount ; 978 979if (ptrdiff_t (size )== stride ) 980 { 981// It's contiguous do in one go 982copyArray (typeMap ,elementType ,dst ,src ,elementSize ,elementCount * count ); 983 } 984else 985 { 986// Do it in array runs 987for (Index i = 0 ;i < count ;++ i ,dst += stride ,src += stride ) 988 { 989copyArray (typeMap ,elementType ,dst ,src ,elementSize ,elementCount ); 990 } 991 } 992return ; 993 } 994case RttiInfo ::Kind ::List : 995case RttiInfo ::Kind ::Dictionary : 996case RttiInfo ::Kind ::Other : 997 { 998auto funcs = typeMap -> getFuncsForType (rttiInfo ); 999SLANG_ASSERT (funcs .isValid ()); 1000 1001const OtherRttiInfo * otherRttiInfo = static_cast < const OtherRttiInfo *> (rttiInfo ); 1002if (otherRttiInfo -> m_size == stride ) 1003 { 1004funcs .copyArray (typeMap ,rttiInfo ,dst ,src ,count ); 1005 } 1006else 1007 { 1008for (Index i = 0 ;i < count ;++ i ,dst += stride ,src += stride ) 1009 { 1010funcs .copyArray (typeMap ,rttiInfo ,dst ,src ,1 ); 1011 } 1012 } 1013return ; 1014 } 1015case RttiInfo ::Kind ::Struct : 1016 { 1017const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (rttiInfo ); 1018 1019do 1020 { 1021// If all the fields can be zero inited, struct can be 1022const auto fieldCount = structRttiInfo -> m_fieldCount ; 1023const auto fields = structRttiInfo -> m_fields ; 1024 1025for (Index i = 0 ;i < fieldCount ;++ i ) 1026 { 1027const auto & field = fields [i ]; 1028copyArray ( 1029typeMap , 1030field .m_type , 1031dst + field .m_offset , 1032src + field .m_offset , 1033stride , 1034count ); 1035 } 1036structRttiInfo = structRttiInfo -> m_super ; 1037 }while (structRttiInfo ); 1038 1039return ; 1040 } 1041case RttiInfo ::Kind ::Optional : 1042 { 1043const OptionalRttiInfo * optionalRttiInfo = 1044static_cast < const OptionalRttiInfo *> (rttiInfo ); 1045copyArray (typeMap ,GetRttiInfo < bool > ::get (),dst ,src ,stride ,count ); 1046copyArray ( 1047typeMap , 1048optionalRttiInfo -> m_elementType , 1049dst + optionalRttiInfo -> m_valueOffset , 1050src + optionalRttiInfo -> m_valueOffset , 1051stride , 1052count ); 1053return ; 1054 } 1055 } 1056 1057SLANG_ASSERT (!"Unexpected" ); 1058} 1059 1060/* static */ void RttiUtil ::dtorArray ( 1061RttiTypeFuncsMap * typeMap , 1062const RttiInfo * rttiInfo , 1063void * inDst , 1064ptrdiff_t stride , 1065Index count ) 1066{ 1067if (count <=0 || !hasDtor (rttiInfo )) 1068 { 1069return ; 1070 } 1071 1072const size_t size = rttiInfo -> m_size ; 1073Byte * dst = (Byte * )inDst ; 1074 1075switch (rttiInfo -> m_kind ) 1076 { 1077case RttiInfo ::Kind ::FixedArray : 1078 { 1079const FixedArrayRttiInfo * fixedArrayRttiInfo = 1080static_cast < const FixedArrayRttiInfo *> (rttiInfo ); 1081const auto elementType = fixedArrayRttiInfo -> m_elementType ; 1082const auto elementSize = elementType -> m_size ; 1083const auto elementCount = fixedArrayRttiInfo -> m_elementCount ; 1084 1085if (ptrdiff_t (size )== stride ) 1086 { 1087// It's contiguous do in one go 1088dtorArray (typeMap ,elementType ,dst ,elementSize ,elementCount * count ); 1089 } 1090else 1091 { 1092// Do it in array runs 1093for (Index i = 0 ;i < count ;++ i ,dst += stride ) 1094 { 1095dtorArray (typeMap ,elementType ,dst ,elementSize ,elementCount ); 1096 } 1097 } 1098return ; 1099 } 1100case RttiInfo ::Kind ::List : 1101case RttiInfo ::Kind ::Dictionary : 1102case RttiInfo ::Kind ::Other : 1103 { 1104auto funcs = typeMap -> getFuncsForType (rttiInfo ); 1105SLANG_ASSERT (funcs .isValid ()); 1106 1107const OtherRttiInfo * otherRttiInfo = static_cast < const OtherRttiInfo *> (rttiInfo ); 1108if (otherRttiInfo -> m_size == stride ) 1109 { 1110funcs .dtorArray (typeMap ,rttiInfo ,dst ,count ); 1111 } 1112else 1113 { 1114for (Index i = 0 ;i < count ;++ i ,dst += stride ) 1115 { 1116funcs .dtorArray (typeMap ,rttiInfo ,dst ,1 ); 1117 } 1118 } 1119return ; 1120 } 1121case RttiInfo ::Kind ::Struct : 1122 { 1123const StructRttiInfo * structRttiInfo = static_cast < const StructRttiInfo *> (rttiInfo ); 1124 1125do 1126 { 1127// If all the fields can be zero inited, struct can be 1128const auto fieldCount = structRttiInfo -> m_fieldCount ; 1129const auto fields = structRttiInfo -> m_fields ; 1130 1131for (Index i = 0 ;i < fieldCount ;++ i ) 1132 { 1133const auto & field = fields [i ]; 1134dtorArray (typeMap ,field .m_type ,dst + field .m_offset ,stride ,count ); 1135 } 1136structRttiInfo = structRttiInfo -> m_super ; 1137 }while (structRttiInfo ); 1138 1139return ; 1140 } 1141case RttiInfo ::Kind ::Optional : 1142 { 1143const OptionalRttiInfo * optionalRttiInfo = 1144static_cast < const OptionalRttiInfo *> (rttiInfo ); 1145dtorArray (typeMap ,GetRttiInfo < bool > ::get (),dst ,stride ,count ); 1146dtorArray ( 1147typeMap , 1148optionalRttiInfo -> m_elementType , 1149dst + optionalRttiInfo -> m_valueOffset , 1150stride , 1151count ); 1152return ; 1153 } 1154 } 1155 1156SLANG_ASSERT (!"Unexpected" ); 1157} 1158 1159}// namespace Slang