include/common/PxSerializer.h

File members: include/common/PxSerializer.h

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of NVIDIA CORPORATION nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2024 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.

#ifndef PX_SERIALIZER_H
#define PX_SERIALIZER_H

#include "foundation/PxAssert.h"
#include "foundation/PxAllocatorCallback.h"
#include "foundation/PxFoundation.h"
#include "common/PxSerialFramework.h"
#include "common/PxCollection.h"

#if !PX_DOXYGEN
namespace physx
{
#endif

class PxSerializer
{
public:

    /**********************************************************************************************************************/

    //\{

    virtual  const  char*           getConcreteTypeName() const                                                         = 0;

    virtual         void            requiresObjects(PxBase&, PxProcessPxBaseCallback&) const                                    = 0;

    virtual         bool            isSubordinate() const                                                               = 0;

    //\}
    /**********************************************************************************************************************/

    /**********************************************************************************************************************/

    //\{

    virtual         void            exportExtraData(PxBase&, PxSerializationContext&) const                             = 0;

    virtual         void            exportData(PxBase&, PxSerializationContext&) const                                  = 0;

    virtual         void            registerReferences(PxBase& obj, PxSerializationContext& s) const                    = 0;

    virtual         size_t          getClassSize() const                                                                = 0;

    virtual         PxBase*         createObject(PxU8*& address, PxDeserializationContext& context) const   = 0;

    //\}
    /**********************************************************************************************************************/
    virtual ~PxSerializer() {}
};

template<class T>
class PxSerializerDefaultAdapter : public PxSerializer
{
public:

    /************************************************************************************************/

    //\{

    PxSerializerDefaultAdapter(const char* name) : mTypeName(name){}

    virtual const char* getConcreteTypeName() const
    {
        return mTypeName;
    }

    virtual void requiresObjects(PxBase& obj, PxProcessPxBaseCallback& c) const
    {
        T& t = static_cast<T&>(obj);
        t.requiresObjects(c);
    }

    virtual bool isSubordinate() const
    {
        return false;
    }

    //\}
    /************************************************************************************************/

    //\{

    // object methods

    virtual void exportExtraData(PxBase& obj, PxSerializationContext& s) const
    {
        T& t = static_cast<T&>(obj);
        t.exportExtraData(s);
    }

    virtual void exportData(PxBase& obj, PxSerializationContext& s) const
    {
        PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
        T* copy = reinterpret_cast<T*>(allocator.allocate(sizeof(T), "TmpAllocExportData", PX_FL));
        PxMemCopy(copy, &obj, sizeof(T));
        copy->preExportDataReset();
        s.writeData(copy, sizeof(T));
        allocator.deallocate(copy);
    }

    virtual void registerReferences(PxBase& obj, PxSerializationContext& s) const
    {
        T& t = static_cast<T&>(obj);

        s.registerReference(obj, PX_SERIAL_REF_KIND_PXBASE, size_t(&obj));

        struct RequiresCallback : public PxProcessPxBaseCallback
        {
            RequiresCallback(PxSerializationContext& c) : context(c) {}
            RequiresCallback& operator=(RequiresCallback&) { PX_ASSERT(0); return *this; }
            void process(physx::PxBase& base)
            {
                context.registerReference(base, PX_SERIAL_REF_KIND_PXBASE, size_t(&base));
            }
            PxSerializationContext& context;
        };

        RequiresCallback callback(s);
        t.requiresObjects(callback);
    }

    // class methods

    virtual size_t getClassSize() const
    {
        return sizeof(T);
    }

    virtual PxBase* createObject(PxU8*& address, PxDeserializationContext& context) const
    {
        return T::createObject(address, context);
    }

    //\}
    /************************************************************************************************/

private:
    const char*    mTypeName;
};

#define PX_NEW_SERIALIZER_ADAPTER(x) \
    *new( PxGetAllocatorCallback()->allocate(sizeof(PxSerializerDefaultAdapter<x>), \
    "PxSerializerDefaultAdapter", PX_FL)) PxSerializerDefaultAdapter<x>(#x)

#define PX_DELETE_SERIALIZER_ADAPTER(x) \
    { PxSerializer* s = x; if (s) { s->~PxSerializer(); PxGetAllocatorCallback()->deallocate(s); } }

#if !PX_DOXYGEN
} // namespace physx
#endif

#endif