The Battle for Wesnoth  1.19.22+dev
wml_exception.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 - 2025
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 std::exception
101 {
102  enum class error_type {
103  INVALID_WML = 0,
104  GUI_LAYOUT_FAILURE = -1
105  };
106 
108  const std::string& user_msg,
109  const std::string& dev_msg,
111  )
112  : user_message(user_msg)
113  , dev_message(dev_msg)
114  , type(error_type)
115  {
116  }
117 
118  ~wml_exception() noexcept {}
119 
120  /**
121  * The message for the user explaining what went wrong. This message can
122  * be translated so the user gets a explanation in his/her native tongue.
123  */
124  std::string user_message;
125 
126  /**
127  * The message for developers telling which problem was triggered, this
128  * shouldn't be translated. It's hard for a dev to parse errors in
129  * foreign tongues.
130  */
131  std::string dev_message;
132 
133  /**
134  * Indicates the category of the error handled by this expection.
135  * Useful to detect the type of error without checking the detailed
136  * messages, especially in unit tests.
137  */
139 
140  /**
141  * Shows the error in a dialog.
142  */
143  void show() const;
144 };
145 
146 /**
147  * Returns a standard message for a missing wml key (attribute).
148  *
149  * @param section The section in which the key should appear.
150  * Shouldn't include leading or trailing brackets,
151  * as they're already in the translatable string;
152  * but if it has to include brackets in the middle,
153  * for example "parent][child][section", then it
154  * seems reasonable include the outer ones too.
155  * @param key The omitted key.
156  * @param primary_key The primary key of the section.
157  * @param primary_value The value of the primary key (mandatory if
158  * primary key isn't empty).
159  *
160  * @returns The error message.
161  */
162 std::string missing_mandatory_wml_key(
163  const std::string& section
164  , const std::string& key
165  , const std::string& primary_key = ""
166  , const std::string& primary_value = "");
167 
168 /**
169  * Returns a standard message for a missing wml child (tag).
170  *
171  * @param section The section in which the child should appear.
172  * Same meaning as for missing_mandatory_wml_key().
173  * @param tag The omitted tag.
174  *
175  * @returns The error message.
176  */
177 std::string missing_mandatory_wml_tag(
178  const std::string& section
179  , const std::string& tag);
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:189
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
Definition: markup.hpp:45
Helper class, don't construct this directly.
error_type type
Indicates the category of the error handled by this expection.
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.
wml_exception(const std::string &user_msg, const std::string &dev_msg, const error_type error_type=error_type::INVALID_WML)
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.