File indexing completed on 2024-09-22 04:53:10
0001 #ifndef __MOCKITOPP_DYNAMIC_OBJECT_HPP__ 0002 #define __MOCKITOPP_DYNAMIC_OBJECT_HPP__ 0003 0004 #include <mockitopp/exceptions.hpp> 0005 #include <mockitopp/detail/stubbing/dynamic_vfunction.hpp> 0006 #include <mockitopp/detail/stubbing/proxy_vfunction.hpp> 0007 #include <mockitopp/detail/util/remove_member_function_pointer_cv.hpp> 0008 0009 namespace mockitopp 0010 { 0011 namespace detail 0012 { 0013 /** 0014 * helper class to find the vtable offset given a member function pointer 0015 */ 0016 struct vtable_offset_helper 0017 { 0018 template <typename T> 0019 static int get(T ptr2member) 0020 { 0021 vtable_offset_helper f; 0022 #pragma GCC diagnostic push 0023 #pragma GCC diagnostic ignored "-Wcast-function-type" 0024 return (f.*reinterpret_cast<int (vtable_offset_helper::*)()>(ptr2member))(); 0025 #pragma GCC diagnostic pop 0026 } 0027 0028 include(`mockitopp/detail/m4/REPEAT.m4')dnl 0029 define(`DEFINE_VTABLE_OFFSET_HELPER_FUNCTION', ` virtual int offset$1() { return $1; } 0030 ')dnl 0031 M4_REPEAT(MOCKITOPP_MAX_VIRTUAL_FUNCTIONS, `DEFINE_VTABLE_OFFSET_HELPER_FUNCTION')dnl 0032 0033 virtual ~vtable_offset_helper() {} 0034 }; 0035 0036 /** 0037 * implementation class for pseduo-dynamically defining an interface 0038 */ 0039 struct dynamic_object 0040 { 0041 struct vtable { 0042 void* vbase_offset; 0043 void* vcall_offset; 0044 void* offset_to_top; 0045 void* type_info; 0046 void* functions[MOCKITOPP_MAX_VIRTUAL_FUNCTIONS]; 0047 }; 0048 0049 void* vtable_object_ptr; 0050 void* vtable_mocks[MOCKITOPP_MAX_VIRTUAL_FUNCTIONS]; 0051 vtable* vtable_actual_ptr; 0052 0053 dynamic_object() 0054 : vtable_actual_ptr(new vtable) 0055 { 0056 vtable_actual_ptr->vbase_offset = 0; 0057 vtable_actual_ptr->vcall_offset = 0; 0058 vtable_actual_ptr->offset_to_top = 0; 0059 vtable_actual_ptr->type_info = 0; 0060 for(int i = 0; i < MOCKITOPP_MAX_VIRTUAL_FUNCTIONS; i++) 0061 { 0062 vtable_actual_ptr->functions[i] = horrible_cast<void*>(&dynamic_object::missing_vfunction); 0063 vtable_mocks[i] = 0; 0064 } 0065 vtable_object_ptr = vtable_actual_ptr->functions; 0066 } 0067 0068 ~dynamic_object() 0069 { 0070 for(int i = 0; i < MOCKITOPP_MAX_VIRTUAL_FUNCTIONS; i++) 0071 { 0072 if(vtable_mocks[i] != 0) 0073 { delete reinterpret_cast<dynamic_vfunction_base*>(vtable_mocks[i]); } 0074 } 0075 delete vtable_actual_ptr; 0076 } 0077 0078 template <typename M> 0079 dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>& define_function(M ptr2member) 0080 { 0081 int offset = vtable_offset_helper::get(ptr2member); 0082 if(vtable_mocks[offset] == 0) 0083 { 0084 vtable_actual_ptr->functions[offset] = proxy_vfunction_factory<M>::get(ptr2member); 0085 vtable_mocks[offset] = new dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>(); 0086 } 0087 return *reinterpret_cast<dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>*>(vtable_mocks[offset]); 0088 } 0089 0090 void missing_vfunction() 0091 { throw missing_implementation_exception(); } 0092 }; 0093 } // namespace detail 0094 } // namespace mockitopp 0095 0096 #endif //__MOCKITOPP_DYNAMIC_OBJECT_HPP__