summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mode.h27
-rw-r--r--src/mode.cpp30
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));