diff options
author | Attila Molnar <attilamolnar@hush.com> | 2014-02-21 14:42:16 +0100 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2014-02-21 14:42:16 +0100 |
commit | 1b6dda7ad54dd0242cd9eac30f167d76f061d2fa (patch) | |
tree | fa46b7bbfdcf5484d82e3984f0c55fc6537f3cfb | |
parent | 9e123ad1218e8c3ff29cee2a8a6e1b4b6f56b33b (diff) |
Assign an id to user modes, parameter chanmodes and simple chanmodes
-rw-r--r-- | include/mode.h | 27 | ||||
-rw-r--r-- | src/mode.cpp | 30 |
2 files changed, 56 insertions, 1 deletions
diff --git a/include/mode.h b/include/mode.h index d3fdabde1..d71423ecf 100644 --- a/include/mode.h +++ b/include/mode.h @@ -94,6 +94,8 @@ class ParamModeBase; class CoreExport ModeHandler : public ServiceProvider { public: + typedef size_t Id; + enum Class { MC_PREFIX, @@ -102,6 +104,11 @@ class CoreExport ModeHandler : public ServiceProvider MC_OTHER }; + private: + /** The opaque id of this mode assigned by the mode parser + */ + Id modeid; + protected: /** * The mode parameter translation type @@ -213,6 +220,11 @@ class CoreExport ModeHandler : public ServiceProvider */ inline char GetModeChar() { return mode; } + /** Return the id of this mode which is used in User::modes and + * Channel::modes as the index to determine whether a mode is set. + */ + Id GetId() const { return modeid; } + /** For user modes, return the current parameter, if any */ virtual std::string GetUserParameter(User* useor); @@ -295,6 +307,8 @@ class CoreExport ModeHandler : public ServiceProvider virtual void RemoveMode(Channel* channel, irc::modestacker& stack); inline unsigned int GetLevelRequired() const { return levelrequired; } + + friend class ModeParser; }; /** @@ -474,6 +488,9 @@ typedef std::multimap<std::string, ModeWatcher*>::iterator ModeWatchIter; */ class CoreExport ModeParser { + public: + static const ModeHandler::Id MODEID_MAX = 64; + private: /** Last item in the ModeType enum */ @@ -490,6 +507,10 @@ class CoreExport ModeParser */ ModeHandler* modehandlers[MODETYPE_LAST][128]; + /** An array of mode handlers indexed by the mode id + */ + ModeHandler* modehandlersbyid[MODETYPE_LAST][MODEID_MAX]; + /** A map of mode handlers keyed by their name */ ModeHandlerMap modehandlersbyname[MODETYPE_LAST]; @@ -539,6 +560,12 @@ class CoreExport ModeParser */ void RecreateModeListFor004Numeric(); + /** Allocates an unused id for the given mode type, throws a ModuleException if out of ids. + * @param mt The type of the mode to allocate the id for + * @return The id + */ + ModeHandler::Id AllocateModeId(ModeType mt); + /** The string representing the last set of modes to be parsed. * Use GetLastParse() to get this value, to be used for display purposes. */ diff --git a/src/mode.cpp b/src/mode.cpp index 053a10ba1..ef18663b9 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -27,7 +27,7 @@ #include "builtinmodes.h" ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type, Class mclass) - : ServiceProvider(Creator, Name, SERVICE_MODE), m_paramtype(TR_TEXT), + : ServiceProvider(Creator, Name, SERVICE_MODE), modeid(ModeParser::MODEID_MAX), m_paramtype(TR_TEXT), parameters_taken(Params), mode(modeletter), oper(false), list(false), m_type(type), type_id(mclass), levelrequired(HALFOP_VALUE) { @@ -608,6 +608,17 @@ void ModeParser::CleanMask(std::string &mask) } } +ModeHandler::Id ModeParser::AllocateModeId(ModeType mt) +{ + for (ModeHandler::Id i = 0; i != MODEID_MAX; ++i) + { + if (!modehandlersbyid[mt][i]) + return i; + } + + throw ModuleException("Out of ModeIds"); +} + bool ModeParser::AddMode(ModeHandler* mh) { /* Yes, i know, this might let people declare modes like '_' or '^'. @@ -635,10 +646,24 @@ bool ModeParser::AddMode(ModeHandler* mh) if (slot) return false; + // The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode. + // Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid. + ModeHandler::Id modeid = MODEID_MAX; + if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode())) + modeid = AllocateModeId(mh->GetModeType()); + if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second) return false; // Everything is fine, add the mode + + // If we allocated an id for this mode then save it and put the mode handler into the slot + if (modeid != MODEID_MAX) + { + mh->modeid = modeid; + modehandlersbyid[mh->GetModeType()][modeid] = mh; + } + slot = mh; if (pm) mhlist.prefix.push_back(pm); @@ -698,6 +723,8 @@ bool ModeParser::DelMode(ModeHandler* mh) } mhmap.erase(mhmapit); + if (mh->GetId() != MODEID_MAX) + modehandlersbyid[mh->GetModeType()][mh->GetId()] = NULL; slot = NULL; if (mh->IsPrefixMode()) mhlist.prefix.erase(std::find(mhlist.prefix.begin(), mhlist.prefix.end(), mh->IsPrefixMode())); @@ -932,6 +959,7 @@ ModeParser::ModeParser() { /* Clear mode handler list */ memset(modehandlers, 0, sizeof(modehandlers)); + memset(modehandlersbyid, 0, sizeof(modehandlersbyid)); seq = 0; memset(&sent, 0, sizeof(sent)); |