The Battle for Wesnoth  1.19.0-dev
lua_jailbreak_exception.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2024
3  by Mark de Wever <koraq@xs4all.nl>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 /**
19  * Base class for exceptions that want to be thrown 'through' lua.
20  *
21  * Classes derived from this class <b>must call `this->store()` in all of their
22  * constructors</b> and use the @ref IMPLEMENT_LUA_JAILBREAK_EXCEPTION macro
23  * in the class definition. No other classes may derive from classes derived
24  * from this class.
25  */
27 {
28 public:
29  virtual ~lua_jailbreak_exception() noexcept {}
30 
31  /** Depth of recursive luaW_pcall_internal() function calls. */
32  static int jail_depth;
33 
34  /** Stores a copy the current exception to be rethrown. */
35  void store() const noexcept;
36 
37  /**
38  * Rethrows the stored exception.
39  *
40  * It is safe to call this function is no exception is stored.
41  */
42  static void rethrow();
43 
44 protected:
45 
46  /** The exception to be rethrown. */
48 
49 private:
50 
51  /** Clears the current exception. */
52  static void clear() noexcept;
53 
54  /**
55  * Creates a copy of the current exception.
56  *
57  * The copy is allocated with @p new and is implemented by the @ref
58  * IMPLEMENT_LUA_JAILBREAK_EXCEPTION macro.
59  *
60  * @note it's implemented by the subclass to avoid slicing.
61  *
62  * @returns A pointer to a copy of the class on the heap.
63  */
64  virtual lua_jailbreak_exception* clone() const = 0;
65 
66  /**
67  * Executes the exception.
68  *
69  * Throws a copy of the stored @ref jailbreak_exception. The caller is
70  * responsible for clearing @ref jailbreak_exception after the throw.
71  * The function is implemented by the @ref
72  * IMPLEMENT_LUA_JAILBREAK_EXCEPTION macro.
73  *
74  * @note it's implemented by the subclass to avoid slicing.
75  *
76  * @pre jailbreak_exception != nullptr
77  */
78  virtual void execute() = 0;
79 };
80 
81 /**
82  * Helper macro for classes deriving from @ref lua_jailbreak_exception.
83  *
84  * @ref lua_jailbreak_exception has several pure virtual functions, this
85  * macro implements them properly. This macro needs to be placed in the
86  * definition of the most derived class, which uses @ref
87  * lua_jailbreak_exception as baseclass.
88  *
89  * @param type The type of the class whc
90  */
91 #define IMPLEMENT_LUA_JAILBREAK_EXCEPTION(type) \
92  \
93  virtual type* clone() const final { return new type(*this); } \
94  \
95  virtual void execute() final \
96  { \
97  type exception(dynamic_cast<type&>(*jailbreak_exception)); \
98  throw exception; \
99  }
Base class for exceptions that want to be thrown 'through' lua.
static lua_jailbreak_exception * jailbreak_exception
The exception to be rethrown.
virtual void execute()=0
Executes the exception.
void store() const noexcept
Stores a copy the current exception to be rethrown.
static void rethrow()
Rethrows the stored exception.
static void clear() noexcept
Clears the current exception.
virtual lua_jailbreak_exception * clone() const =0
Creates a copy of the current exception.
virtual ~lua_jailbreak_exception() noexcept
static int jail_depth
Depth of recursive luaW_pcall_internal() function calls.