anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
anope.h (29522B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #ifndef ANOPE_H 13 #define ANOPE_H 14 15 #include <signal.h> 16 17 #include "hashcomp.h" 18 19 namespace Anope 20 { 21 /** 22 * A wrapper string class around all the other string classes, this class will 23 * allow us to only require one type of string everywhere that can be converted 24 * at any time to a specific type of string. 25 */ 26 class CoreExport string 27 { 28 private: 29 /** 30 * The actual string is stored in an std::string as it can be converted to 31 * ci::string, or a C-style string at any time. 32 */ 33 std::string _string; 34 public: 35 /** 36 * Extras. 37 */ 38 typedef std::string::iterator iterator; 39 typedef std::string::const_iterator const_iterator; 40 typedef std::string::reverse_iterator reverse_iterator; 41 typedef std::string::const_reverse_iterator const_reverse_iterator; 42 typedef std::string::size_type size_type; 43 static const size_type npos = static_cast<size_type>(-1); 44 45 /** 46 * Constructors that can take in any type of string. 47 */ 48 string() : _string("") { } 49 string(char chr) : _string() { _string = chr; } 50 string(size_type n, char chr) : _string(n, chr) { } 51 string(const char *_str) : _string(_str) { } 52 string(const char *_str, size_type n) : _string(_str, n) { } 53 string(const std::string &_str) : _string(_str) { } 54 string(const ci::string &_str) : _string(_str.c_str()) { } 55 string(const string &_str, size_type pos, size_type n = npos) : _string(_str._string, pos, n) { } 56 template <class InputIterator> string(InputIterator first, InputIterator last) : _string(first, last) { } 57 #if __cplusplus >= 201103L 58 string(const string &) = default; 59 #endif 60 61 /** 62 * Assignment operators, so any type of string can be assigned to this class. 63 */ 64 inline string &operator=(char chr) { this->_string = chr; return *this; } 65 inline string &operator=(const char *_str) { this->_string = _str; return *this; } 66 inline string &operator=(const std::string &_str) { this->_string = _str; return *this; } 67 inline string &operator=(const string &_str) { if (this != &_str) this->_string = _str._string; return *this; } 68 69 /** 70 * Equality operators, to compare to any type of string. 71 */ 72 inline bool operator==(const char *_str) const { return this->_string == _str; } 73 inline bool operator==(const std::string &_str) const { return this->_string == _str; } 74 inline bool operator==(const string &_str) const { return this->_string == _str._string; } 75 76 inline bool equals_cs(const char *_str) const { return this->_string == _str; } 77 inline bool equals_cs(const std::string &_str) const { return this->_string == _str; } 78 inline bool equals_cs(const string &_str) const { return this->_string == _str._string; } 79 80 inline bool equals_ci(const char *_str) const { return ci::string(this->_string.c_str()) == _str; } 81 inline bool equals_ci(const std::string &_str) const { return ci::string(this->_string.c_str()) == _str.c_str(); } 82 inline bool equals_ci(const string &_str) const { return ci::string(this->_string.c_str()) == _str._string.c_str(); } 83 84 /** 85 * Inequality operators, exact opposites of the above. 86 */ 87 inline bool operator!=(const char *_str) const { return !operator==(_str); } 88 inline bool operator!=(const std::string &_str) const { return !operator==(_str); } 89 inline bool operator!=(const string &_str) const { return !operator==(_str); } 90 91 /** 92 * Compound addition operators, overloaded to do concatenation. 93 */ 94 inline string &operator+=(char chr) { this->_string += chr; return *this; } 95 inline string &operator+=(const char *_str) { this->_string += _str; return *this; } 96 inline string &operator+=(const std::string &_str) { this->_string += _str; return *this; } 97 inline string &operator+=(const string &_str) { if (this != &_str) this->_string += _str._string; return *this; } 98 99 /** 100 * Addition operators, overloaded to do concatenation. 101 */ 102 inline const string operator+(char chr) const { return string(*this) += chr; } 103 inline const string operator+(const char *_str) const { return string(*this) += _str; } 104 inline const string operator+(const std::string &_str) const { return string(*this) += _str; } 105 inline const string operator+(const string &_str) const { return string(*this) += _str; } 106 107 friend const string operator+(char chr, const string &str); 108 friend const string operator+(const char *_str, const string &str); 109 friend const string operator+(const std::string &_str, const string &str); 110 111 /** 112 * Less-than operator. 113 */ 114 inline bool operator<(const string &_str) const { return this->_string < _str._string; } 115 116 /** 117 * The following functions return the various types of strings. 118 */ 119 inline const char *c_str() const { return this->_string.c_str(); } 120 inline const char *data() const { return this->_string.data(); } 121 inline std::string &str() { return this->_string; } 122 inline const std::string &str() const { return this->_string; } 123 inline ci::string ci_str() const { return ci::string(this->_string.c_str()); } 124 125 /** 126 * Returns if the string is empty or not. 127 */ 128 inline bool empty() const { return this->_string.empty(); } 129 130 /** 131 * Returns the string's length. 132 */ 133 inline size_type length() const { return this->_string.length(); } 134 135 /** 136 * Returns the size of the currently allocated storage space in the string object. 137 * This can be equal or greater than the length of the string. 138 */ 139 inline size_type capacity() const { return this->_string.capacity(); } 140 141 /** 142 * Add a char to the end of the string. 143 */ 144 inline void push_back(char c) { return this->_string.push_back(c); } 145 146 inline string& append(const string &s) { this->_string.append(s.str()); return *this; } 147 inline string& append(const char *s, size_t n) { this->_string.append(s, n); return *this; } 148 149 /** 150 * Resizes the string content to n characters. 151 */ 152 inline void resize(size_type n) { return this->_string.resize(n); } 153 154 /** 155 * Erases characters from the string. 156 */ 157 inline iterator erase(const iterator &i) { return this->_string.erase(i); } 158 inline iterator erase(const iterator &first, const iterator &last) { return this->_string.erase(first, last); } 159 inline void erase(size_type pos = 0, size_type n = std::string::npos) { this->_string.erase(pos, n); } 160 161 /** 162 * Trim leading and trailing white spaces from the string. 163 */ 164 165 inline string& ltrim(const Anope::string &what = " \t\r\n") 166 { 167 while (!this->_string.empty() && what.find(this->_string[0]) != Anope::string::npos) 168 this->_string.erase(this->_string.begin()); 169 return *this; 170 } 171 172 inline string& rtrim(const Anope::string &what = " \t\r\n") 173 { 174 while (!this->_string.empty() && what.find(this->_string[this->_string.length() - 1]) != Anope::string::npos) 175 this->_string.erase(this->_string.length() - 1); 176 return *this; 177 } 178 179 inline string& trim(const Anope::string &what = " \t\r\n") 180 { 181 this->ltrim(what); 182 this->rtrim(what); 183 return *this; 184 } 185 186 /** 187 * Clears the string. 188 */ 189 inline void clear() { this->_string.clear(); } 190 191 /** 192 * Find substrings of the string. 193 */ 194 inline size_type find(const string &_str, size_type pos = 0) const { return this->_string.find(_str._string, pos); } 195 inline size_type find(char chr, size_type pos = 0) const { return this->_string.find(chr, pos); } 196 inline size_type find_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(ci::string(_str._string.c_str()), pos); } 197 inline size_type find_ci(char chr, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(chr, pos); } 198 199 inline size_type rfind(const string &_str, size_type pos = npos) const { return this->_string.rfind(_str._string, pos); } 200 inline size_type rfind(char chr, size_type pos = npos) const { return this->_string.rfind(chr, pos); } 201 inline size_type rfind_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(ci::string(_str._string.c_str()), pos); } 202 inline size_type rfind_ci(char chr, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(chr, pos); } 203 204 inline size_type find_first_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_of(_str._string, pos); } 205 inline size_type find_first_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_of(ci::string(_str._string.c_str()), pos); } 206 207 inline size_type find_first_not_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_not_of(_str._string, pos); } 208 inline size_type find_first_not_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_not_of(ci::string(_str._string.c_str()), pos); } 209 210 inline size_type find_last_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_of(_str._string, pos); } 211 inline size_type find_last_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_of(ci::string(_str._string.c_str()), pos); } 212 213 inline size_type find_last_not_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_not_of(_str._string, pos); } 214 inline size_type find_last_not_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_not_of(ci::string(_str._string.c_str()), pos); } 215 216 /** 217 * Determine if string consists of only numbers. 218 */ 219 inline bool is_number_only() const { return this->find_first_not_of("0123456789.-") == npos; } 220 inline bool is_pos_number_only() const { return this->find_first_not_of("0123456789.") == npos; } 221 222 /** 223 * Replace parts of the string. 224 */ 225 inline string replace(size_type pos, size_type n, const string &_str) { return string(this->_string.replace(pos, n, _str._string)); } 226 inline string replace(size_type pos, size_type n, const string &_str, size_type pos1, size_type n1) { return string(this->_string.replace(pos, n, _str._string, pos1, n1)); } 227 inline string replace(size_type pos, size_type n, size_type n1, char chr) { return string(this->_string.replace(pos, n, n1, chr)); } 228 inline string replace(iterator first, iterator last, const string &_str) { return string(this->_string.replace(first, last, _str._string)); } 229 inline string replace(iterator first, iterator last, size_type n, char chr) { return string(this->_string.replace(first, last, n, chr)); } 230 template <class InputIterator> inline string replace(iterator first, iterator last, InputIterator f, InputIterator l) { return string(this->_string.replace(first, last, f, l)); } 231 inline string replace_all_cs(const string &_orig, const string &_repl) const 232 { 233 Anope::string new_string = *this; 234 size_type pos = new_string.find(_orig), orig_length = _orig.length(), repl_length = _repl.length(); 235 while (pos != npos) 236 { 237 new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length); 238 pos = new_string.find(_orig, pos + repl_length); 239 } 240 return new_string; 241 } 242 inline string replace_all_ci(const string &_orig, const string &_repl) const 243 { 244 Anope::string new_string = *this; 245 size_type pos = new_string.find_ci(_orig), orig_length = _orig.length(), repl_length = _repl.length(); 246 while (pos != npos) 247 { 248 new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length); 249 pos = new_string.find_ci(_orig, pos + repl_length); 250 } 251 return new_string; 252 } 253 254 /** 255 * Get the string in lowercase. 256 */ 257 inline string lower() const 258 { 259 Anope::string new_string = *this; 260 for (size_type i = 0; i < new_string.length(); ++i) 261 new_string[i] = Anope::tolower(new_string[i]); 262 return new_string; 263 } 264 265 /** 266 * Get the string in uppercase. 267 */ 268 inline string upper() const 269 { 270 Anope::string new_string = *this; 271 for (size_type i = 0; i < new_string.length(); ++i) 272 new_string[i] = Anope::toupper(new_string[i]); 273 return new_string; 274 } 275 276 /** 277 * Get a substring of the string. 278 */ 279 inline string substr(size_type pos = 0, size_type n = npos) const { return string(this->_string.substr(pos, n)); } 280 281 /** 282 * Iterators to the string. 283 */ 284 inline iterator begin() { return this->_string.begin(); } 285 inline const_iterator begin() const { return this->_string.begin(); } 286 inline iterator end() { return this->_string.end(); } 287 inline const_iterator end() const { return this->_string.end(); } 288 inline reverse_iterator rbegin() { return this->_string.rbegin(); } 289 inline const_reverse_iterator rbegin() const { return this->_string.rbegin(); } 290 inline reverse_iterator rend() { return this->_string.rend(); } 291 inline const_reverse_iterator rend() const { return this->_string.rend(); } 292 293 /** 294 * Subscript operator, to access individual characters of the string. 295 */ 296 inline char &operator[](size_type n) { return this->_string[n]; } 297 inline const char &operator[](size_type n) const { return this->_string[n]; } 298 299 /** 300 * Stream insertion operator, must be friend because they cannot be inside the class. 301 */ 302 friend std::ostream &operator<<(std::ostream &os, const string &_str); 303 friend std::istream &operator>>(std::istream &is, string &_str); 304 }; 305 306 inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _str._string; } 307 /* This is not standard to make operator>> behave like operator<< in that it will allow extracting a whole line, not just one word */ 308 inline std::istream &operator>>(std::istream &is, string &_str) { return std::getline(is, _str._string); } 309 310 inline const string operator+(char chr, const string &str) { string tmp(chr); tmp += str; return tmp; } 311 inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; } 312 inline const string operator+(const std::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; } 313 314 struct hash_ci 315 { 316 inline size_t operator()(const string &s) const 317 { 318 return TR1NS::hash<std::string>()(s.lower().str()); 319 } 320 }; 321 322 struct hash_cs 323 { 324 inline size_t operator()(const string &s) const 325 { 326 return TR1NS::hash<std::string>()(s.str()); 327 } 328 }; 329 330 struct compare 331 { 332 inline bool operator()(const string &s1, const string &s2) const 333 { 334 return s1.equals_ci(s2); 335 } 336 }; 337 338 template<typename T> class map : public std::map<string, T, ci::less> { }; 339 template<typename T> class multimap : public std::multimap<string, T, ci::less> { }; 340 template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { }; 341 342 #ifndef REPRODUCIBLE_BUILD 343 static const char *const compiled = __TIME__ " " __DATE__; 344 #endif 345 346 /** The time Anope started. 347 */ 348 extern CoreExport time_t StartTime; 349 350 /** The value to return from main() 351 */ 352 extern int ReturnValue; 353 354 extern sig_atomic_t Signal; 355 extern CoreExport bool Quitting; 356 extern CoreExport bool Restarting; 357 extern CoreExport Anope::string QuitReason; 358 359 /** The current system time, which is pretty close to being accurate. 360 * Use this unless you need very specific time checks 361 */ 362 extern CoreExport time_t CurTime; 363 364 /** The debug level we are running at. 365 */ 366 extern CoreExport int Debug; 367 368 /** Other command line options. 369 */ 370 extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug; 371 372 /** The root of the services installation. Usually ~/services 373 */ 374 extern CoreExport Anope::string ServicesDir; 375 376 /** Services binary name (eg services) 377 */ 378 extern CoreExport Anope::string ServicesBin; 379 380 /** Various directory paths. These can be set at runtime by command line args 381 */ 382 extern CoreExport Anope::string ConfigDir; 383 extern CoreExport Anope::string DataDir; 384 extern CoreExport Anope::string ModuleDir; 385 extern CoreExport Anope::string LocaleDir; 386 extern CoreExport Anope::string LogDir; 387 388 /** The uplink we are currently connected to 389 */ 390 extern CoreExport int CurrentUplink; 391 392 /** Various methods to determine the Anope version running 393 */ 394 extern CoreExport string Version(); 395 extern CoreExport string VersionShort(); 396 extern CoreExport string VersionBuildString(); 397 extern CoreExport int VersionMajor(); 398 extern CoreExport int VersionMinor(); 399 extern CoreExport int VersionPatch(); 400 401 /** Determines if we are still attached to the terminal, and can print 402 * messages to the user via stderr/stdout. 403 * @return true if still attached 404 */ 405 extern bool AtTerm(); 406 407 /** Used to "fork" the process and go into the background during initial startup 408 * while we are AtTerm(). The actual fork is not done here, but earlier, and this 409 * simply notifies the parent via kill() to exit(). 410 */ 411 extern void Fork(); 412 413 /** Does something with the signal in Anope::Signal 414 */ 415 extern void HandleSignal(); 416 417 /** One of the first functions called, does general initialization such as reading 418 * command line args, loading the configuration, doing the initial fork() if necessary, 419 * initializing language support, loading modules, and loading databases. 420 * @throws CoreException if something bad went wrong 421 */ 422 extern void Init(int ac, char **av); 423 424 /** Calls the save database event 425 */ 426 extern CoreExport void SaveDatabases(); 427 428 /** Check whether two strings match. 429 * @param str The string to check against the pattern (e.g. foobar) 430 * @param mask The pattern to check (e.g. foo*bar) 431 * @param case_sensitive Whether or not the match is case sensitive, default false. 432 * @param use_regex Whether or not to try regex. case_sensitive is not used in regex. 433 */ 434 extern CoreExport bool Match(const string &str, const string &mask, bool case_sensitive = false, bool use_regex = false); 435 436 /** Converts a string to hex 437 * @param the data to be converted 438 * @return a anope::string containing the hex value 439 */ 440 extern CoreExport string Hex(const string &data); 441 extern CoreExport string Hex(const char *data, unsigned len); 442 443 /** Converts a string from hex 444 * @param src The data to be converted 445 * @param dest The destination string 446 */ 447 extern CoreExport void Unhex(const string &src, string &dest); 448 extern CoreExport void Unhex(const string &src, char *dest, size_t sz); 449 450 /** Base 64 encode a string 451 * @param src The string to encode 452 * @param target Where the encoded string is placed 453 */ 454 extern CoreExport void B64Encode(const string &src, string &target); 455 456 /** Base 64 decode a string 457 * @param src The base64 encoded string 458 * @param target The plain text result 459 */ 460 extern CoreExport void B64Decode(const string &src, string &target); 461 462 /** Encrypts what is in 'src' to 'dest' 463 * @param src The source string to encrypt 464 * @param dest The destination where the encrypted string is placed 465 */ 466 extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest); 467 468 /** Decrypts what is in 'src' to 'dest'. 469 * @param src The source string to decrypt 470 * @param dest The destination where the decrypted string is placed 471 * @return true if decryption was successful. This is usually not the case 472 * as most encryption methods we use are one way. 473 */ 474 extern CoreExport bool Decrypt(const Anope::string &src, Anope::string &dest); 475 476 /** Hashes a buffer with SipHash-2-4 477 * @param src The start of the buffer to hash 478 * @param src_sz The total number of bytes in the buffer 479 * @param key A 16 byte key to hash the buffer with. 480 */ 481 extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]); 482 483 /** Returns a sequence of data formatted as the format argument specifies. 484 ** After the format parameter, the function expects at least as many 485 ** additional arguments as specified in format. 486 * @param fmt Format of the Message 487 * @param ... any number of parameters 488 * @return a Anope::string 489 */ 490 extern CoreExport string printf(const char *fmt, ...); 491 492 /** Return the last error code 493 * @return The error code 494 */ 495 extern CoreExport int LastErrorCode(); 496 497 /** Return the last error, uses errno/GetLastError() to determine this 498 * @return An error message 499 */ 500 extern CoreExport const string LastError(); 501 502 /** Determines if a path is a file 503 */ 504 extern CoreExport bool IsFile(const Anope::string &file); 505 506 /** Converts a string into seconds 507 * @param s The string, eg 3d 508 * @return The time represented by the string, eg 259,200 509 */ 510 extern CoreExport time_t DoTime(const Anope::string &s); 511 512 /** Retrieves a human readable string representing the time in seconds 513 * @param seconds The time on seconds, eg 60 514 * @param nc The account to use language settings for to translate this string, if applicable 515 * @return A human readable string, eg "1 minute" 516 */ 517 extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL); 518 519 /** Generates a human readable string of type "expires in ..." 520 * @param expires time in seconds 521 * @param nc The account to use language settings for to translate this string, if applicable 522 * @return A human readable string, eg "expires in 5 days" 523 */ 524 extern CoreExport Anope::string Expires(time_t seconds, const NickCore *nc = NULL); 525 526 /** Converts a time in seconds (epoch) to a human readable format. 527 * @param t The time 528 * @param nc The account to use language settings for to translate this string, if applicable 529 * @param short_output If true, the output is just a date (eg, "Apr 12 20:18:22 2009 MSD"), else it includes the date and how long ago/from now that date is, (eg "Apr 12 20:18:22 2009 MSD (1313 days, 9 hours, 32 minutes ago)" 530 */ 531 extern CoreExport Anope::string strftime(time_t t, const NickCore *nc = NULL, bool short_output = false); 532 533 /** Normalize buffer, stripping control characters and colors 534 * @param A string to be parsed for control and color codes 535 * @return A string stripped of control and color codes 536 */ 537 extern CoreExport Anope::string NormalizeBuffer(const Anope::string &); 538 539 /** Main processing routine. Parses the message and takes the appropriate action. 540 * @param Raw message from the uplink 541 */ 542 extern void Process(const Anope::string &); 543 544 /** Does a blocking dns query and returns the first IP. 545 * @param host host to look up 546 * @param type inet addr type 547 * @return the IP if it was found, else the host 548 */ 549 extern Anope::string Resolve(const Anope::string &host, int type); 550 551 /** Generate a string of random letters and numbers 552 * @param len The length of the string returned 553 */ 554 extern CoreExport Anope::string Random(size_t len); 555 } 556 557 /** sepstream allows for splitting token separated lists. 558 * Each successive call to sepstream::GetToken() returns 559 * the next token, until none remain, at which point the method returns 560 * an empty string. 561 */ 562 class CoreExport sepstream 563 { 564 private: 565 /** Original string. 566 */ 567 Anope::string tokens; 568 /** Seperator value 569 */ 570 char sep; 571 /** Current string position 572 */ 573 size_t pos; 574 /** If set then GetToken() can return an empty string 575 */ 576 bool allow_empty; 577 public: 578 /** Create a sepstream and fill it with the provided data 579 */ 580 sepstream(const Anope::string &source, char separator, bool allowempty = false); 581 582 /** Fetch the next token from the stream 583 * @param token The next token from the stream is placed here 584 * @return True if tokens still remain, false if there are none left 585 */ 586 bool GetToken(Anope::string &token); 587 588 /** Gets token number 'num' from the stream 589 * @param token The token is placed here 590 * @param num The token number to fetch 591 * @return True if the token was able to be fetched 592 */ 593 bool GetToken(Anope::string &token, int num); 594 595 /** Gets every token from this stream 596 * @param token Tokens are pushed back here 597 */ 598 template<typename T> void GetTokens(T& token) 599 { 600 token.clear(); 601 Anope::string t; 602 while (this->GetToken(t)) 603 token.push_back(t); 604 } 605 606 /** Gets token number 'num' from the stream and all remaining tokens. 607 * @param token The token is placed here 608 * @param num The token number to fetch 609 * @return True if the token was able to be fetched 610 */ 611 bool GetTokenRemainder(Anope::string &token, int num); 612 613 /** Determines the number of tokens in this stream. 614 * @return The number of tokens in this stream 615 */ 616 int NumTokens(); 617 618 /** Fetch the entire remaining stream, without tokenizing 619 * @return The remaining part of the stream 620 */ 621 const Anope::string GetRemaining(); 622 623 /** Returns true if the end of the stream has been reached 624 * @return True if the end of the stream has been reached, otherwise false 625 */ 626 bool StreamEnd(); 627 }; 628 629 /** A derived form of sepstream, which separates on commas 630 */ 631 class commasepstream : public sepstream 632 { 633 public: 634 /** Initialize with comma separator 635 */ 636 commasepstream(const Anope::string &source, bool allowempty = false) : sepstream(source, ',', allowempty) { } 637 }; 638 639 /** A derived form of sepstream, which separates on spaces 640 */ 641 class spacesepstream : public sepstream 642 { 643 public: 644 /** Initialize with space separator 645 */ 646 spacesepstream(const Anope::string &source) : sepstream(source, ' ') { } 647 }; 648 649 /** This class can be used on its own to represent an exception, or derived to represent a module-specific exception. 650 * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or 651 * a class derived from ModuleException. If a module throws an exception during its constructor, the module will not 652 * be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user 653 * attempting to load the module, or dumped to the console if the ircd is currently loading for the first time. 654 */ 655 class CoreException : public std::exception 656 { 657 protected: 658 /** Holds the error message to be displayed 659 */ 660 Anope::string err; 661 /** Source of the exception 662 */ 663 Anope::string source; 664 public: 665 /** Default constructor, just uses the error message 'Core threw an exception'. 666 */ 667 CoreException() : err("Core threw an exception"), source("The core") { } 668 /** This constructor can be used to specify an error message before throwing. 669 */ 670 CoreException(const Anope::string &message) : err(message), source("The core") { } 671 /** This constructor can be used to specify an error message before throwing, 672 * and to specify the source of the exception. 673 */ 674 CoreException(const Anope::string &message, const Anope::string &src) : err(message), source(src) { } 675 /** This destructor solves world hunger, cancels the world debt, and causes the world to end. 676 * Actually no, it does nothing. Never mind. 677 * @throws Nothing! 678 */ 679 virtual ~CoreException() throw() { } 680 /** Returns the reason for the exception. 681 * The module should probably put something informative here as the user will see this upon failure. 682 */ 683 virtual const Anope::string &GetReason() const 684 { 685 return err; 686 } 687 688 virtual const Anope::string &GetSource() const 689 { 690 return source; 691 } 692 }; 693 694 class ModuleException : public CoreException 695 { 696 public: 697 /** Default constructor, just uses the error message 'Module threw an exception'. 698 */ 699 ModuleException() : CoreException("Module threw an exception", "A Module") { } 700 701 /** This constructor can be used to specify an error message before throwing. 702 */ 703 ModuleException(const Anope::string &message) : CoreException(message, "A Module") { } 704 /** This destructor solves world hunger, cancels the world debt, and causes the world to end. 705 * Actually no, it does nothing. Never mind. 706 * @throws Nothing! 707 */ 708 virtual ~ModuleException() throw() { } 709 }; 710 711 class ConvertException : public CoreException 712 { 713 public: 714 ConvertException(const Anope::string &reason = "") : CoreException(reason) { } 715 716 virtual ~ConvertException() throw() { } 717 }; 718 719 /** Convert something to a string 720 */ 721 template<typename T> inline Anope::string stringify(const T &x) 722 { 723 std::ostringstream stream; 724 725 if (!(stream << x)) 726 throw ConvertException("Stringify fail"); 727 728 return stream.str(); 729 } 730 731 template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true) 732 { 733 leftover.clear(); 734 std::istringstream i(s.str()); 735 char c; 736 if (!(i >> x)) 737 throw ConvertException("Convert fail"); 738 if (failIfLeftoverChars) 739 { 740 if (i.get(c)) 741 throw ConvertException("Convert fail"); 742 } 743 else 744 { 745 std::string left; 746 getline(i, left); 747 leftover = left; 748 } 749 } 750 751 template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true) 752 { 753 Anope::string Unused; 754 convert(s, x, Unused, failIfLeftoverChars); 755 } 756 757 template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true) 758 { 759 T x; 760 convert(s, x, leftover, failIfLeftoverChars); 761 return x; 762 } 763 764 template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true) 765 { 766 T x; 767 convert(s, x, failIfLeftoverChars); 768 return x; 769 } 770 771 /** Casts to be used instead of dynamic_cast, this uses dynamic_cast 772 * for debug builds and static_cast on release builds 773 * to speed up the program because dynamic_cast relies on RTTI. 774 */ 775 #ifdef DEBUG_BUILD 776 # include <typeinfo> 777 template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr) 778 { 779 T ret = dynamic_cast<T>(ptr); 780 if (ptr != NULL && ret == NULL) 781 throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O).name() + ") fail"); 782 return ret; 783 } 784 #else 785 template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr) 786 { 787 return static_cast<T>(ptr); 788 } 789 #endif 790 791 #endif // ANOPE_H