Commit 03476a93 authored by Simon Morlat's avatar Simon Morlat

Feature/object++

parent 536c7c30
...@@ -183,10 +183,10 @@ else() ...@@ -183,10 +183,10 @@ else()
endif() endif()
if(ENABLE_STRICT) if(ENABLE_STRICT)
list(APPEND STRICT_OPTIONS_CPP "-Werror" "-Wextra" "-Wno-unused-parameter" "-Wno-error=unknown-pragmas" "-Wuninitialized" "-fno-strict-aliasing") list(APPEND STRICT_OPTIONS_CPP "-Werror" "-Wextra" "-Wno-unused-parameter" "-Wno-error=unknown-pragmas" "-Wuninitialized" "-fno-strict-aliasing")
list(APPEND STRICT_OPTIONS_C "-Wstrict-prototypes -Wno-missing-field-initializers" "-Wno-error=unused-result") list(APPEND STRICT_OPTIONS_C " -Wno-missing-field-initializers" "-Wno-error=unused-result")
endif() endif()
# this warning is generated by antlr so ignore it for now # this warning is generated by antlr so ignore it for now
list(APPEND STRICT_OPTIONS_C "-Wno-strict-prototypes" "-Wno-error=sign-compare") list(APPEND STRICT_OPTIONS_C "-Wno-error=sign-compare")
endif() endif()
if(STRICT_OPTIONS_CPP) if(STRICT_OPTIONS_CPP)
list(REMOVE_DUPLICATES STRICT_OPTIONS_CPP) list(REMOVE_DUPLICATES STRICT_OPTIONS_CPP)
......
...@@ -167,19 +167,14 @@ BELLE_SIP_END_DECLS ...@@ -167,19 +167,14 @@ BELLE_SIP_END_DECLS
#ifndef BELLE_SIP_USE_STL #ifndef BELLE_SIP_USE_STL
#define BELLE_SIP_USE_STL 1 #define BELLE_SIP_USE_STL 1
#endif #endif
#if __cplusplus >= 201103L && BELLE_SIP_USE_STL
#if ((defined(WIN32) && defined(__cplusplus)) || __cplusplus >= 201103L) && BELLE_SIP_USE_STL
/*Only Visual Studio 2018 properly defines __cplusplus according to c++ level. */
#include <functional> #include <functional>
typedef std::function<int (unsigned int)> belle_sip_source_cpp_func_t; typedef std::function<int (unsigned int)> belle_sip_source_cpp_func_t;
BELLESIP_EXPORT inline int belle_sip_source_cpp_func(belle_sip_source_cpp_func_t* user_data, unsigned int events)
{
int result = (*user_data)(events);
return result;
}
BELLESIP_EXPORT inline void belle_sip_source_on_remove(belle_sip_source_t* source)
{
delete static_cast<belle_sip_source_cpp_func_t *>(belle_sip_source_get_user_data(source));
belle_sip_source_set_user_data(source,NULL);
}
/*purpose of this function is to simplify c++ timer integration. /*purpose of this function is to simplify c++ timer integration.
* ex: * ex:
...@@ -196,19 +191,13 @@ BELLESIP_EXPORT inline void belle_sip_source_on_remove(belle_sip_source_t* sourc ...@@ -196,19 +191,13 @@ BELLESIP_EXPORT inline void belle_sip_source_on_remove(belle_sip_source_t* sourc
* *
*/ */
BELLESIP_EXPORT inline belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml BELLESIP_EXPORT belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml
, belle_sip_source_cpp_func_t *func , belle_sip_source_cpp_func_t *func
, unsigned int timeout_value_ms , unsigned int timeout_value_ms
, const char* timer_name) , const char* timer_name);
{
belle_sip_source_t* source = belle_sip_main_loop_create_timeout( ml BELLESIP_EXPORT void belle_sip_main_loop_cpp_do_later(belle_sip_main_loop_t *ml, const std::function<void (void)> &func);
, (belle_sip_source_func_t)belle_sip_source_cpp_func
, func
, timeout_value_ms
, timer_name);
belle_sip_source_set_remove_cb(source,belle_sip_source_on_remove);
return source;
}
#endif #endif
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2019 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle-sip/object.h"
#include <memory>
#include <functional>
namespace bellesip{
class ObjectCAccessors;
class BELLESIP_EXPORT Object{
friend ObjectCAccessors;
public:
Object();
Object *ref();
void unref();
virtual belle_sip_error_code marshal(char* buff, size_t buff_size, size_t *offset);
std::string toString()const{
std::string ret(belle_sip_object_to_string(&mObject));
return ret;
}
virtual Object *clone()const;
belle_sip_object_t *getCObject();
const belle_sip_object_t *getCObject()const;
void *getCPtr(){
return static_cast<void*>(getCObject());
}
const void *getCPtr()const{
return static_cast<const void*>(getCObject());
}
static Object *getCppObject(void *);
static const Object *getCppObject(const void *);
protected:
virtual ~Object(); /*the destructor must be kept protected, never public, including for all classes inherting from this*/
Object(const Object &other);
private:
void init();
belle_sip_object_t mObject;
static belle_sip_object_t *sClone(belle_sip_object_t *);
static belle_sip_error_code sMarshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset);
};
/**
* Template class to help define an Object usable in both C and C++
* The template arguments are:
* - _CType : the type used to represent this object in C
* - _CppType : the type used in C++ to implement this object. _CppType is used to be set to the type
* of the class inheriting from HybridObject.
* Example:
* typedef struct _CExample CExample;
* class Example : public HybridObject<CExample, Example>{
* ...
* }
* 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.
*
* 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.
* If you don't care about belle_sip_object_t inheritance in your C api, don't use this.
* An usage example is shown in tester/object_tester.cc .
**/
template <typename _CType, typename _CppType>
class BELLESIP_EXPORT HybridObject : public Object{
public:
HybridObject(){
}
_CType *toC(){
return static_cast<_CType*>(getCPtr());
}
const _CType *toC()const{
return static_cast<const _CType*>(getCPtr());
}
static _CppType *toCpp(_CType *ptr){
return static_cast<_CppType *>(getCppObject(ptr));
}
static const _CppType *toCpp(const _CType *ptr){
return static_cast<const _CppType *>(getCppObject(ptr));
}
protected:
virtual ~HybridObject() = default;
HybridObject(const HybridObject<_CType, _CppType> &other) : Object(other){
}
};
/**
* Convenience function to create a std::shared_ptr that calls Object::unref() instead of delete expression.
*/
template <typename _T, typename... _Args>
BELLESIP_EXPORT std::shared_ptr<_T> make_shared(_Args&&... __args){
return std::shared_ptr<_T>(new _T(std::forward<_Args>(__args)...), std::mem_fun(&Object::unref));
}
}//end of namespace
extern "C" {
BELLE_SIP_DECLARE_VPTR(belle_sip_cpp_object_t);
}
...@@ -84,7 +84,7 @@ typedef unsigned int belle_sip_type_id_t; ...@@ -84,7 +84,7 @@ typedef unsigned int belle_sip_type_id_t;
(belle_sip_object_get_vptr_t)BELLE_SIP_OBJECT_GET_VPTR_FUNC(parent_type), \ (belle_sip_object_get_vptr_t)BELLE_SIP_OBJECT_GET_VPTR_FUNC(parent_type), \
(belle_sip_interface_desc_t**)object_type##interfaces_table (belle_sip_interface_desc_t**)object_type##interfaces_table
#define BELLE_SIP_INSTANCIATE_VPTR2(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned) \ #define BELLE_SIP_INSTANCIATE_VPTR3(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned,is_cpp) \
static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)={ \ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)={ \
BELLE_SIP_VPTR_INIT(object_type,parent_type,unowned), \ BELLE_SIP_VPTR_INIT(object_type,parent_type,unowned), \
(belle_sip_object_destroy_t)destroy, \ (belle_sip_object_destroy_t)destroy, \
...@@ -92,12 +92,16 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object ...@@ -92,12 +92,16 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object
(belle_sip_object_marshal_t)marshal,\ (belle_sip_object_marshal_t)marshal,\
(belle_sip_object_on_first_ref_t)on_first_ref,\ (belle_sip_object_on_first_ref_t)on_first_ref,\
(belle_sip_object_on_last_ref_t)on_last_ref,\ (belle_sip_object_on_last_ref_t)on_last_ref,\
BELLE_SIP_DEFAULT_BUFSIZE_HINT\ BELLE_SIP_DEFAULT_BUFSIZE_HINT,\
is_cpp, 0\
}; \ }; \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) * BELLE_SIP_OBJECT_GET_VPTR_FUNC(object_type)(void){\ BELLE_SIP_OBJECT_VPTR_TYPE(object_type) * BELLE_SIP_OBJECT_GET_VPTR_FUNC(object_type)(void){\
return &BELLE_SIP_OBJECT_VPTR_NAME(object_type); \ return &BELLE_SIP_OBJECT_VPTR_NAME(object_type); \
} }
#define BELLE_SIP_INSTANCIATE_VPTR2(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned) \
BELLE_SIP_INSTANCIATE_VPTR3(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned,FALSE)
#define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal,unowned) \ #define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal,unowned) \
BELLE_SIP_INSTANCIATE_VPTR2(object_type, parent_type, destroy, clone, marshal, NULL, NULL, unowned) BELLE_SIP_INSTANCIATE_VPTR2(object_type, parent_type, destroy, clone, marshal, NULL, NULL, unowned)
...@@ -141,6 +145,7 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object ...@@ -141,6 +145,7 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object
* when they no longer need it. This rule must be strictly followed by developers doing things inside belle-sip. * when they no longer need it. This rule must be strictly followed by developers doing things inside belle-sip.
**/ **/
typedef struct _belle_sip_object belle_sip_object_t; typedef struct _belle_sip_object belle_sip_object_t;
typedef struct _belle_sip_cpp_object belle_sip_cpp_object_t;
typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*); typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*);
...@@ -163,6 +168,8 @@ struct _belle_sip_object_vptr{ ...@@ -163,6 +168,8 @@ struct _belle_sip_object_vptr{
belle_sip_object_on_first_ref_t on_first_ref; /*called when object is ref'd for the first time*/ belle_sip_object_on_first_ref_t on_first_ref; /*called when object is ref'd for the first time*/
belle_sip_object_on_last_ref_t on_last_ref; /*called in unref() when the last reference of the object remains*/ belle_sip_object_on_last_ref_t on_last_ref; /*called in unref() when the last reference of the object remains*/
int tostring_bufsize_hint; /*optimization: you can suggest here the typical size for a to_string() result.*/ int tostring_bufsize_hint; /*optimization: you can suggest here the typical size for a to_string() result.*/
int is_cpp; /*indicates whether this object kind is defined in c++*/
int cpp_offset; /*offset to apply to the belle_sip_object_t to find the pointer to the corresponding bellesip::Object, if any*/
}; };
typedef struct _belle_sip_object_vptr belle_sip_object_vptr_t; typedef struct _belle_sip_object_vptr belle_sip_object_vptr_t;
...@@ -369,7 +376,7 @@ BELLESIP_EXPORT void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_t ...@@ -369,7 +376,7 @@ BELLESIP_EXPORT void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_t
* WHen the object is a sip header, uri or message, this is the textual representation of the header, uri or message. * WHen the object is a sip header, uri or message, this is the textual representation of the header, uri or message.
* This function internally calls belle_sip_object_marshal(). * This function internally calls belle_sip_object_marshal().
**/ **/
BELLESIP_EXPORT char* belle_sip_object_to_string(void* obj); BELLESIP_EXPORT char* belle_sip_object_to_string(const void* obj);
/** /**
* Writes a string representation of the object into the supplied buffer. * Writes a string representation of the object into the supplied buffer.
......
...@@ -150,7 +150,8 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1) ...@@ -150,7 +150,8 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_header_reason_t), BELLE_SIP_TYPE_ID(belle_sip_header_reason_t),
BELLE_SIP_TYPE_ID(belle_sip_header_authentication_info_t), BELLE_SIP_TYPE_ID(belle_sip_header_authentication_info_t),
BELLE_SIP_TYPE_ID(belle_sip_mdns_register_t), BELLE_SIP_TYPE_ID(belle_sip_mdns_register_t),
BELLE_SIP_TYPE_ID(belle_sip_resolver_results_t) BELLE_SIP_TYPE_ID(belle_sip_resolver_results_t),
BELLE_SIP_TYPE_ID(belle_sip_cpp_object_t)
BELLE_SIP_DECLARE_TYPES_END BELLE_SIP_DECLARE_TYPES_END
......
...@@ -160,6 +160,8 @@ if(ANDROID) ...@@ -160,6 +160,8 @@ if(ANDROID)
endif() endif()
set(BELLE_SIP_SOURCE_FILES_CXX set(BELLE_SIP_SOURCE_FILES_CXX
${TUNNEL_SOURCE_FILES_CXX} ${TUNNEL_SOURCE_FILES_CXX}
object++.cc
cpp_utils.cc
) )
if(APPLE) if(APPLE)
set(BELLE_SIP_SOURCE_FILES_OBJC set(BELLE_SIP_SOURCE_FILES_OBJC
...@@ -200,6 +202,7 @@ string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}") ...@@ -200,6 +202,7 @@ string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
if(ENABLE_STATIC) if(ENABLE_STATIC)
add_library(bellesip-static STATIC ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES}) add_library(bellesip-static STATIC ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES})
set_target_properties(bellesip-static PROPERTIES OUTPUT_NAME bellesip) set_target_properties(bellesip-static PROPERTIES OUTPUT_NAME bellesip)
set_target_properties(bellesip-static PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
target_include_directories(bellesip-static PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS}) target_include_directories(bellesip-static PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS})
target_link_libraries(bellesip-static INTERFACE ${LIBS}) target_link_libraries(bellesip-static INTERFACE ${LIBS})
if(NOT "${LINK_FLAGS_STR}" STREQUAL "") if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
...@@ -215,6 +218,7 @@ if(ENABLE_SHARED) ...@@ -215,6 +218,7 @@ if(ENABLE_SHARED)
add_library(bellesip SHARED ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES}) add_library(bellesip SHARED ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES})
set_target_properties(bellesip PROPERTIES SOVERSION 0) set_target_properties(bellesip PROPERTIES SOVERSION 0)
set_target_properties(bellesip PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(bellesip PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(bellesip PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
target_include_directories(bellesip PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS}) target_include_directories(bellesip PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS})
target_link_libraries(bellesip PRIVATE ${LIBS}) target_link_libraries(bellesip PRIVATE ${LIBS})
if(NOT "${LINK_FLAGS_STR}" STREQUAL "") if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
......
...@@ -134,6 +134,9 @@ typedef struct weak_ref{ ...@@ -134,6 +134,9 @@ typedef struct weak_ref{
void *userpointer; void *userpointer;
}weak_ref_t; }weak_ref_t;
#ifdef __cplusplus
extern "C" {
#endif
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid); void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
/*used internally by unref()*/ /*used internally by unref()*/
...@@ -141,6 +144,11 @@ void belle_sip_object_delete(void *obj); ...@@ -141,6 +144,11 @@ void belle_sip_object_delete(void *obj);
void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj); void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj); void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
belle_sip_object_t * _belle_sip_object_init(belle_sip_object_t *obj, belle_sip_object_vptr_t *vptr);
void belle_sip_cpp_object_delete(belle_sip_object_t *obj);
void belle_sip_object_uninit(belle_sip_object_t *obj);
#define belle_sip_object_init(obj) /*nothing*/ #define belle_sip_object_init(obj) /*nothing*/
...@@ -1098,5 +1106,8 @@ belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_t ...@@ -1098,5 +1106,8 @@ belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_t
typedef struct authorization_context authorization_context_t; typedef struct authorization_context authorization_context_t;
BELLESIP_EXPORT void belle_sip_authorization_destroy(authorization_context_t* object); BELLESIP_EXPORT void belle_sip_authorization_destroy(authorization_context_t* object);
#ifdef __cplusplus
}
#endif
#endif #endif
...@@ -91,9 +91,7 @@ void belle_sip_object_dump_active_objects(void){ ...@@ -91,9 +91,7 @@ void belle_sip_object_dump_active_objects(void){
}else belle_sip_warning("No objects leaked."); }else belle_sip_warning("No objects leaked.");
} }
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){ belle_sip_object_t * _belle_sip_object_init(belle_sip_object_t *obj, belle_sip_object_vptr_t *vptr){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(vptr->size);
obj->vptr = vptr; obj->vptr = vptr;
obj->ref = vptr->initially_unowned ? 0 : 1; obj->ref = vptr->initially_unowned ? 0 : 1;
...@@ -106,6 +104,12 @@ belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr ...@@ -106,6 +104,12 @@ belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr
return obj; return obj;
} }
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(vptr->size);
return _belle_sip_object_init(obj, vptr);
}
int belle_sip_object_is_initially_unowned(const belle_sip_object_t *obj){ int belle_sip_object_is_initially_unowned(const belle_sip_object_t *obj){
return obj->vptr->initially_unowned; return obj->vptr->initially_unowned;
} }
...@@ -245,18 +249,29 @@ belle_sip_object_vptr_t *belle_sip_object_t_vptr_get(void){ ...@@ -245,18 +249,29 @@ belle_sip_object_vptr_t *belle_sip_object_t_vptr_get(void){
return &belle_sip_object_t_vptr; return &belle_sip_object_t_vptr;
} }
void belle_sip_object_delete(void *ptr){ void belle_sip_object_uninit(belle_sip_object_t *obj){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
belle_sip_object_vptr_t *vptr; belle_sip_object_vptr_t *vptr;
belle_sip_object_loose_weak_refs(obj); belle_sip_object_loose_weak_refs(obj);
belle_sip_object_remove_from_leak_detector(obj); belle_sip_object_remove_from_leak_detector(obj);
vptr=obj->vptr; vptr = obj->vptr;
while(vptr!=NULL){ while(vptr!=NULL){
if (vptr->destroy) vptr->destroy(obj); if (vptr->destroy) vptr->destroy(obj);
vptr=vptr->get_parent(); vptr=vptr->get_parent();
} }
belle_sip_object_data_clear(obj); belle_sip_object_data_clear(obj);
}
void belle_sip_object_delete(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
if (obj->vptr->is_cpp){
/*This will call delete which calls the destructor chain*/
belle_sip_cpp_object_delete(obj);
return;
}
/*otherwise we're in C, call the destructor chain and free the memory*/
belle_sip_object_uninit(obj);
belle_sip_free(obj); belle_sip_free(obj);
} }
...@@ -553,10 +568,10 @@ belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buf ...@@ -553,10 +568,10 @@ belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buf
} }
static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){ static char * belle_sip_object_to_alloc_string(const belle_sip_object_t *obj, int size_hint){
char *buf=belle_sip_malloc(size_hint); char *buf=belle_sip_malloc(size_hint);
size_t offset=0; size_t offset=0;
belle_sip_error_code error = belle_sip_object_marshal(obj,buf,size_hint-1,&offset); belle_sip_error_code error = belle_sip_object_marshal((belle_sip_object_t *)obj,buf,size_hint-1,&offset);
obj->vptr->tostring_bufsize_hint=size_hint; obj->vptr->tostring_bufsize_hint=size_hint;
if (error==BELLE_SIP_BUFFER_OVERFLOW){ if (error==BELLE_SIP_BUFFER_OVERFLOW){
belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name); belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name);
...@@ -574,14 +589,14 @@ static int get_hint_size(int size){ ...@@ -574,14 +589,14 @@ static int get_hint_size(int size){
return size; return size;
} }
char* belle_sip_object_to_string(void* _obj) { char* belle_sip_object_to_string(const void* _obj) {
belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj); const belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj);
if (obj->vptr->tostring_bufsize_hint!=0){ if (obj->vptr->tostring_bufsize_hint!=0){
return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint); return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint);
}else{ }else{
char buff[BELLE_SIP_MAX_TO_STRING_SIZE]; char buff[BELLE_SIP_MAX_TO_STRING_SIZE];
size_t offset=0; size_t offset=0;
belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff)-1,&offset); belle_sip_error_code error = belle_sip_object_marshal((belle_sip_object_t *)obj,buff,sizeof(buff)-1,&offset);
if (error==BELLE_SIP_BUFFER_OVERFLOW){ if (error==BELLE_SIP_BUFFER_OVERFLOW){
belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name); belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name);
return belle_sip_object_to_alloc_string(obj,get_hint_size(2*(int)offset)); return belle_sip_object_to_alloc_string(obj,get_hint_size(2*(int)offset));
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010-2018 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle-sip/belle-sip.h"
#ifndef BELLE_SIP_USE_STL
#define BELLE_SIP_USE_STL 1
#endif
#if BELLE_SIP_USE_STL
#include <functional>
typedef std::function<int (unsigned int)> belle_sip_source_cpp_func_t;
static int belle_sip_source_cpp_func(belle_sip_source_cpp_func_t* user_data, unsigned int events)
{
int result = (*user_data)(events);
return result;
}
static void belle_sip_source_on_remove(belle_sip_source_t* source)
{
delete static_cast<belle_sip_source_cpp_func_t *>(belle_sip_source_get_user_data(source));
belle_sip_source_set_user_data(source,NULL);
}
belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml
, belle_sip_source_cpp_func_t *func
, unsigned int timeout_value_ms
, const char* timer_name)
{
belle_sip_source_t* source = belle_sip_main_loop_create_timeout( ml
, (belle_sip_source_func_t)belle_sip_source_cpp_func
, func
, timeout_value_ms
, timer_name);
belle_sip_source_set_remove_cb(source,belle_sip_source_on_remove);
return source;
}
static void do_later(void *ud){
std::function<void (void)> *func = static_cast<std::function<void (void)> *>(ud);
(*func)();
delete func;
}
void belle_sip_main_loop_cpp_do_later(belle_sip_main_loop_t *ml, const std::function<void (void)> &func){
belle_sip_main_loop_do_later(ml, do_later, new std::function<void (void)>(func));
}
#endif
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2019 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle-sip/object++.hh"
#include "belle_sip_internal.h"
struct _belle_sip_cpp_object{
belle_sip_object_t base;
};
namespace bellesip{
class ObjectCAccessors{
public:
static belle_sip_error_code sMarshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset){
return Object::getCppObject(obj)->marshal(buff, buff_size, offset);
}
static void doDelete(belle_sip_object_t* obj){
delete Object::getCppObject(obj);
}
};
void Object::init(){
static bool offsetDefined = false;
belle_sip_object_vptr_t *vptr = belle_sip_cpp_object_t_vptr_get();
if (!offsetDefined){
vptr->cpp_offset = (int) ((intptr_t)&mObject - (intptr_t)this);
offsetDefined = true;
}
memset(&mObject, 0, sizeof(mObject)); /*the new allocator does not zero the memory*/
_belle_sip_object_init(&mObject, vptr);
}
Object::Object(){
init();
}
Object::Object(const Object &other){
init();
mObject.vptr->get_parent()->clone(&mObject, &other.mObject); /*belle_sip_object_t own's clone method*/
}
Object::~Object(){
if (mObject.ref != -1){
/*note: throwing an exception here does not work*/
belle_sip_fatal("bellesip::Object [%p] has been destroyed directly with delete operator. This is prohibited, use unref() instead.", this);
}
belle_sip_object_uninit(&mObject);
belle_sip_message("Object destroyed");
}
Object *Object::ref(){
belle_sip_object_ref(&mObject);
return this;
}
void Object::unref(){
belle_sip_object_unref(&mObject);
}
belle_sip_error_code Object::marshal(char* buff, size_t buff_size, size_t *offset){
return mObject.vptr->get_parent()->marshal(&mObject, buff, buff_size, offset); /*default to belle_sip_object_t's implementation*/
}
Object *Object::clone()const{
return new Object(*this);
}
belle_sip_object_t *Object::getCObject(){
return &mObject;
}
const belle_sip_object_t *Object::getCObject()const{
return &mObject;
}
Object *Object::getCppObject(void *ptr){
belle_sip_object_t *obj = BELLE_SIP_OBJECT(ptr);
intptr_t cppaddr = (intptr_t)obj - (intptr_t)obj->vptr->cpp_offset;
return reinterpret_cast<Object*>(cppaddr);
}
const Object *Object::getCppObject(const void *ptr){
return Object::getCppObject((void*)ptr);
}
}//end of namespace
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_cpp_object_t);
BELLE_SIP_INSTANCIATE_VPTR3(belle_sip_cpp_object_t,belle_sip_object_t,NULL,NULL,bellesip::ObjectCAccessors::sMarshal,NULL,NULL,FALSE,TRUE);
void belle_sip_cpp_object_delete(belle_sip_object_t *obj){
bellesip::ObjectCAccessors::doDelete(obj);
}
...@@ -44,6 +44,7 @@ set(SOURCE_FILES_C ...@@ -44,6 +44,7 @@ set(SOURCE_FILES_C
belle_sip_fast_uri_tester.c belle_sip_fast_uri_tester.c
cast_test.c cast_test.c
register_tester.h register_tester.h
object_tester.cc
) )
set(OTHER_FILES set(OTHER_FILES
...@@ -77,6 +78,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") ...@@ -77,6 +78,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set_target_properties(belle_sip_tester_runtime PROPERTIES VS_WINRT_COMPONENT TRUE) set_target_properties(belle_sip_tester_runtime PROPERTIES VS_WINRT_COMPONENT TRUE)
set_target_properties(belle_sip_tester_runtime PROPERTIES LIBRARY_OUTPUT_NAME "BelledonneCommunications.BelleSip.Tester") set_target_properties(belle_sip_tester_runtime PROPERTIES LIBRARY_OUTPUT_NAME "BelledonneCommunications.BelleSip.Tester")
set_target_properties(belle_sip_tester_runtime PROPERTIES LINK_FLAGS "/WINMDFILE:BelledonneCommunications.BelleSip.Tester.winmd") set_target_properties(belle_sip_tester_runtime PROPERTIES LINK_FLAGS "/WINMDFILE:BelledonneCommunications.BelleSip.Tester.winmd")
set_target_properties(belle_sip_tester_runtime PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
install(TARGETS belle_sip_tester_runtime install(TARGETS belle_sip_tester_runtime
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
...@@ -99,6 +101,7 @@ else() ...@@ -99,6 +101,7 @@ else()
add_executable(belle_sip_tester ${USE_BUNDLE} ${SOURCE_FILES_C} ${SOURCE_FILES_OBJC}) add_executable(belle_sip_tester ${USE_BUNDLE} ${SOURCE_FILES_C} ${SOURCE_FILES_OBJC})
set_target_properties(belle_sip_tester PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(belle_sip_tester PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(belle_sip_tester PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
if(NOT "${LINK_FLAGS_STR}" STREQUAL "") if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
set_target_properties(belle_sip_tester PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}") set_target_properties(belle_sip_tester PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
......
...@@ -152,6 +152,7 @@ void belle_sip_tester_init(void(*ftester_printf)(int level, const char *fmt, va_ ...@@ -152,6 +152,7 @@ void belle_sip_tester_init(void(*ftester_printf)(int level, const char *fmt, va_
bc_tester_add_suite(&dialog_test_suite); bc_tester_add_suite(&dialog_test_suite);
bc_tester_add_suite(&refresher_test_suite); bc_tester_add_suite(&refresher_test_suite);
bc_tester_add_suite(&http_test_suite); bc_tester_add_suite(&http_test_suite);
bc_tester_add_suite(&object_test_suite);
} }
void belle_sip_tester_uninit(void) { void belle_sip_tester_uninit(void) {
......
...@@ -46,6 +46,7 @@ extern test_suite_t register_test_suite; ...@@ -46,6 +46,7 @@ extern test_suite_t register_test_suite;
extern test_suite_t dialog_test_suite; extern test_suite_t dialog_test_suite;
extern test_suite_t refresher_test_suite; extern test_suite_t refresher_test_suite;
extern test_suite_t http_test_suite; extern test_suite_t http_test_suite;
extern test_suite_t object_test_suite;