Elfspy/elfspy/Fake.h

71 lines
1.5 KiB
C++

#ifndef ELFSPY_FAKE_H
#define ELFSPY_FAKE_H
#include "elfspy/Lambda.h"
#include <memory>
#include <vector>
namespace spy
{
/**
* @namespace spy
* @class Fake
* This replaces an existing function with another function, so that all calls
* to the program are made to the other function.
* The constructor installs the new function in place of the function, the
* destructor uninstalls it
*/
class FakeI {
};
extern std::vector<FakeI *> fake_list;
void delete_mocks (void) {
while (fake_list.size () != 0) {
auto index = fake_list.size () - 1;
auto element = fake_list[index];
fake_list.erase (fake_list.begin() + index);
delete element;
}
}
template <typename H, typename ReturnType, typename... ArgTypes>
class Fake : FakeI
{
public:
Fake(H& hook, ReturnType (*func)(ArgTypes...));
~Fake();
private:
H& hook_;
ReturnType (*func_)(ArgTypes...);
};
template <typename H, typename ReturnType, typename... ArgTypes>
inline Fake<H, ReturnType, ArgTypes...>::
Fake(H& hook, ReturnType (*func)(ArgTypes...))
:hook_(hook)
{
func_ = hook_.patch(func);
}
template <typename H, typename ReturnType, typename... ArgTypes>
inline Fake<H, ReturnType, ArgTypes...>::~Fake()
{
hook_.patch(func_);
}
template <typename H, typename ReturnType, typename... ArgTypes>
inline auto new_fake(H& hook, ReturnType (*patch)(ArgTypes...))
-> Fake<H, ReturnType, ArgTypes...>*
{
auto instance = std::make_shared<Fake<H, ReturnType, ArgTypes...>>(hook, patch);
fake_list.push_back (instance);
return instance;
}
} // namespace elfspy
#endif