/* * (C) 2003-2011 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 #include #include #include "hashcomp.h" class Message; namespace Anope { template class map : public std::map { }; template class insensitive_map : public std::map > { }; /** * 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 string { private: /** * The actual string is stored in an std::string as it can be converted to * ci::string, irc::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(-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 std::string &_str) : _string(_str) { } string(const ci::string &_str) : _string(_str.c_str()) { } string(const irc::string &_str) : _string(_str.c_str()) { } string(const string &_str, size_type pos = 0, size_type n = npos) : _string(_str._string, pos, n) { } template string(InputIterator first, InputIterator last) : _string(first, last) { } /** * 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 ci::string &_str) { this->_string = _str.c_str(); return *this; } inline string &operator=(const irc::string &_str) { this->_string = _str.c_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 ci::string &_str) const { return ci::string(this->_string.c_str()) == _str; } inline bool operator==(const irc::string &_str) const { return irc::string(this->_string.c_str()) == _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 ci::string &_str) const { return this->_string == _str.c_str(); } inline bool equals_cs(const irc::string &_str) const { return this->_string == _str.c_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 ci::string &_str) const { return _str == this->_string.c_str(); } inline bool equals_ci(const irc::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(); } inline bool equals_irc(const char *_str) const { return irc::string(this->_string.c_str()) == _str; } inline bool equals_irc(const std::string &_str) const { return irc::string(this->_string.c_str()) == _str.c_str(); } inline bool equals_irc(const ci::string &_str) const { return irc::string(this->_string.c_str()) == _str.c_str(); } inline bool equals_irc(const irc::string &_str) const { return _str == this->_string.c_str(); } inline bool equals_irc(const string &_str) const { return irc::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 ci::string &_str) const { return !operator==(_str); } inline bool operator!=(const irc::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 ci::string &_str) { this->_string += _str.c_str(); return *this; } inline string &operator+=(const irc::string &_str) { this->_string += _str.c_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 ci::string &_str) const { return string(*this) += _str; } inline const string operator+(const irc::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); friend const string operator+(const ci::string &_str, const string &str); friend const string operator+(const irc::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 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()); } inline irc::string irc_str() const { return irc::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(); } /** * Add a char to the end of the string. */ inline void push_back(char c) { return this->_string.push_back(c); } /** * 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); } /** * 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 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) { 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) { 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 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); }; /** Hash an Anope::string for unorderd_map, passed as the third template arg to unordered_map */ struct hash { /* VS 2008 specific code */ enum { bucket_size = 4, min_buckets = 8 }; bool operator()(const string &s1, const string &s2) const; /* End of 2008 specific code */ /** Hash an Anope::string for unordered_map * @param s The string * @return A hash value for the string */ bool operator()(const string &s) const; }; inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _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; } inline const string operator+(const ci::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; } inline const string operator+(const irc::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; } static const char *const compiled = __TIME__ " " __DATE__; /** 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; extern CoreExport string Version(); extern CoreExport string VersionShort(); extern CoreExport string VersionBuildString(); extern CoreExport int VersionMajor(); extern CoreExport int VersionMinor(); extern CoreExport int VersionPatch(); extern CoreExport int VersionBuild(); /** 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. */ extern CoreExport bool Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive = false); /** Returns a list of pointers to message handlers * @param The message name as sent by the IRCd * @return a vector with pointers to the messagehandlers (you can bind more than one handler to a message) */ extern CoreExport std::vector FindMessage(const string &name); /** 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 Anope::string &src, Anope::string &dest); extern CoreExport void Unhex(const Anope::string &src, char *dest); /** 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, uses errno/GetLastError() to determin this * @return An error message */ extern CoreExport const Anope::string LastError(); } /** sepstream allows for splitting token seperated 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; /** Last position of a seperator token */ Anope::string::iterator last_starting_position; /** Current string position */ Anope::string::iterator n; /** Seperator value */ char sep; public: /** Create a sepstream and fill it with the provided data */ sepstream(const Anope::string &source, char seperator); virtual ~sepstream() { } /** 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 */ virtual bool GetToken(Anope::string &token); /** Fetch the entire remaining stream, without tokenizing * @return The remaining part of the stream */ virtual 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 */ virtual bool StreamEnd(); }; /** A derived form of sepstream, which seperates on commas */ class commasepstream : public sepstream { public: /** Initialize with comma seperator */ commasepstream(const Anope::string &source) : sepstream(source, ',') { } }; /** A derived form of sepstream, which seperates on spaces */ class spacesepstream : public sepstream { public: /** Initialize with space seperator */ spacesepstream(const Anope::string &source) : sepstream(source, ' ') { } }; /** The base class that most classes in Anope inherit from */ class dynamic_reference_base; class CoreExport Base { /* References to this base class */ std::set References; public: Base(); virtual ~Base(); void AddReference(dynamic_reference_base *r); void DelReference(dynamic_reference_base *r); }; class dynamic_reference_base : public Base { protected: bool invalid; public: dynamic_reference_base() : invalid(false) { } virtual ~dynamic_reference_base() { } inline void Invalidate() { this->invalid = true; } }; template class dynamic_reference : public dynamic_reference_base { protected: T *ref; public: dynamic_reference(T *obj) : ref(obj) { if (ref) ref->AddReference(this); } virtual ~dynamic_reference() { if (this->invalid) { this->invalid = false; this->ref = NULL; } else if (ref) ref->DelReference(this); } virtual operator bool() { if (this->invalid) { this->invalid = false; this->ref = NULL; } return this->ref; } virtual inline void operator=(T *newref) { if (this->invalid) { this->invalid = false; this->ref = NULL; } else if (this->ref) this->ref->DelReference(this); this->ref = newref; if (this->ref) this->ref->AddReference(this); } virtual inline T *operator->() { return this->ref; } virtual inline T *operator*() { return this->ref; } }; #endif // ANOPE_H