//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Shared object based on a CBaseRecord subclass // //============================================================================= #ifndef PROTOBUFSHAREDOBJECT_H #define PROTOBUFSHAREDOBJECT_H #ifdef _WIN32 #pragma once #endif #include "google/protobuf/descriptor.h" #include "tier1/KeyValues.h" #if defined( GC ) && defined( DEBUG ) #include "gcbase.h" #endif namespace google { namespace protobuf { class Message; } } namespace GCSDK { //---------------------------------------------------------------------------- // Purpose: Base class for CProtoBufSharedObject. This is where all the actual // code lives. //---------------------------------------------------------------------------- class CProtoBufSharedObjectBase : public CSharedObject { public: typedef CSharedObject BaseClass; virtual bool BParseFromMessage( const CUtlBuffer & buffer ) OVERRIDE; virtual bool BParseFromMessage( const std::string &buffer ) OVERRIDE; virtual bool BUpdateFromNetwork( const CSharedObject & objUpdate ) OVERRIDE; virtual bool BIsKeyLess( const CSharedObject & soRHS ) const ; virtual void Copy( const CSharedObject & soRHS ); virtual void Dump() const OVERRIDE; #ifdef DBGFLAG_VALIDATE virtual void Validate( CValidator &validator, const char *pchName ); #endif #ifdef GC virtual bool BAddToMessage( CUtlBuffer & bufOutput ) const OVERRIDE; virtual bool BAddToMessage( std::string *pBuffer ) const OVERRIDE; virtual bool BAddDestroyToMessage( CUtlBuffer & bufDestroy ) const OVERRIDE; virtual bool BAddDestroyToMessage( std::string *pBuffer ) const OVERRIDE; virtual bool BParseFromMemcached( CUtlBuffer & buffer ) OVERRIDE; virtual bool BAddToMemcached( CUtlBuffer & bufOutput ) const OVERRIDE; static bool SerializeToBuffer( const ::google::protobuf::Message & msg, CUtlBuffer & bufOutput ); #endif //GC // Static helpers static void Dump( const ::google::protobuf::Message & msg ); static KeyValues *CreateKVFromProtoBuf( const ::google::protobuf::Message & msg ); static void RecursiveAddProtoBufToKV( KeyValues *pKVDest, const ::google::protobuf::Message & msg ); protected: virtual ::google::protobuf::Message *GetPObject() = 0; const ::google::protobuf::Message *GetPObject() const { return const_cast(this)->GetPObject(); } private: #ifdef GC static ::google::protobuf::Message *BuildDestroyToMessage( const ::google::protobuf::Message & msg ); #endif //GC }; //---------------------------------------------------------------------------- // Purpose: Template for making a shared object that uses a specific protobuf // message class for its wire protocol and in-memory representation. //---------------------------------------------------------------------------- template< typename Message_t, int nTypeID, bool bPublicMutable = true > class CProtoBufSharedObject : public CProtoBufSharedObjectBase { public: ~CProtoBufSharedObject() { #if defined( GC ) && defined( DEBUG ) // Ensure this SO is not in any cache, or we have an error. We must provide the type since it is a virutal function otherwise Assert( !GGCBase()->IsSOCached( this, nTypeID ) ); #endif } virtual int GetTypeID() const { return nTypeID; } // WHERE IS YOUR GOD NOW template< typename T > using Public_Message_t = typename std::enable_if< bPublicMutable && std::is_same< T, Message_t >::value, Message_t & >::type; template< typename T > using Protected_Message_t = typename std::enable_if< !bPublicMutable && std::is_same< T, Message_t >::value, Message_t & >::type; template< typename T = Message_t > Public_Message_t Obj() { return m_msgObject; } const Message_t & Obj() const { return m_msgObject; } typedef Message_t SchObjectType_t; const static int k_nTypeID = nTypeID; protected: template< typename T = Message_t > Protected_Message_t MutObj() { return m_msgObject; } ::google::protobuf::Message *GetPObject() { return &m_msgObject; } private: Message_t m_msgObject; }; //---------------------------------------------------------------------------- // Purpose: Template for making a shared object that uses a specific protobuf // message class for its wire protocol and in-memory representation. // // The wrapper version of this class wraps a message allocated and // owned elsewhere. The user of this class is in charge of // guaranteeing that lifetime. //---------------------------------------------------------------------------- template< typename Message_t, int nTypeID > class CProtoBufSharedObjectWrapper : public CProtoBufSharedObjectBase { public: CProtoBufSharedObjectWrapper( Message_t *pMsgToWrap ) : m_pMsgObject( pMsgToWrap ) {} ~CProtoBufSharedObjectWrapper() { #if defined( GC ) && defined( DEBUG ) // Ensure this SO is not in any cache, or we have an error. We must provide the type since it is a virutal function otherwise Assert( !GGCBase()->IsSOCached( this, nTypeID ) ); #endif } virtual int GetTypeID() const { return nTypeID; } Message_t & Obj() { return *m_pMsgObject; } const Message_t & Obj() const { return *m_pMsgObject; } typedef Message_t SchObjectType_t; public: const static int k_nTypeID = nTypeID; protected: ::google::protobuf::Message *GetPObject() { return m_pMsgObject; } private: Message_t *m_pMsgObject; }; } // GCSDK namespace #endif //PROTOBUFSHAREDOBJECT_H