mirror of
git://git.acid.vegas/anope.git
synced 2024-11-30 11:36:41 +00:00
792 lines
29 KiB
C++
792 lines
29 KiB
C++
/*
|
|
*
|
|
* (C) 2003-2022 Anope Team
|
|
* Contact us at team@anope.org
|
|
*
|
|
* Please read COPYING and README for further details.
|
|
*
|
|
* Based on the original code of Epona by Lara.
|
|
* Based on the original code of Services by Andy Church.
|
|
*/
|
|
|
|
#ifndef ANOPE_H
|
|
#define ANOPE_H
|
|
|
|
#include <signal.h>
|
|
|
|
#include "hashcomp.h"
|
|
|
|
namespace Anope
|
|
{
|
|
/**
|
|
* A wrapper string class around all the other string classes, this class will
|
|
* allow us to only require one type of string everywhere that can be converted
|
|
* at any time to a specific type of string.
|
|
*/
|
|
class CoreExport string
|
|
{
|
|
private:
|
|
/**
|
|
* The actual string is stored in an std::string as it can be converted to
|
|
* ci::string, or a C-style string at any time.
|
|
*/
|
|
std::string _string;
|
|
public:
|
|
/**
|
|
* Extras.
|
|
*/
|
|
typedef std::string::iterator iterator;
|
|
typedef std::string::const_iterator const_iterator;
|
|
typedef std::string::reverse_iterator reverse_iterator;
|
|
typedef std::string::const_reverse_iterator const_reverse_iterator;
|
|
typedef std::string::size_type size_type;
|
|
static const size_type npos = static_cast<size_type>(-1);
|
|
|
|
/**
|
|
* Constructors that can take in any type of string.
|
|
*/
|
|
string() : _string("") { }
|
|
string(char chr) : _string() { _string = chr; }
|
|
string(size_type n, char chr) : _string(n, chr) { }
|
|
string(const char *_str) : _string(_str) { }
|
|
string(const char *_str, size_type n) : _string(_str, n) { }
|
|
string(const std::string &_str) : _string(_str) { }
|
|
string(const ci::string &_str) : _string(_str.c_str()) { }
|
|
string(const string &_str, size_type pos, size_type n = npos) : _string(_str._string, pos, n) { }
|
|
template <class InputIterator> string(InputIterator first, InputIterator last) : _string(first, last) { }
|
|
#if __cplusplus >= 201103L
|
|
string(const string &) = default;
|
|
#endif
|
|
|
|
/**
|
|
* Assignment operators, so any type of string can be assigned to this class.
|
|
*/
|
|
inline string &operator=(char chr) { this->_string = chr; return *this; }
|
|
inline string &operator=(const char *_str) { this->_string = _str; return *this; }
|
|
inline string &operator=(const std::string &_str) { this->_string = _str; return *this; }
|
|
inline string &operator=(const string &_str) { if (this != &_str) this->_string = _str._string; return *this; }
|
|
|
|
/**
|
|
* Equality operators, to compare to any type of string.
|
|
*/
|
|
inline bool operator==(const char *_str) const { return this->_string == _str; }
|
|
inline bool operator==(const std::string &_str) const { return this->_string == _str; }
|
|
inline bool operator==(const string &_str) const { return this->_string == _str._string; }
|
|
|
|
inline bool equals_cs(const char *_str) const { return this->_string == _str; }
|
|
inline bool equals_cs(const std::string &_str) const { return this->_string == _str; }
|
|
inline bool equals_cs(const string &_str) const { return this->_string == _str._string; }
|
|
|
|
inline bool equals_ci(const char *_str) const { return ci::string(this->_string.c_str()) == _str; }
|
|
inline bool equals_ci(const std::string &_str) const { return ci::string(this->_string.c_str()) == _str.c_str(); }
|
|
inline bool equals_ci(const string &_str) const { return ci::string(this->_string.c_str()) == _str._string.c_str(); }
|
|
|
|
/**
|
|
* Inequality operators, exact opposites of the above.
|
|
*/
|
|
inline bool operator!=(const char *_str) const { return !operator==(_str); }
|
|
inline bool operator!=(const std::string &_str) const { return !operator==(_str); }
|
|
inline bool operator!=(const string &_str) const { return !operator==(_str); }
|
|
|
|
/**
|
|
* Compound addition operators, overloaded to do concatenation.
|
|
*/
|
|
inline string &operator+=(char chr) { this->_string += chr; return *this; }
|
|
inline string &operator+=(const char *_str) { this->_string += _str; return *this; }
|
|
inline string &operator+=(const std::string &_str) { this->_string += _str; return *this; }
|
|
inline string &operator+=(const string &_str) { if (this != &_str) this->_string += _str._string; return *this; }
|
|
|
|
/**
|
|
* Addition operators, overloaded to do concatenation.
|
|
*/
|
|
inline const string operator+(char chr) const { return string(*this) += chr; }
|
|
inline const string operator+(const char *_str) const { return string(*this) += _str; }
|
|
inline const string operator+(const std::string &_str) const { return string(*this) += _str; }
|
|
inline const string operator+(const string &_str) const { return string(*this) += _str; }
|
|
|
|
friend const string operator+(char chr, const string &str);
|
|
friend const string operator+(const char *_str, const string &str);
|
|
friend const string operator+(const std::string &_str, const string &str);
|
|
|
|
/**
|
|
* Less-than operator.
|
|
*/
|
|
inline bool operator<(const string &_str) const { return this->_string < _str._string; }
|
|
|
|
/**
|
|
* The following functions return the various types of strings.
|
|
*/
|
|
inline const char *c_str() const { return this->_string.c_str(); }
|
|
inline const char *data() const { return this->_string.data(); }
|
|
inline std::string &str() { return this->_string; }
|
|
inline const std::string &str() const { return this->_string; }
|
|
inline ci::string ci_str() const { return ci::string(this->_string.c_str()); }
|
|
|
|
/**
|
|
* Returns if the string is empty or not.
|
|
*/
|
|
inline bool empty() const { return this->_string.empty(); }
|
|
|
|
/**
|
|
* Returns the string's length.
|
|
*/
|
|
inline size_type length() const { return this->_string.length(); }
|
|
|
|
/**
|
|
* Returns the size of the currently allocated storage space in the string object.
|
|
* This can be equal or greater than the length of the string.
|
|
*/
|
|
inline size_type capacity() const { return this->_string.capacity(); }
|
|
|
|
/**
|
|
* Add a char to the end of the string.
|
|
*/
|
|
inline void push_back(char c) { return this->_string.push_back(c); }
|
|
|
|
inline string& append(const string &s) { this->_string.append(s.str()); return *this; }
|
|
inline string& append(const char *s, size_t n) { this->_string.append(s, n); return *this; }
|
|
|
|
/**
|
|
* Resizes the string content to n characters.
|
|
*/
|
|
inline void resize(size_type n) { return this->_string.resize(n); }
|
|
|
|
/**
|
|
* Erases characters from the string.
|
|
*/
|
|
inline iterator erase(const iterator &i) { return this->_string.erase(i); }
|
|
inline iterator erase(const iterator &first, const iterator &last) { return this->_string.erase(first, last); }
|
|
inline void erase(size_type pos = 0, size_type n = std::string::npos) { this->_string.erase(pos, n); }
|
|
|
|
/**
|
|
* Trim leading and trailing white spaces from the string.
|
|
*/
|
|
|
|
inline string& ltrim(const Anope::string &what = " \t\r\n")
|
|
{
|
|
while (!this->_string.empty() && what.find(this->_string[0]) != Anope::string::npos)
|
|
this->_string.erase(this->_string.begin());
|
|
return *this;
|
|
}
|
|
|
|
inline string& rtrim(const Anope::string &what = " \t\r\n")
|
|
{
|
|
while (!this->_string.empty() && what.find(this->_string[this->_string.length() - 1]) != Anope::string::npos)
|
|
this->_string.erase(this->_string.length() - 1);
|
|
return *this;
|
|
}
|
|
|
|
inline string& trim(const Anope::string &what = " \t\r\n")
|
|
{
|
|
this->ltrim(what);
|
|
this->rtrim(what);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Clears the string.
|
|
*/
|
|
inline void clear() { this->_string.clear(); }
|
|
|
|
/**
|
|
* Find substrings of the string.
|
|
*/
|
|
inline size_type find(const string &_str, size_type pos = 0) const { return this->_string.find(_str._string, pos); }
|
|
inline size_type find(char chr, size_type pos = 0) const { return this->_string.find(chr, pos); }
|
|
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); }
|
|
inline size_type find_ci(char chr, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(chr, pos); }
|
|
|
|
inline size_type rfind(const string &_str, size_type pos = npos) const { return this->_string.rfind(_str._string, pos); }
|
|
inline size_type rfind(char chr, size_type pos = npos) const { return this->_string.rfind(chr, pos); }
|
|
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); }
|
|
inline size_type rfind_ci(char chr, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(chr, pos); }
|
|
|
|
inline size_type find_first_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_of(_str._string, pos); }
|
|
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); }
|
|
|
|
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); }
|
|
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); }
|
|
|
|
inline size_type find_last_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_of(_str._string, pos); }
|
|
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); }
|
|
|
|
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); }
|
|
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); }
|
|
|
|
/**
|
|
* Determine if string consists of only numbers.
|
|
*/
|
|
inline bool is_number_only() const { return this->find_first_not_of("0123456789.-") == npos; }
|
|
inline bool is_pos_number_only() const { return this->find_first_not_of("0123456789.") == npos; }
|
|
|
|
/**
|
|
* Replace parts of the string.
|
|
*/
|
|
inline string replace(size_type pos, size_type n, const string &_str) { return string(this->_string.replace(pos, n, _str._string)); }
|
|
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)); }
|
|
inline string replace(size_type pos, size_type n, size_type n1, char chr) { return string(this->_string.replace(pos, n, n1, chr)); }
|
|
inline string replace(iterator first, iterator last, const string &_str) { return string(this->_string.replace(first, last, _str._string)); }
|
|
inline string replace(iterator first, iterator last, size_type n, char chr) { return string(this->_string.replace(first, last, n, chr)); }
|
|
template <class InputIterator> inline string replace(iterator first, iterator last, InputIterator f, InputIterator l) { return string(this->_string.replace(first, last, f, l)); }
|
|
inline string replace_all_cs(const string &_orig, const string &_repl) const
|
|
{
|
|
Anope::string new_string = *this;
|
|
size_type pos = new_string.find(_orig), orig_length = _orig.length(), repl_length = _repl.length();
|
|
while (pos != npos)
|
|
{
|
|
new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
|
|
pos = new_string.find(_orig, pos + repl_length);
|
|
}
|
|
return new_string;
|
|
}
|
|
inline string replace_all_ci(const string &_orig, const string &_repl) const
|
|
{
|
|
Anope::string new_string = *this;
|
|
size_type pos = new_string.find_ci(_orig), orig_length = _orig.length(), repl_length = _repl.length();
|
|
while (pos != npos)
|
|
{
|
|
new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
|
|
pos = new_string.find_ci(_orig, pos + repl_length);
|
|
}
|
|
return new_string;
|
|
}
|
|
|
|
/**
|
|
* Get the string in lowercase.
|
|
*/
|
|
inline string lower() const
|
|
{
|
|
Anope::string new_string = *this;
|
|
for (size_type i = 0; i < new_string.length(); ++i)
|
|
new_string[i] = Anope::tolower(new_string[i]);
|
|
return new_string;
|
|
}
|
|
|
|
/**
|
|
* Get the string in uppercase.
|
|
*/
|
|
inline string upper() const
|
|
{
|
|
Anope::string new_string = *this;
|
|
for (size_type i = 0; i < new_string.length(); ++i)
|
|
new_string[i] = Anope::toupper(new_string[i]);
|
|
return new_string;
|
|
}
|
|
|
|
/**
|
|
* Get a substring of the string.
|
|
*/
|
|
inline string substr(size_type pos = 0, size_type n = npos) const { return string(this->_string.substr(pos, n)); }
|
|
|
|
/**
|
|
* Iterators to the string.
|
|
*/
|
|
inline iterator begin() { return this->_string.begin(); }
|
|
inline const_iterator begin() const { return this->_string.begin(); }
|
|
inline iterator end() { return this->_string.end(); }
|
|
inline const_iterator end() const { return this->_string.end(); }
|
|
inline reverse_iterator rbegin() { return this->_string.rbegin(); }
|
|
inline const_reverse_iterator rbegin() const { return this->_string.rbegin(); }
|
|
inline reverse_iterator rend() { return this->_string.rend(); }
|
|
inline const_reverse_iterator rend() const { return this->_string.rend(); }
|
|
|
|
/**
|
|
* Subscript operator, to access individual characters of the string.
|
|
*/
|
|
inline char &operator[](size_type n) { return this->_string[n]; }
|
|
inline const char &operator[](size_type n) const { return this->_string[n]; }
|
|
|
|
/**
|
|
* Stream insertion operator, must be friend because they cannot be inside the class.
|
|
*/
|
|
friend std::ostream &operator<<(std::ostream &os, const string &_str);
|
|
friend std::istream &operator>>(std::istream &is, string &_str);
|
|
};
|
|
|
|
inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _str._string; }
|
|
/* This is not standard to make operator>> behave like operator<< in that it will allow extracting a whole line, not just one word */
|
|
inline std::istream &operator>>(std::istream &is, string &_str) { return std::getline(is, _str._string); }
|
|
|
|
inline const string operator+(char chr, const string &str) { string tmp(chr); tmp += str; return tmp; }
|
|
inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
|
|
inline const string operator+(const std::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
|
|
|
|
struct hash_ci
|
|
{
|
|
inline size_t operator()(const string &s) const
|
|
{
|
|
return TR1NS::hash<std::string>()(s.lower().str());
|
|
}
|
|
};
|
|
|
|
struct hash_cs
|
|
{
|
|
inline size_t operator()(const string &s) const
|
|
{
|
|
return TR1NS::hash<std::string>()(s.str());
|
|
}
|
|
};
|
|
|
|
struct compare
|
|
{
|
|
inline bool operator()(const string &s1, const string &s2) const
|
|
{
|
|
return s1.equals_ci(s2);
|
|
}
|
|
};
|
|
|
|
template<typename T> class map : public std::map<string, T, ci::less> { };
|
|
template<typename T> class multimap : public std::multimap<string, T, ci::less> { };
|
|
template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { };
|
|
|
|
#ifndef REPRODUCIBLE_BUILD
|
|
static const char *const compiled = __TIME__ " " __DATE__;
|
|
#endif
|
|
|
|
/** The time Anope started.
|
|
*/
|
|
extern CoreExport time_t StartTime;
|
|
|
|
/** The value to return from main()
|
|
*/
|
|
extern int ReturnValue;
|
|
|
|
extern sig_atomic_t Signal;
|
|
extern CoreExport bool Quitting;
|
|
extern CoreExport bool Restarting;
|
|
extern CoreExport Anope::string QuitReason;
|
|
|
|
/** The current system time, which is pretty close to being accurate.
|
|
* Use this unless you need very specific time checks
|
|
*/
|
|
extern CoreExport time_t CurTime;
|
|
|
|
/** The debug level we are running at.
|
|
*/
|
|
extern CoreExport int Debug;
|
|
|
|
/** Other command line options.
|
|
*/
|
|
extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
|
|
|
|
/** The root of the services installation. Usually ~/services
|
|
*/
|
|
extern CoreExport Anope::string ServicesDir;
|
|
|
|
/** Services binary name (eg services)
|
|
*/
|
|
extern CoreExport Anope::string ServicesBin;
|
|
|
|
/** Various directory paths. These can be set at runtime by command line args
|
|
*/
|
|
extern CoreExport Anope::string ConfigDir;
|
|
extern CoreExport Anope::string DataDir;
|
|
extern CoreExport Anope::string ModuleDir;
|
|
extern CoreExport Anope::string LocaleDir;
|
|
extern CoreExport Anope::string LogDir;
|
|
|
|
/** The uplink we are currently connected to
|
|
*/
|
|
extern CoreExport int CurrentUplink;
|
|
|
|
/** Various methods to determine the Anope version running
|
|
*/
|
|
extern CoreExport string Version();
|
|
extern CoreExport string VersionShort();
|
|
extern CoreExport string VersionBuildString();
|
|
extern CoreExport int VersionMajor();
|
|
extern CoreExport int VersionMinor();
|
|
extern CoreExport int VersionPatch();
|
|
|
|
/** Determines if we are still attached to the terminal, and can print
|
|
* messages to the user via stderr/stdout.
|
|
* @return true if still attached
|
|
*/
|
|
extern bool AtTerm();
|
|
|
|
/** Used to "fork" the process and go into the background during initial startup
|
|
* while we are AtTerm(). The actual fork is not done here, but earlier, and this
|
|
* simply notifies the parent via kill() to exit().
|
|
*/
|
|
extern void Fork();
|
|
|
|
/** Does something with the signal in Anope::Signal
|
|
*/
|
|
extern void HandleSignal();
|
|
|
|
/** One of the first functions called, does general initialization such as reading
|
|
* command line args, loading the configuration, doing the initial fork() if necessary,
|
|
* initializing language support, loading modules, and loading databases.
|
|
* @throws CoreException if something bad went wrong
|
|
*/
|
|
extern void Init(int ac, char **av);
|
|
|
|
/** Calls the save database event
|
|
*/
|
|
extern CoreExport void SaveDatabases();
|
|
|
|
/** Check whether two strings match.
|
|
* @param str The string to check against the pattern (e.g. foobar)
|
|
* @param mask The pattern to check (e.g. foo*bar)
|
|
* @param case_sensitive Whether or not the match is case sensitive, default false.
|
|
* @param use_regex Whether or not to try regex. case_sensitive is not used in regex.
|
|
*/
|
|
extern CoreExport bool Match(const string &str, const string &mask, bool case_sensitive = false, bool use_regex = false);
|
|
|
|
/** Converts a string to hex
|
|
* @param the data to be converted
|
|
* @return a anope::string containing the hex value
|
|
*/
|
|
extern CoreExport string Hex(const string &data);
|
|
extern CoreExport string Hex(const char *data, unsigned len);
|
|
|
|
/** Converts a string from hex
|
|
* @param src The data to be converted
|
|
* @param dest The destination string
|
|
*/
|
|
extern CoreExport void Unhex(const string &src, string &dest);
|
|
extern CoreExport void Unhex(const string &src, char *dest, size_t sz);
|
|
|
|
/** Base 64 encode a string
|
|
* @param src The string to encode
|
|
* @param target Where the encoded string is placed
|
|
*/
|
|
extern CoreExport void B64Encode(const string &src, string &target);
|
|
|
|
/** Base 64 decode a string
|
|
* @param src The base64 encoded string
|
|
* @param target The plain text result
|
|
*/
|
|
extern CoreExport void B64Decode(const string &src, string &target);
|
|
|
|
/** Encrypts what is in 'src' to 'dest'
|
|
* @param src The source string to encrypt
|
|
* @param dest The destination where the encrypted string is placed
|
|
*/
|
|
extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest);
|
|
|
|
/** Decrypts what is in 'src' to 'dest'.
|
|
* @param src The source string to decrypt
|
|
* @param dest The destination where the decrypted string is placed
|
|
* @return true if decryption was successful. This is usually not the case
|
|
* as most encryption methods we use are one way.
|
|
*/
|
|
extern CoreExport bool Decrypt(const Anope::string &src, Anope::string &dest);
|
|
|
|
/** Hashes a buffer with SipHash-2-4
|
|
* @param src The start of the buffer to hash
|
|
* @param src_sz The total number of bytes in the buffer
|
|
* @param key A 16 byte key to hash the buffer with.
|
|
*/
|
|
extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]);
|
|
|
|
/** Returns a sequence of data formatted as the format argument specifies.
|
|
** After the format parameter, the function expects at least as many
|
|
** additional arguments as specified in format.
|
|
* @param fmt Format of the Message
|
|
* @param ... any number of parameters
|
|
* @return a Anope::string
|
|
*/
|
|
extern CoreExport string printf(const char *fmt, ...);
|
|
|
|
/** Return the last error code
|
|
* @return The error code
|
|
*/
|
|
extern CoreExport int LastErrorCode();
|
|
|
|
/** Return the last error, uses errno/GetLastError() to determine this
|
|
* @return An error message
|
|
*/
|
|
extern CoreExport const string LastError();
|
|
|
|
/** Determines if a path is a file
|
|
*/
|
|
extern CoreExport bool IsFile(const Anope::string &file);
|
|
|
|
/** Converts a string into seconds
|
|
* @param s The string, eg 3d
|
|
* @return The time represented by the string, eg 259,200
|
|
*/
|
|
extern CoreExport time_t DoTime(const Anope::string &s);
|
|
|
|
/** Retrieves a human readable string representing the time in seconds
|
|
* @param seconds The time on seconds, eg 60
|
|
* @param nc The account to use language settings for to translate this string, if applicable
|
|
* @return A human readable string, eg "1 minute"
|
|
*/
|
|
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL);
|
|
|
|
/** Generates a human readable string of type "expires in ..."
|
|
* @param expires time in seconds
|
|
* @param nc The account to use language settings for to translate this string, if applicable
|
|
* @return A human readable string, eg "expires in 5 days"
|
|
*/
|
|
extern CoreExport Anope::string Expires(time_t seconds, const NickCore *nc = NULL);
|
|
|
|
/** Converts a time in seconds (epoch) to a human readable format.
|
|
* @param t The time
|
|
* @param nc The account to use language settings for to translate this string, if applicable
|
|
* @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)"
|
|
*/
|
|
extern CoreExport Anope::string strftime(time_t t, const NickCore *nc = NULL, bool short_output = false);
|
|
|
|
/** Normalize buffer, stripping control characters and colors
|
|
* @param A string to be parsed for control and color codes
|
|
* @return A string stripped of control and color codes
|
|
*/
|
|
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
|
|
|
|
/** Main processing routine. Parses the message and takes the appropriate action.
|
|
* @param Raw message from the uplink
|
|
*/
|
|
extern void Process(const Anope::string &);
|
|
|
|
/** Does a blocking dns query and returns the first IP.
|
|
* @param host host to look up
|
|
* @param type inet addr type
|
|
* @return the IP if it was found, else the host
|
|
*/
|
|
extern Anope::string Resolve(const Anope::string &host, int type);
|
|
|
|
/** Generate a string of random letters and numbers
|
|
* @param len The length of the string returned
|
|
*/
|
|
extern CoreExport Anope::string Random(size_t len);
|
|
}
|
|
|
|
/** sepstream allows for splitting token separated lists.
|
|
* Each successive call to sepstream::GetToken() returns
|
|
* the next token, until none remain, at which point the method returns
|
|
* an empty string.
|
|
*/
|
|
class CoreExport sepstream
|
|
{
|
|
private:
|
|
/** Original string.
|
|
*/
|
|
Anope::string tokens;
|
|
/** Seperator value
|
|
*/
|
|
char sep;
|
|
/** Current string position
|
|
*/
|
|
size_t pos;
|
|
/** If set then GetToken() can return an empty string
|
|
*/
|
|
bool allow_empty;
|
|
public:
|
|
/** Create a sepstream and fill it with the provided data
|
|
*/
|
|
sepstream(const Anope::string &source, char separator, bool allowempty = false);
|
|
|
|
/** Fetch the next token from the stream
|
|
* @param token The next token from the stream is placed here
|
|
* @return True if tokens still remain, false if there are none left
|
|
*/
|
|
bool GetToken(Anope::string &token);
|
|
|
|
/** Gets token number 'num' from the stream
|
|
* @param token The token is placed here
|
|
* @param num The token number to fetch
|
|
* @return True if the token was able to be fetched
|
|
*/
|
|
bool GetToken(Anope::string &token, int num);
|
|
|
|
/** Gets every token from this stream
|
|
* @param token Tokens are pushed back here
|
|
*/
|
|
template<typename T> void GetTokens(T& token)
|
|
{
|
|
token.clear();
|
|
Anope::string t;
|
|
while (this->GetToken(t))
|
|
token.push_back(t);
|
|
}
|
|
|
|
/** Gets token number 'num' from the stream and all remaining tokens.
|
|
* @param token The token is placed here
|
|
* @param num The token number to fetch
|
|
* @return True if the token was able to be fetched
|
|
*/
|
|
bool GetTokenRemainder(Anope::string &token, int num);
|
|
|
|
/** Determines the number of tokens in this stream.
|
|
* @return The number of tokens in this stream
|
|
*/
|
|
int NumTokens();
|
|
|
|
/** Fetch the entire remaining stream, without tokenizing
|
|
* @return The remaining part of the stream
|
|
*/
|
|
const Anope::string GetRemaining();
|
|
|
|
/** Returns true if the end of the stream has been reached
|
|
* @return True if the end of the stream has been reached, otherwise false
|
|
*/
|
|
bool StreamEnd();
|
|
};
|
|
|
|
/** A derived form of sepstream, which separates on commas
|
|
*/
|
|
class commasepstream : public sepstream
|
|
{
|
|
public:
|
|
/** Initialize with comma separator
|
|
*/
|
|
commasepstream(const Anope::string &source, bool allowempty = false) : sepstream(source, ',', allowempty) { }
|
|
};
|
|
|
|
/** A derived form of sepstream, which separates on spaces
|
|
*/
|
|
class spacesepstream : public sepstream
|
|
{
|
|
public:
|
|
/** Initialize with space separator
|
|
*/
|
|
spacesepstream(const Anope::string &source) : sepstream(source, ' ') { }
|
|
};
|
|
|
|
/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
|
|
* When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
|
|
* a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
|
|
* be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
|
|
* attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
|
|
*/
|
|
class CoreException : public std::exception
|
|
{
|
|
protected:
|
|
/** Holds the error message to be displayed
|
|
*/
|
|
Anope::string err;
|
|
/** Source of the exception
|
|
*/
|
|
Anope::string source;
|
|
public:
|
|
/** Default constructor, just uses the error message 'Core threw an exception'.
|
|
*/
|
|
CoreException() : err("Core threw an exception"), source("The core") { }
|
|
/** This constructor can be used to specify an error message before throwing.
|
|
*/
|
|
CoreException(const Anope::string &message) : err(message), source("The core") { }
|
|
/** This constructor can be used to specify an error message before throwing,
|
|
* and to specify the source of the exception.
|
|
*/
|
|
CoreException(const Anope::string &message, const Anope::string &src) : err(message), source(src) { }
|
|
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
|
|
* Actually no, it does nothing. Never mind.
|
|
* @throws Nothing!
|
|
*/
|
|
virtual ~CoreException() throw() { }
|
|
/** Returns the reason for the exception.
|
|
* The module should probably put something informative here as the user will see this upon failure.
|
|
*/
|
|
virtual const Anope::string &GetReason() const
|
|
{
|
|
return err;
|
|
}
|
|
|
|
virtual const Anope::string &GetSource() const
|
|
{
|
|
return source;
|
|
}
|
|
};
|
|
|
|
class ModuleException : public CoreException
|
|
{
|
|
public:
|
|
/** Default constructor, just uses the error message 'Module threw an exception'.
|
|
*/
|
|
ModuleException() : CoreException("Module threw an exception", "A Module") { }
|
|
|
|
/** This constructor can be used to specify an error message before throwing.
|
|
*/
|
|
ModuleException(const Anope::string &message) : CoreException(message, "A Module") { }
|
|
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
|
|
* Actually no, it does nothing. Never mind.
|
|
* @throws Nothing!
|
|
*/
|
|
virtual ~ModuleException() throw() { }
|
|
};
|
|
|
|
class ConvertException : public CoreException
|
|
{
|
|
public:
|
|
ConvertException(const Anope::string &reason = "") : CoreException(reason) { }
|
|
|
|
virtual ~ConvertException() throw() { }
|
|
};
|
|
|
|
/** Convert something to a string
|
|
*/
|
|
template<typename T> inline Anope::string stringify(const T &x)
|
|
{
|
|
std::ostringstream stream;
|
|
|
|
if (!(stream << x))
|
|
throw ConvertException("Stringify fail");
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true)
|
|
{
|
|
leftover.clear();
|
|
std::istringstream i(s.str());
|
|
char c;
|
|
if (!(i >> x))
|
|
throw ConvertException("Convert fail");
|
|
if (failIfLeftoverChars)
|
|
{
|
|
if (i.get(c))
|
|
throw ConvertException("Convert fail");
|
|
}
|
|
else
|
|
{
|
|
std::string left;
|
|
getline(i, left);
|
|
leftover = left;
|
|
}
|
|
}
|
|
|
|
template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true)
|
|
{
|
|
Anope::string Unused;
|
|
convert(s, x, Unused, failIfLeftoverChars);
|
|
}
|
|
|
|
template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true)
|
|
{
|
|
T x;
|
|
convert(s, x, leftover, failIfLeftoverChars);
|
|
return x;
|
|
}
|
|
|
|
template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true)
|
|
{
|
|
T x;
|
|
convert(s, x, failIfLeftoverChars);
|
|
return x;
|
|
}
|
|
|
|
/** Casts to be used instead of dynamic_cast, this uses dynamic_cast
|
|
* for debug builds and static_cast on release builds
|
|
* to speed up the program because dynamic_cast relies on RTTI.
|
|
*/
|
|
#ifdef DEBUG_BUILD
|
|
# include <typeinfo>
|
|
template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
|
|
{
|
|
T ret = dynamic_cast<T>(ptr);
|
|
if (ptr != NULL && ret == NULL)
|
|
throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O).name() + ") fail");
|
|
return ret;
|
|
}
|
|
#else
|
|
template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
|
|
{
|
|
return static_cast<T>(ptr);
|
|
}
|
|
#endif
|
|
|
|
#endif // ANOPE_H
|