chenqiyang
2022-09-02 6a99d9bf65aa5878cb409945ed2bdbdcb916d047
Shared.IOS.HDLLinphoneSDK/Shared.IOS.HDLLinphoneSDK/Library/belle-sip.framework/Headers/object++.hh
@@ -31,7 +31,7 @@
class ObjectCAccessors;
class BELLESIP_EXPORT Object {
class BELLESIP_EXPORT Object{
   friend ObjectCAccessors;
   public:
      Object();
@@ -39,7 +39,7 @@
      const Object *ref() const;
      void unref();
      //Overrides should keep   the size of toString() lower than BELLE_SIP_MAX_TO_STRING_SIZE
           virtual std::string toString() const;
      virtual std::string toString() const;
      virtual Object *clone()const;
      belle_sip_cpp_object_t *getCObject();
      const belle_sip_cpp_object_t *getCObject()const;
@@ -75,35 +75,37 @@
 * }
 * The C object can be obtained with toC() method, directly casted in the expected type.
 * The C++ object can be obtained from C object with static method toCpp().
 * The destructor MUST be kept protected so that no one can call delete operator on the object. Instead unref() must be used.
 * make_shared<>() MUST NOT be used to instanciate an HybridObject, use create() instead.
 * a shared_ptr<> can be obtained at any time from an HybridObject using getSharedFromThis().
 *
 * VERY IMPORTANT USAGE RULES:
 * - The destructor MUST be kept protected so that no one can call delete operator on the object. Instead unref() must be used.
 * - make_shared<>() or shared_ptr<>(new ...) MUST NOT be used to instanciate an HybridObject, use create() instead.
 *
 * A shared_ptr<> can be obtained at any time from an HybridObject using getSharedFromThis().
 * The static getSharedFromThis(_Ctype*) method can be used to directly obtain a shared_ptr from the C object.
 *
 *
 * The clone() method must be overriden to return a new _CppType contructed with copy contructor,
 * or return nullptr if the object is defined to be not clonable.
 *
 * Rational for using this template:
 * - You have an existing library in C where all C objects are inheriting from belle_sip_object_t (for refcounting, data_set etc...).
 * - You want to use C++ in your library without making any disruption in the API.
 * IMPORTANT:
 * If you don't care about belle_sip_object_t inheritance in your C api,
 * IMPORTANT:
 * If you don't care about belle_sip_object_t inheritance in your C api,
 * or if you don't need any C api associated to this object at all, DON'T USE THIS.
 * An usage example is shown in tester/object_tester.cc .
**/
template <typename _CType, typename _CppType>
class HybridObject : public Object {
   public:
      //Create the C++ object returned as a shared_ptr. Ref is managed by shared_ptr, unref will be called on last ref.
      //Create the C++ object returned as a shared_ptr. Reference counting is managed by shared_ptr automatically.
      template <typename... _Args>
      static inline std::shared_ptr<_CppType> create(_Args&&... __args) {
         return (new _CppType(std::forward<_Args>(__args)...))->toSharedPtr();
      }
      //Convenience creator to get the C object object instead. Automatically aquires a ref. Consumers have the responsibility to unref
      //Convenience creator to get the C object object instead. Automatically acquires a ref. Consumers have the responsibility to unref
      template <typename... _Args>
      static inline _CType *createCObject(_Args&&... __args) {
         _CppType *obj = new _CppType(std::forward<_Args>(__args)...);
         return obj->toC();
         return (new _CppType(std::forward<_Args>(__args)...))->toC();
      }
      //Obtain the C object from this.
      _CType *toC(){
@@ -123,13 +125,11 @@
      }
      //Obtain a shared_ptr from the C++ object.
      std::shared_ptr<_CppType> getSharedFromThis() {
         this->ref();
         return std::shared_ptr<_CppType>(static_cast<_CppType *>(this), std::mem_fun(&Object::unref));
         return sharedFromThis(false);
      }
      //Obtain a shared_ptr from the C++ object in the const case.
      std::shared_ptr<const _CppType> getSharedFromThis () const {
         this->ref();
         return std::shared_ptr<const _CppType>(static_cast<const _CppType *>(this), std::mem_fun(&HybridObject<_CType,_CppType>::constUnref));
         return sharedFromThis(false);
      }
      //Convenience method for easy CType -> shared_ptr<CppType> conversion
      static std::shared_ptr<_CppType> getSharedFromThis(_CType *ptr) {
@@ -143,28 +143,30 @@
      // Use this method with caution as it will transfer the ownership of the object to the shared_ptr, unlike getSharedFromThis() that
      // gives you a new reference to the object.
      // This method should be only useful to transfer into a shared_ptr an object that was created as a normal pointer, for example
      // by clone() method.
      // There should be NO const variant of this method.
      // by clone() or createCObject() methods.
      // There should be NO public const variant of this method.
      std::shared_ptr<_CppType> toSharedPtr(){
         return std::shared_ptr<_CppType>(static_cast<_CppType *>(this), std::mem_fun(&Object::unref));
         return sharedFromThis(true);
      }
      //Convenience method for easy bctbx_list(_Ctype) -> std::list<_CppType> conversion
      static std::list<_CppType> getCppListFromCList(const bctbx_list_t *cList) {
         std::list<_CppType> result;
         for (auto it = cList; it; it = bctbx_list_next(it))
            result.push_back(toCpp(static_cast<_CType>(bctbx_list_get_data(it))));
      //It does not take ownership of the hybrid object, but takes a ref.
      static std::list<std::shared_ptr<_CppType>> getCppListFromCList(const bctbx_list_t *cList) {
         std::list<std::shared_ptr<_CppType>> result;
         for (auto it = cList; it != nullptr; it = bctbx_list_next(it))
            result.push_back(toCpp(static_cast<_CType*>(bctbx_list_get_data(it)))->getSharedFromThis() );
         return result;
      }
      //Convenience method for easy bctbx_list(_Ctype) -> std::list<_CppType> conversion
      //Applies 'func' to get _CppType from _CType. Used in case we do not want to call  `toCpp` on _Ctype
      static std::list<_CppType> getCppListFromCList(const bctbx_list_t *cList, const std::function<_CppType (_CType)> &func) {
         std::list<_CppType> result;
         for (auto it = cList; it; it = bctbx_list_next(it))
             result.push_back(func(static_cast<_CType>(bctbx_list_get_data(it))));
      static std::list<std::shared_ptr<_CppType>> getCppListFromCList(const bctbx_list_t *cList, const std::function<std::shared_ptr<_CppType> (_CType *)> &func) {
         std::list<std::shared_ptr<_CppType>> result;
         for (auto it = cList; it != nullptr; it = bctbx_list_next(it))
             result.push_back(func(static_cast<_CType*>(bctbx_list_get_data(it))));
         return result;
      }
      //Convenience method for easy std::list<shared_ptr<CppType>> -> bctbx_list(CType) conversion
      //It does not take ownership of the hybrid object, but takes a ref.
      static bctbx_list_t* getCListFromCppList(const std::list<std::shared_ptr<_CppType> > &cppList) {
         bctbx_list_t *result = nullptr;
         for (auto it = cppList.begin(); it != cppList.end(); it++) {
@@ -175,13 +177,47 @@
         }
         return result;
      }
      //Convenience method for easy std::list<CppType*> -> bctbx_list(CType) conversion
      //It does not take ownership of the hybrid object, but takes a ref.
      static bctbx_list_t* getCListFromCppList(const std::list<_CppType*> &cppList) {
         bctbx_list_t *result = nullptr;
         for (auto it = cppList.begin(); it != cppList.end(); it++) {
            _CppType *cppPtr = static_cast<_CppType*>(*it);
            cppPtr->ref();
            _CType *cptr = cppPtr->toC();
            result = bctbx_list_append(result, cptr);
         }
         return result;
      }
      static const char * nullifyEmptyString(const std::string& cppString){
         if (cppString.empty()) return nullptr;
         else return cppString.c_str();
      }
   protected:
      virtual ~HybridObject() {}
      virtual ~HybridObject() = default;
      HybridObject() {}
      HybridObject(const HybridObject<_CType, _CppType> &other) : Object(other) {}
   private:
      std::shared_ptr<_CppType> sharedFromThis(bool withTransfer)const{
         std::shared_ptr<_CppType> sp;
         if ((sp = mSelf.lock()) == nullptr){
            sp = std::shared_ptr<_CppType>(static_cast<_CppType *>(const_cast<HybridObject<_CType, _CppType> *>(this)),
                          std::mem_fn(&HybridObject<_CType, _CppType>::constUnref));
            mSelf = sp;
            if (!withTransfer){
               sp->ref();
            }
         }else{
            if (withTransfer){
               belle_sip_fatal("This HybridObject already has shared_ptr<> instances pointing to it.");
            }
         }
         return sp;
      }
      mutable std::weak_ptr<_CppType> mSelf;
};
}//end of namespace