// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "PlainPropsBind.h" namespace PlainProps { // Iterates over member bindings class FMemberVisitor { public: explicit FMemberVisitor(const FSchemaBinding& InSchema); bool HasMore() const { return MemberIdx < NumMembers; } uint16 GetIndex() const { return MemberIdx; } EMemberKind PeekKind() const; // @pre HasMore() FMemberBindType PeekType() const; // @pre HasMore() uint32 PeekOffset() const; // @pre HasMore() FLeafMemberBinding GrabLeaf(); // @pre PeekKind() == EMemberKind::Leaf FRangeMemberBinding GrabRange(); // @pre PeekKind() == EMemberKind::Range FStructMemberBinding GrabStruct(); // @pre PeekKind() == EMemberKind::Struct FBindId GrabSuper(); // @pre First grab and has declared super void SkipMember(); protected: // for unit tests const FSchemaBinding& Schema; const uint16 NumMembers; uint16 MemberIdx = 0; uint16 InnerRangeIdx = 0; // Types of [nested] ranges uint16 InnerSchemaIdx = 0; // Types of static structs and enums using FMemberBindTypeRange = TConstArrayView; uint64 GrabMemberOffset(); FMemberBindTypeRange GrabInnerTypes(); FInnerId GrabInnerSchema(); FBindId GrabStructSchema(FStructType Type); FOptionalInnerId GrabRangeSchema(FMemberType InnermostType); FEnumId GrabEnumSchema() { return GrabInnerSchema().AsEnum(); } }; //////////////////////////////////////////////////////////////////////////////////////////////// struct FMemberBinderBase { FMemberBinderBase(FSchemaBinding& InSchema) : Schema(InSchema) , MemberIt(Schema.Members) , RangeTypeIt(const_cast(Schema.GetInnerRangeTypes())) , OffsetIt(const_cast(Schema.GetOffsets())) , RangeBindingIt(const_cast(Schema.GetRangeBindings())) {} ~FMemberBinderBase() { check(MemberIt == Schema.GetInnerRangeTypes()); check(Align(RangeTypeIt, alignof(uint32)) == (const void*)Schema.GetOffsets()); check(OffsetIt == (const void*)Schema.GetInnerSchemas()); check(Schema.NumInnerRanges == RangeBindingIt - Schema.GetRangeBindings()); } void AddMember(FMemberBindType Type, uint32 Offset) { *MemberIt++ = Type; *OffsetIt++ = Offset; } void AddRange(TConstArrayView Ranges, FMemberBindType InnermostType, uint32 Offset) { AddMember(FMemberBindType(Ranges[0].GetSizeType()), Offset); for (FRangeBinding Range : Ranges.RightChop(1)) { *RangeTypeIt++ = FMemberBindType(Range.GetSizeType()); } *RangeTypeIt++ = InnermostType; FMemory::Memcpy(RangeBindingIt, Ranges.GetData(), Ranges.Num() * Ranges.GetTypeSize()); RangeBindingIt += Ranges.Num(); } FSchemaBinding& Schema; FMemberBindType* MemberIt; FMemberBindType* RangeTypeIt; uint32* OffsetIt; FRangeBinding* RangeBindingIt; }; //////////////////////////////////////////////////////////////////////////////////////////////// [[nodiscard]] inline FMemberType ToMemberType(FMemberBindType In) { switch (In.GetKind()) { case EMemberKind::Leaf: return FMemberType(ToLeafType(In.AsLeaf())); case EMemberKind::Range: return FMemberType(In.AsRange()); default: return FMemberType(In.AsStruct()); } } } // namespace PlainProps