Files
UnrealEngine/Engine/Plugins/Experimental/PlainProps/Source/Private/PlainPropsInternalRead.h
2025-05-18 13:04:45 +08:00

142 lines
5.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "PlainPropsTypes.h"
#include "PlainPropsRead.h"
#include "PlainPropsInternalFormat.h"
#include <type_traits>
namespace PlainProps
{
template<typename MemberType, typename IndexType>
TConstArrayView<MemberType> GrabInnerRangeTypes(TConstArrayView<MemberType> InnerRangeTypes, IndexType& InOutIdx)
{
const int32 StartIdx = InOutIdx;
int32 Idx = StartIdx;
while (InnerRangeTypes[Idx++].IsRange());
InOutIdx = static_cast<IndexType>(Idx);
return MakeArrayView(&InnerRangeTypes[StartIdx], Idx - StartIdx);
}
inline uint64 GrabRangeNum(ERangeSizeType MaxSize, FByteReader& ByteIt, FBitCacheReader& BitIt)
{
switch(MaxSize)
{
case ERangeSizeType::Uni: return BitIt.GrabNext(/* in-out */ ByteIt) ? 1 : 0;
case ERangeSizeType::S8: return IntCastChecked<uint64>( ByteIt.Grab<int8>());
case ERangeSizeType::U8: return ByteIt.Grab<uint8>();
case ERangeSizeType::S16: return IntCastChecked<uint64>( ByteIt.Grab<int16>());
case ERangeSizeType::U16: return ByteIt.Grab<uint16>();
case ERangeSizeType::S32: return IntCastChecked<uint64>( ByteIt.Grab<int32>());
case ERangeSizeType::U32: return ByteIt.Grab<uint32>();
case ERangeSizeType::S64: return IntCastChecked<uint64>( ByteIt.Grab<int64>());
case ERangeSizeType::U64: return ByteIt.Grab<uint64>();
}
check(false);
return 0;
}
inline FMemoryView GrabRangeValues(uint64 Num, FMemberType InnerType, /* in-out */ FByteReader& ByteIt)
{
if (Num == 0)
{
return FMemoryView();
}
uint64 NumBytes = InnerType.IsLeaf() ? GetLeafRangeSize(Num, InnerType.AsLeaf()) : ByteIt.GrabVarIntU();
return ByteIt.GrabSlice(NumBytes);
}
inline FMemberType GetInnermostType(FRangeSchema Schema)
{
FMemberType Inner = Schema.ItemType;
for (const FMemberType* It = Schema.NestedItemTypes; Inner.IsRange(); Inner = *It++) {}
return Inner;
}
//////////////////////////////////////////////////////////////////////////
template<class T>
struct TSchemaIterator
{
uintptr_t Base;
const uint32* OffsetIt;
void operator++() { ++OffsetIt; }
bool operator!=(TSchemaIterator O) const { return OffsetIt != O.OffsetIt; }
T& operator*() const { return *reinterpret_cast<T*>(Base + *OffsetIt); }
};
template<class T>
struct TSchemaRange
{
static constexpr bool bStructSchema = std::is_convertible_v<T, FStructSchema>;
TSchemaRange(std::conditional_t<std::is_const_v<T>, const FSchemaBatch&, FSchemaBatch&> Batch)
: Base(reinterpret_cast<uintptr_t>(&Batch))
, Offsets(Batch.SchemaOffsets + (bStructSchema ? 0 : Batch.NumStructSchemas), bStructSchema ? Batch.NumStructSchemas : Batch.NumSchemas - Batch.NumStructSchemas)
{
static_assert(bStructSchema ^ std::is_convertible_v<T, FEnumSchema>);
}
TSchemaIterator<T> begin() const { return { Base, Offsets.begin() }; }
TSchemaIterator<T> end() const { return { Base, Offsets.end() }; }
T& First() const { return *reinterpret_cast<T*>(Base + Offsets[0]); }
T& Last() const { return *reinterpret_cast<T*>(Base + Offsets.Last()); }
T& operator[](uint32 Idx) const { return *reinterpret_cast<T*>(Base + Offsets[Idx]); }
uintptr_t Base;
TConstArrayView<uint32> Offsets;
};
inline TSchemaRange<FEnumSchema> GetEnumSchemas(FSchemaBatch& Batch) { return { Batch }; }
inline TSchemaRange<const FEnumSchema> GetEnumSchemas(const FSchemaBatch& Batch) { return { Batch }; }
inline TSchemaRange<FStructSchema> GetStructSchemas(FSchemaBatch& Batch) { return { Batch }; }
inline TSchemaRange<const FStructSchema> GetStructSchemas(const FSchemaBatch& Batch) { return { Batch }; }
//////////////////////////////////////////////////////////////////////////
const FSchemaBatch& GetReadSchemas(FSchemaBatchId Batch);
inline const FStructSchema& ResolveStructSchema(const FSchemaBatch& Batch, FSchemaId Id)
{
check(Id.Idx < Batch.NumSchemas);
return *reinterpret_cast<const FStructSchema*>(reinterpret_cast<const uint8*>(&Batch) + Batch.SchemaOffsets[Id.Idx]);
}
inline const FEnumSchema& ResolveEnumSchema(const FSchemaBatch& Batch, FSchemaId Id)
{
check(Id.Idx < Batch.NumSchemas);
return *reinterpret_cast<const FEnumSchema*>(reinterpret_cast<const uint8*>(&Batch) + Batch.SchemaOffsets[Id.Idx]);
}
inline FNestedScope ResolveNestedScope(const FSchemaBatch& Batch, FNestedScopeId Id)
{
return Batch.GetNestedScopes()[Id.Idx];
}
inline FParametricTypeView ResolveParametricType(const FSchemaBatch& Batch, FParametricTypeId Id)
{
FParametricType Type = Batch.GetParametricTypes()[Id.Idx];
return {Type.Name, IntCastChecked<uint8>(Type.Parameters.NumParameters), Batch.GetFirstParameter() + Type.Parameters.Idx};
}
//////////////////////////////////////////////////////////////////////////
inline FMemoryView GetSchemaData(const FSchemaBatch& Batch)
{
check(Batch.NumSchemas > 0);
const uint8* BatchPtr = reinterpret_cast<const uint8*>(&Batch);
TConstArrayView<uint32> Offsets(Batch.SchemaOffsets, Batch.NumSchemas);
bool bHasEnums = Batch.NumSchemas > Batch.NumStructSchemas;
uint32 LastSchemaSize = bHasEnums ? CalculateSize(GetEnumSchemas(Batch).Last())
: CalculateSize(GetStructSchemas(Batch).Last());
return FMemoryView(BatchPtr + Offsets[0], Offsets.Last() + LastSchemaSize - Offsets[0]);
}
} // namespace PlainProps