1 /**
2  * @file
3  * @brief System independent functions
4 **/
5 
6 #pragma once
7 
8 #include <cctype>
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 #include <unordered_set>
14 
15 #include "defines.h"
16 #include "coord-def.h"
17 #include "description-level-type.h"
18 #include "enum.h"
19 
20 using std::string;
21 using std::unique_ptr;
22 using std::vector;
23 
24 bool key_is_escape(int key);
25 
26 // numeric string functions
27 
28 #define CASE_ESCAPE case ESCAPE: case CONTROL('G'): case -1:
29 
30 // Unscales a fixed-point number, rounding up.
unscale_round_up(int number,int scale)31 static inline int unscale_round_up(int number, int scale)
32 {
33     return (number + scale - 1) / scale;
34 }
35 
36 // Chinese rod numerals are _not_ digits for our purposes.
isadigit(int c)37 static inline bool isadigit(int c)
38 {
39     return c >= '0' && c <= '9';
40 }
41 
42 // 'ä' is a letter, but not a valid inv slot/etc.
isalower(int c)43 static inline bool isalower(int c)
44 {
45     return c >= 'a' && c <= 'z';
46 }
47 
isaupper(int c)48 static inline bool isaupper(int c)
49 {
50     return c >= 'A' && c <= 'Z';
51 }
52 
isaalpha(int c)53 static inline bool isaalpha(int c)
54 {
55     return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
56 }
57 
isaalnum(int c)58 static inline bool isaalnum(int c)
59 {
60     return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
61 }
62 
toalower(char32_t c)63 static inline char32_t toalower(char32_t c)
64 {
65     return isaupper(c) ? c + 'a' - 'A' : c;
66 }
67 
68 // Same thing with signed int, so we can pass though -1 undisturbed.
toalower(int c)69 static inline int toalower(int c)
70 {
71     return isaupper(c) ? c + 'a' - 'A' : c;
72 }
73 
toaupper(char32_t c)74 static inline char32_t toaupper(char32_t c)
75 {
76     return isalower(c) ? c + 'A' - 'a' : c;
77 }
78 
79 // Same thing with signed int, so we can pass though -1 undisturbed.
toaupper(int c)80 static inline int toaupper(int c)
81 {
82     return isalower(c) ? c + 'A' - 'a' : c;
83 }
84 
tolower_safe(T c)85 template<typename T> inline T tolower_safe(T c)
86 {
87     return isaupper(c) ? toalower(c) : tolower(c);
88 }
89 
toupper_safe(T c)90 template<typename T> inline T toupper_safe(T c)
91 {
92     return isalower(c) ? toaupper(c) : toupper(c);
93 }
94 
95 int numcmp(const char *a, const char *b, int limit = 0);
96 bool numcmpstr(const string &a, const string &b);
97 
98 bool version_is_stable(const char *ver);
99 
100 // String "tags"
101 #define TAG_UNFOUND -20404
102 bool strip_tag(string &s, const string &tag, bool nopad = false);
103 int strip_number_tag(string &s, const string &tagprefix);
104 vector<string> strip_multiple_tag_prefix(string &s, const string &tagprefix);
105 string strip_tag_prefix(string &s, const string &tagprefix);
106 const string tag_without_prefix(const string &s, const string &tagprefix);
107 unordered_set<string> parse_tags(const string &tags);
108 bool parse_int(const char *s, int &i);
109 
110 // String 'descriptions'
111 description_level_type description_type_by_name(const char *desc);
112 
113 bool shell_safe(const char *file);
114 
115 string unwrap_desc(string&& desc);
116 
117 /** Ignore any number of arguments and return true.
118  *
119  * @return true
120  */
always_true(Ts...)121 template<class ... Ts> bool always_true(Ts ...) { return true; }
122 
123 /** Remove an element from a vector without preserving order.
124  *  The indicated element is replaced by the last element of the vector.
125  *
126  * @tparam Z The value type of the vector.
127  * @param vec The vector to modify.
128  * @param which The index of the element to remove.
129  */
130 template <typename Z>
erase_any(vector<Z> & vec,unsigned long which)131 void erase_any(vector<Z> &vec, unsigned long which)
132 {
133     if (which != vec.size() - 1)
134         vec[which] = std::move(vec[vec.size() - 1]);
135     vec.pop_back();
136 }
137 
138 /** A comparator to compare pairs by their second elements.
139  *
140  * @tparam T  The type of the pairs (not the second element!)
141  * @param left,right  The pairs to be compared.
142  * @return true if left.second > right.second, false otherwise.
143  */
144 template<typename T>
145 struct greater_second
146 {
operatorgreater_second147     bool operator()(const T & left, const T & right)
148     {
149         return left.second > right.second;
150     }
151 };
152 
153 /** Delete all the pointers in a container and clear the container.
154  *
155  * @tparam T The type of the container; must be a container of pointers
156  *           to non-arrays.
157  * @param collection The container to clear.
158  */
159 template<class T>
deleteAll(T & collection)160 static void deleteAll(T& collection)
161 {
162     for (auto ptr : collection)
163         delete ptr;
164     collection.clear();
165 }
166 
167 /** Find a map element by key, and return a pointer to its value.
168  *
169  * @tparam M The type of the map; may be const.
170  * @param map The map in which to do the lookup.
171  * @param obj The key to search for.
172  * @return a pointer to the value associated with obj if found,
173  *         otherwise null. The pointer is const if the map is.
174  */
175 template<class M>
176 auto map_find(M &map, const typename M::key_type &obj)
177     -> decltype(&map.begin()->second)
178 {
179     auto it = map.find(obj);
180     return it == map.end() ? nullptr : &it->second;
181 }
182 
183 /** Find a map element by key, and return its value or a default.
184  *  Only intended for use with simple map values where copying is not
185  *  a concern; use map_find if the returned value should not be
186  *  copied.
187  *
188  * @tparam M The type of the map; may be const.
189  * @param map The map in which to do the lookup.
190  * @param key The key to search for.
191  * @param unfound The object to return if the key was not found.
192  *
193  * @return a copy of the value associated with key if found, otherwise
194  *         a copy of unfound.
195  */
196 template<class M>
lookup(M & map,const typename M::key_type & key,const typename M::mapped_type & unfound)197 typename M::mapped_type lookup(M &map, const typename M::key_type &key,
198                                const typename M::mapped_type &unfound)
199 {
200     auto it = map.find(key);
201     return it == map.end() ? unfound : it->second;
202 }
203 
204 // Delete when we upgrade to C++14!
205 #ifndef TARGET_COMPILER_VC
206 template<typename T, typename... Args>
make_unique(Args &&...args)207 unique_ptr<T> make_unique(Args&&... args)
208 {
209     return unique_ptr<T>(new T(forward<Args>(args)...));
210 }
211 #endif
212 /** Remove from a container all elements matching a predicate.
213  *
214  * @tparam C the container type. Must be reorderable (not a map or set!),
215  *           and must provide an erase() method taking two iterators.
216  * @tparam P the predicate type, typically but not necessarily
217  *           function<bool (const C::value_type &)>
218  * @param container The container to modify.
219  * @param pred The predicate to test.
220  *
221  * @post The container contains only those elements for which pred(elt)
222  *       returns false, in the same relative order.
223  */
224 template<class C, class P>
erase_if(C & container,P pred)225 void erase_if(C &container, P pred)
226 {
227     container.erase(remove_if(begin(container), end(container), pred),
228                     end(container));
229 }
230 
231 /** Remove from a container all elements with a given value.
232  *
233  * @tparam C the container type. Must be reorderable (not a map or set!),
234  *           must provide an erase() method taking two iterators, and
235  *           must provide a value_type type member.
236  * @param container The container to modify.
237  * @param val The value to remove.
238  *
239  * @post The container contains only those elements not equal to val, in the
240  *       in the same relative order.
241  */
242 template<class C>
erase_val(C & container,const typename C::value_type & val)243 void erase_val(C &container, const typename C::value_type &val)
244 {
245     container.erase(remove(begin(container), end(container), val),
246                     end(container));
247 }
248 
sqr(int x)249 static inline int sqr(int x)
250 {
251     return x * x;
252 }
253 
254 unsigned int isqrt(unsigned int x);
255 int isqrt_ceil(int x);
256 
testbits(uint64_t flags,uint64_t test)257 static inline bool testbits(uint64_t flags, uint64_t test)
258 {
259     return (flags & test) == test;
260 }
261 
262 template<class E, int Exp>
testbits(enum_bitfield<E,Exp> flags,enum_bitfield<E,Exp> test)263 static inline bool testbits(enum_bitfield<E, Exp> flags,
264                             enum_bitfield<E, Exp> test)
265 {
266     return (flags & test) == test;
267 }
268 
269 template<class E, int Exp>
testbits(enum_bitfield<E,Exp> flags,E test)270 static inline bool testbits(enum_bitfield<E, Exp> flags, E test)
271 {
272     return (flags & test) == test;
273 }
274 
275 coord_def cgetsize(GotoRegion region = GOTO_CRT);
276 void cscroll(int n, GotoRegion region);
277 
278 string untag_tiles_console(string s);
279 string colour_string(string in, int col);
280 
281 #ifdef TARGET_OS_WINDOWS
282 enum taskbar_pos
283 {
284     TASKBAR_NO      = 0x00,
285     TASKBAR_BOTTOM  = 0x01,
286     TASKBAR_TOP     = 0x02,
287     TASKBAR_LEFT    = 0x04,
288     TASKBAR_RIGHT   = 0x08,
289     TASKBAR_H       = 0x03,
290     TASKBAR_V       = 0x0C
291 };
292 
293 int get_taskbar_size();
294 taskbar_pos get_taskbar_pos();
295 void text_popup(const string& text, const wchar_t *caption);
296 #endif
297 
298 class mouse_control
299 {
300 public:
301     mouse_control(mouse_mode mode);
302     ~mouse_control();
current_mode()303     static mouse_mode current_mode() { return ms_current_mode; }
304 
305 private:
306     mouse_mode m_previous_mode;
307     static mouse_mode ms_current_mode;
308 };
309 
310 void init_signals();
311 void release_cli_signals();
312