Files
godot/thirdparty/jolt_physics/Jolt/Core/StreamUtils.h
noahbackus 9d30169a8d
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
initial commit, 4.5 stable
2025-09-16 20:46:46 -04:00

169 lines
4.0 KiB
C++

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
#include <Jolt/Core/Result.h>
#include <Jolt/Core/StreamIn.h>
#include <Jolt/Core/StreamOut.h>
#include <Jolt/Core/UnorderedMap.h>
#include <Jolt/Core/Factory.h>
JPH_NAMESPACE_BEGIN
namespace StreamUtils {
template <class Type>
using ObjectToIDMap = UnorderedMap<const Type *, uint32>;
template <class Type>
using IDToObjectMap = Array<Ref<Type>>;
// Restore a single object by reading the hash of the type, constructing it and then calling the restore function
template <class Type>
Result<Ref<Type>> RestoreObject(StreamIn &inStream, void (Type::*inRestoreBinaryStateFunction)(StreamIn &))
{
Result<Ref<Type>> result;
// Read the hash of the type
uint32 hash;
inStream.Read(hash);
if (inStream.IsEOF() || inStream.IsFailed())
{
result.SetError("Failed to read type hash");
return result;
}
// Get the RTTI for the type
const RTTI *rtti = Factory::sInstance->Find(hash);
if (rtti == nullptr)
{
result.SetError("Failed to create instance of type");
return result;
}
// Construct and read the data of the type
Ref<Type> object = reinterpret_cast<Type *>(rtti->CreateObject());
(object->*inRestoreBinaryStateFunction)(inStream);
if (inStream.IsEOF() || inStream.IsFailed())
{
result.SetError("Failed to restore object");
return result;
}
result.Set(object);
return result;
}
/// Save an object reference to a stream. Uses a map to map objects to IDs which is also used to prevent writing duplicates.
template <class Type>
void SaveObjectReference(StreamOut &inStream, const Type *inObject, ObjectToIDMap<Type> *ioObjectToIDMap)
{
if (ioObjectToIDMap == nullptr || inObject == nullptr)
{
// Write null ID
inStream.Write(~uint32(0));
}
else
{
typename ObjectToIDMap<Type>::const_iterator id = ioObjectToIDMap->find(inObject);
if (id != ioObjectToIDMap->end())
{
// Existing object, write ID
inStream.Write(id->second);
}
else
{
// New object, write the ID
uint32 new_id = uint32(ioObjectToIDMap->size());
(*ioObjectToIDMap)[inObject] = new_id;
inStream.Write(new_id);
// Write the object
inObject->SaveBinaryState(inStream);
}
}
}
/// Restore an object reference from stream.
template <class Type>
Result<Ref<Type>> RestoreObjectReference(StreamIn &inStream, IDToObjectMap<Type> &ioIDToObjectMap)
{
Result<Ref<Type>> result;
// Read id
uint32 id = ~uint32(0);
inStream.Read(id);
// Check null
if (id == ~uint32(0))
{
result.Set(nullptr);
return result;
}
// Check if it already exists
if (id >= ioIDToObjectMap.size())
{
// New object, restore it
result = Type::sRestoreFromBinaryState(inStream);
if (result.HasError())
return result;
JPH_ASSERT(id == ioIDToObjectMap.size());
ioIDToObjectMap.push_back(result.Get());
}
else
{
// Existing object filter
result.Set(ioIDToObjectMap[id].GetPtr());
}
return result;
}
// Save an array of objects to a stream.
template <class ArrayType, class ValueType>
void SaveObjectArray(StreamOut &inStream, const ArrayType &inArray, ObjectToIDMap<ValueType> *ioObjectToIDMap)
{
uint32 len = uint32(inArray.size());
inStream.Write(len);
for (const ValueType *value: inArray)
SaveObjectReference(inStream, value, ioObjectToIDMap);
}
// Restore an array of objects from a stream.
template <class ArrayType, class ValueType>
Result<ArrayType> RestoreObjectArray(StreamIn &inStream, IDToObjectMap<ValueType> &ioIDToObjectMap)
{
Result<ArrayType> result;
uint32 len;
inStream.Read(len);
if (inStream.IsEOF() || inStream.IsFailed())
{
result.SetError("Failed to read stream");
return result;
}
ArrayType values;
values.reserve(len);
for (size_t i = 0; i < len; ++i)
{
Result value = RestoreObjectReference(inStream, ioIDToObjectMap);
if (value.HasError())
{
result.SetError(value.GetError());
return result;
}
values.push_back(std::move(value.Get()));
}
result.Set(values);
return result;
}
} // StreamUtils
JPH_NAMESPACE_END