Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
common/scope_exit.h
ShadPKG / common / scope_exit.h
1// SPDX-FileCopyrightText: 2014 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3 
4#pragma once
5 
6#include <utility>
7 
8namespace detail {
9template <class F>
10class ScopeGuard {
11private:
12 F f;
13 bool active;
14 
15public:
16 constexpr ScopeGuard(F f_) : f(std::move(f_)), active(true) {}
17 constexpr ~ScopeGuard() {
18 if (active) {
19 f();
20 }
21 }
22 constexpr void Cancel() {
23 active = false;
24 }
25 
26 constexpr ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) {
27 rhs.Cancel();
28 }
29 
30 ScopeGuard& operator=(ScopeGuard&& rhs) = delete;
31};
32 
33template <class F>
34constexpr ScopeGuard<F> MakeScopeGuard(F f) {
35 return ScopeGuard<F>(std::move(f));
36}
37 
38enum class ScopeGuardOnExit {};
39 
40template <typename F>
41constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
42 return ScopeGuard<F>(std::forward<F>(f));
43}
44 
45} // namespace detail
46 
47#define CONCATENATE_IMPL(s1, s2) s1##s2
48#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
49 
50#ifdef __COUNTER__
51#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__)
52#else
53#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__)
54#endif
55 
56/**
57 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
58 * used when the caller might want to cancel the ScopeExit.
59 */
60#define SCOPE_GUARD detail::ScopeGuardOnExit() + [&]()
61 
62/**
63 * This macro allows you to conveniently specify a block of code that will run on scope exit. Handy
64 * for doing ad-hoc clean-up tasks in a function with multiple returns.
65 *
66 * Example usage:
67 * \code
68 * const int saved_val = g_foo;
69 * g_foo = 55;
70 * SCOPE_EXIT{ g_foo = saved_val; };
71 *
72 * if (Bar()) {
73 * return 0;
74 * } else {
75 * return 20;
76 * }
77 * \endcode
78 */
79#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = SCOPE_GUARD
80