The Battle for Wesnoth  1.19.0-dev
wml_exception.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 - 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 /**
17  * @file
18  * Add a special kind of assert to validate whether the input from WML
19  * doesn't contain any problems that might crash the game.
20  */
21 
22 #pragma once
23 
25 
26 #include <string>
27 
28 /**
29  * The macro to use for the validation of WML
30  *
31  * @param cond The condition to test, if false and exception is generated.
32  * @param message The translatable message to show at the user.
33  */
34 #ifndef __func__
35  #ifdef __FUNCTION__
36  #define __func__ __FUNCTION__
37  #endif
38 #endif
39 
40 #define VALIDATE(cond, message) \
41  do { \
42  if(!(cond)) { \
43  throw_wml_exception(#cond, __FILE__, __LINE__, __func__, message); \
44  } \
45  } while(false)
46 
47 #define VALIDATE_WML_CHILD(cfg, key, message) \
48  ([](auto c, auto k) { \
49  if(auto child = c.optional_child(k)) { return *child; } \
50  throw_wml_exception( "Missing [" key "]", __FILE__, __LINE__, __func__, message); \
51  })(cfg, key) \
52 
53 #define VALIDATE_WITH_DEV_MESSAGE(cond, message, dev_message) \
54  do { \
55  if(!(cond)) { \
56  throw_wml_exception(#cond \
57  , __FILE__ \
58  , __LINE__ \
59  , __func__ \
60  , message \
61  , dev_message); \
62  } \
63  } while(false)
64 
65 #define FAIL(message) \
66  do { \
67  throw_wml_exception(nullptr, __FILE__, __LINE__, __func__, message); \
68  } while(false)
69 
70 #define FAIL_WITH_DEV_MESSAGE(message, dev_message) \
71  do { \
72  throw_wml_exception(nullptr \
73  , __FILE__ \
74  , __LINE__ \
75  , __func__ \
76  , message \
77  , dev_message); \
78  } while(false)
79 
80 /**
81  * Helper function, don't call this directly.
82  *
83  * @param cond The textual presentation of the test that failed.
84  * @param file The file in which the test failed.
85  * @param line The line at which the test failed.
86  * @param function The function in which the test failed.
87  * @param message The translated message to show the user.
88  * @param dev_message Any additional information that might be useful to a developer.
89  */
90 [[noreturn]] void throw_wml_exception(
91  const char* cond
92  , const char* file
93  , int line
94  , const char *function
95  , const std::string& message
96  , const std::string& dev_message = "");
97 
98 /** Helper class, don't construct this directly. */
99 struct wml_exception final
100  : public lua_jailbreak_exception
101 {
102  wml_exception(const std::string& user_msg, const std::string& dev_msg)
103  : user_message(user_msg)
104  , dev_message(dev_msg)
105  {
106  this->store();
107  }
108 
109  ~wml_exception() noexcept {}
110 
111  /**
112  * The message for the user explaining what went wrong. This message can
113  * be translated so the user gets a explanation in his/her native tongue.
114  */
115  std::string user_message;
116 
117  /**
118  * The message for developers telling which problem was triggered, this
119  * shouldn't be translated. It's hard for a dev to parse errors in
120  * foreign tongues.
121  */
122  std::string dev_message;
123 
124  /**
125  * Shows the error in a dialog.
126  */
127  void show() const;
128 private:
130 };
131 
132 /**
133  * Returns a standard message for a missing wml key (attribute).
134  *
135  * @param section The section in which the key should appear.
136  * Shouldn't include leading or trailing brackets,
137  * as they're already in the translatable string;
138  * but if it has to include brackets in the middle,
139  * for example "parent][child][section", then it
140  * seems reasonable include the outer ones too.
141  * @param key The omitted key.
142  * @param primary_key The primary key of the section.
143  * @param primary_value The value of the primary key (mandatory if
144  * primary key isn't empty).
145  *
146  * @returns The error message.
147  */
148 std::string missing_mandatory_wml_key(
149  const std::string& section
150  , const std::string& key
151  , const std::string& primary_key = ""
152  , const std::string& primary_value = "");
153 
154 /**
155  * Returns a standard message for a missing wml child (tag).
156  *
157  * @param section The section in which the child should appear.
158  * Same meaning as for missing_mandatory_wml_key().
159  * @param tag The omitted tag.
160  *
161  * @returns The error message.
162  */
163 std::string missing_mandatory_wml_tag(
164  const std::string& section
165  , const std::string& tag);
Base class for exceptions that want to be thrown 'through' lua.
void store() const noexcept
Stores a copy the current exception to be rethrown.
#define IMPLEMENT_LUA_JAILBREAK_EXCEPTION(type)
Helper macro for classes deriving from lua_jailbreak_exception.
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:180
Helper class, don't construct this directly.
wml_exception(const std::string &user_msg, const std::string &dev_msg)
void show() const
Shows the error in a dialog.
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated.
std::string user_message
The message for the user explaining what went wrong.
~wml_exception() noexcept
std::string missing_mandatory_wml_key(const std::string &section, const std::string &key, const std::string &primary_key="", const std::string &primary_value="")
Returns a standard message for a missing wml key (attribute).
std::string missing_mandatory_wml_tag(const std::string &section, const std::string &tag)
Returns a standard message for a missing wml child (tag).
void throw_wml_exception(const char *cond, const char *file, int line, const char *function, const std::string &message, const std::string &dev_message="")
Helper function, don't call this directly.