File indexing completed on 2024-09-22 04:53:10
0001 /* 0002 * SPDX-FileCopyrightText: 2008 Trevor Pounds 0003 * SPDX-License-Identifier: MIT 0004 */ 0005 0006 #ifndef __MOCKITOPP_DYNAMIC_OBJECT_HPP__ 0007 #define __MOCKITOPP_DYNAMIC_OBJECT_HPP__ 0008 0009 #include <mockitopp/exceptions.hpp> 0010 #include <mockitopp/detail/stubbing/dynamic_vfunction.hpp> 0011 #include <mockitopp/detail/stubbing/proxy_vfunction.hpp> 0012 #include <mockitopp/detail/util/remove_member_function_pointer_cv.hpp> 0013 0014 namespace mockitopp 0015 { 0016 namespace detail 0017 { 0018 /** 0019 * helper class to find the vtable offset given a member function pointer 0020 */ 0021 struct vtable_offset_helper 0022 { 0023 template <typename T> 0024 static int get(T ptr2member) 0025 { 0026 vtable_offset_helper f; 0027 #pragma GCC diagnostic push 0028 #pragma GCC diagnostic ignored "-Wcast-function-type" 0029 return (f.*reinterpret_cast<int (vtable_offset_helper::*)()>(ptr2member))(); 0030 #pragma GCC diagnostic pop 0031 } 0032 0033 virtual int offset0() { return 0; } 0034 virtual int offset1() { return 1; } 0035 virtual int offset2() { return 2; } 0036 virtual int offset3() { return 3; } 0037 virtual int offset4() { return 4; } 0038 virtual int offset5() { return 5; } 0039 virtual int offset6() { return 6; } 0040 virtual int offset7() { return 7; } 0041 virtual int offset8() { return 8; } 0042 virtual int offset9() { return 9; } 0043 virtual int offset10() { return 10; } 0044 virtual int offset11() { return 11; } 0045 virtual int offset12() { return 12; } 0046 virtual int offset13() { return 13; } 0047 virtual int offset14() { return 14; } 0048 virtual int offset15() { return 15; } 0049 virtual int offset16() { return 16; } 0050 virtual int offset17() { return 17; } 0051 virtual int offset18() { return 18; } 0052 virtual int offset19() { return 19; } 0053 virtual int offset20() { return 20; } 0054 virtual int offset21() { return 21; } 0055 virtual int offset22() { return 22; } 0056 virtual int offset23() { return 23; } 0057 virtual int offset24() { return 24; } 0058 virtual int offset25() { return 25; } 0059 virtual int offset26() { return 26; } 0060 virtual int offset27() { return 27; } 0061 virtual int offset28() { return 28; } 0062 virtual int offset29() { return 29; } 0063 virtual int offset30() { return 30; } 0064 virtual int offset31() { return 31; } 0065 virtual int offset32() { return 32; } 0066 virtual int offset33() { return 33; } 0067 virtual int offset34() { return 34; } 0068 virtual int offset35() { return 35; } 0069 virtual int offset36() { return 36; } 0070 virtual int offset37() { return 37; } 0071 virtual int offset38() { return 38; } 0072 virtual int offset39() { return 39; } 0073 virtual int offset40() { return 40; } 0074 virtual int offset41() { return 41; } 0075 virtual int offset42() { return 42; } 0076 virtual int offset43() { return 43; } 0077 virtual int offset44() { return 44; } 0078 virtual int offset45() { return 45; } 0079 virtual int offset46() { return 46; } 0080 virtual int offset47() { return 47; } 0081 virtual int offset48() { return 48; } 0082 virtual int offset49() { return 49; } 0083 0084 virtual ~vtable_offset_helper() {} 0085 }; 0086 0087 /** 0088 * implementation class for pseduo-dynamically defining an interface 0089 */ 0090 struct dynamic_object 0091 { 0092 struct vtable { 0093 void* vbase_offset; 0094 void* vcall_offset; 0095 void* offset_to_top; 0096 void* type_info; 0097 void* functions[50]; 0098 }; 0099 0100 void* vtable_object_ptr; 0101 void* vtable_mocks[50]; 0102 vtable* vtable_actual_ptr; 0103 0104 dynamic_object() 0105 : vtable_actual_ptr(new vtable) 0106 { 0107 vtable_actual_ptr->vbase_offset = 0; 0108 vtable_actual_ptr->vcall_offset = 0; 0109 vtable_actual_ptr->offset_to_top = 0; 0110 vtable_actual_ptr->type_info = 0; 0111 for(int i = 0; i < 50; i++) 0112 { 0113 vtable_actual_ptr->functions[i] = horrible_cast<void*>(&dynamic_object::missing_vfunction); 0114 vtable_mocks[i] = 0; 0115 } 0116 vtable_object_ptr = vtable_actual_ptr->functions; 0117 } 0118 0119 ~dynamic_object() 0120 { 0121 for(int i = 0; i < 50; i++) 0122 { 0123 if(vtable_mocks[i] != 0) 0124 { delete reinterpret_cast<dynamic_vfunction_base*>(vtable_mocks[i]); } 0125 } 0126 delete vtable_actual_ptr; 0127 } 0128 0129 template <typename M> 0130 dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>& define_function(M ptr2member) 0131 { 0132 int offset = vtable_offset_helper::get(ptr2member); 0133 if(vtable_mocks[offset] == 0) 0134 { 0135 vtable_actual_ptr->functions[offset] = proxy_vfunction_factory<M>::get(ptr2member); 0136 vtable_mocks[offset] = new dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>(); 0137 } 0138 return *reinterpret_cast<dynamic_vfunction<typename remove_member_function_pointer_cv<M>::type>*>(vtable_mocks[offset]); 0139 } 0140 0141 void missing_vfunction() 0142 { throw missing_implementation_exception(); } 0143 0144 private: 0145 dynamic_object(const dynamic_object &); 0146 dynamic_object &operator=(const dynamic_object &); 0147 }; 0148 } // namespace detail 0149 } // namespace mockitopp 0150 0151 #endif //__MOCKITOPP_DYNAMIC_OBJECT_HPP__