core/AdminCache.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jan 24 21:51:49 2007 +0000 (2007-01-24)
changeset 335 02cc96355b09
child 336 3f4073018d76
permissions -rw-r--r--
Initial import of admin system (groups and overrides done)
Added a "clear" function for Tries
     1 #include <string.h>
     2 #include <assert.h>
     3 #include "AdminCache.h"
     4 #include "ShareSys.h"
     5 
     6 AdminCache g_Admins;
     7 
     8 AdminCache::AdminCache()
     9 {
    10 	m_pCmdOverrides = NULL;
    11 	m_pCmdGrpOverrides = NULL;
    12 	m_pStrings = new BaseStringTable(1024);
    13 	m_pMemory = m_pStrings->GetMemTable();
    14 	m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
    15 	m_pGroups = sm_trie_create();
    16 }
    17 
    18 AdminCache::~AdminCache()
    19 {
    20 	if (m_pCmdGrpOverrides)
    21 	{
    22 		sm_trie_destroy(m_pCmdGrpOverrides);
    23 	}
    24 
    25 	if (m_pCmdOverrides)
    26 	{
    27 		sm_trie_destroy(m_pCmdOverrides);
    28 	}
    29 
    30 	InvalidateGroupCache();
    31 
    32 	if (m_pGroups)
    33 	{
    34 		sm_trie_destroy(m_pGroups);
    35 	}
    36 
    37 	delete m_pStrings;
    38 }
    39 
    40 void AdminCache::OnSourceModAllInitialized()
    41 {
    42 	g_ShareSys.AddInterface(NULL, this);
    43 }
    44 
    45 void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag)
    46 {
    47 	if (type == Override_Command)
    48 	{
    49 		_AddCommandOverride(cmd, flag);
    50 	} else if (type == Override_CommandGroup) {
    51 		_AddCommandGroupOverride(cmd, flag);
    52 	}
    53 }
    54 
    55 bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag)
    56 {
    57 	if (type == Override_Command)
    58 	{
    59 		return _GetCommandOverride(cmd, pFlag);
    60 	} else if (type == Override_CommandGroup) {
    61 		return _GetCommandGroupOverride(cmd, pFlag);
    62 	}
    63 
    64 	return false;
    65 }
    66 
    67 void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
    68 {
    69 	if (type == Override_Command)
    70 	{
    71 		return _UnsetCommandOverride(cmd);
    72 	} else if (type == Override_CommandGroup) {
    73 		return _UnsetCommandGroupOverride(cmd);
    74 	}
    75 }
    76 
    77 void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag)
    78 {
    79 	if (!m_pCmdGrpOverrides)
    80 	{
    81 		m_pCmdGrpOverrides = sm_trie_create();
    82 	}
    83 
    84 	/* :TODO: Notify command system */
    85 
    86 	sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag);
    87 }
    88 
    89 void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag)
    90 {
    91 	if (!m_pCmdOverrides)
    92 	{
    93 		m_pCmdOverrides = sm_trie_create();
    94 	}
    95 
    96 	/* :TODO: Notify command system */
    97 
    98 	sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag);
    99 }
   100 
   101 bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag)
   102 {
   103 	if (!m_pCmdGrpOverrides)
   104 	{
   105 		return false;
   106 	}
   107 
   108 	if (!pFlag)
   109 	{
   110 		return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL);
   111 	} else {
   112 		void *object;
   113 		bool ret;
   114 		if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object))
   115 		{
   116 			*pFlag = (AdminFlag)(int)object;
   117 		}
   118 		return ret;
   119 	}
   120 }
   121 
   122 bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag)
   123 {
   124 	if (!m_pCmdOverrides)
   125 	{
   126 		return false;
   127 	}
   128 
   129 	if (!pFlag)
   130 	{
   131 		return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL);
   132 	} else {
   133 		void *object;
   134 		bool ret;
   135 		if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object))
   136 		{
   137 			*pFlag = (AdminFlag)(int)object;
   138 		}
   139 		return ret;
   140 	}
   141 }
   142 
   143 void AdminCache::_UnsetCommandGroupOverride(const char *group)
   144 {
   145 	if (!m_pCmdGrpOverrides)
   146 	{
   147 		return;
   148 	}
   149 
   150 	/* :TODO: Notify command system */
   151 
   152 	sm_trie_delete(m_pCmdGrpOverrides, group);
   153 }
   154 
   155 void AdminCache::_UnsetCommandOverride(const char *cmd)
   156 {
   157 	if (!m_pCmdOverrides)
   158 	{
   159 		return;
   160 	}
   161 
   162 	/* :TODO: Notify command system */
   163 
   164 	sm_trie_delete(m_pCmdOverrides, cmd);
   165 }
   166 
   167 void AdminCache::DumpCommandOverrideCache(OverrideType type)
   168 {
   169 	if (type == Override_Command && m_pCmdOverrides)
   170 	{
   171 		sm_trie_clear(m_pCmdOverrides);
   172 	} else if (type == Override_CommandGroup && m_pCmdGrpOverrides) {
   173 		sm_trie_clear(m_pCmdGrpOverrides);
   174 	}
   175 }
   176 
   177 GroupId AdminCache::AddGroup(const char *group_name)
   178 {
   179 	if (sm_trie_retrieve(m_pGroups, group_name, NULL))
   180 	{
   181 		return INVALID_GROUP_ID;
   182 	}
   183 
   184 	GroupId id;
   185 	AdminGroup *pGroup;
   186 	if (m_FreeGroupList != INVALID_GROUP_ID)
   187 	{
   188 		pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList);
   189 		assert(pGroup->magic == GRP_MAGIC_UNSET);
   190 		id = m_FreeGroupList;
   191 		m_FreeGroupList = pGroup->next_grp;
   192 	} else {
   193 		id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup);
   194 	}
   195 
   196 	pGroup->immune_default = false;
   197 	pGroup->immune_global = false;
   198 	pGroup->immune_table = -1;
   199 	pGroup->magic = GRP_MAGIC_SET;
   200 	pGroup->next_grp = INVALID_GROUP_ID;
   201 	pGroup->pCmdGrpTable = NULL;
   202 	pGroup->pCmdTable = NULL;
   203 	pGroup->nameidx = m_pStrings->AddString(group_name);
   204 	memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
   205 
   206 	if (m_FirstGroup == INVALID_GROUP_ID)
   207 	{
   208 		m_FirstGroup = id;
   209 		m_LastGroup = id;
   210 		pGroup->prev_grp = INVALID_GROUP_ID;
   211 	} else {
   212 		AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
   213 		assert(pPrev->magic == GRP_MAGIC_SET);
   214 		pPrev->next_grp = id;
   215 		pGroup->prev_grp = m_LastGroup;
   216 		m_LastGroup = id;
   217 	}
   218 
   219 	sm_trie_insert(m_pGroups, group_name, (void *)id);
   220 
   221 	return id;
   222 }
   223 
   224 GroupId AdminCache::FindGroupByName(const char *group_name)
   225 {
   226 	void *object;
   227 
   228 	if (!sm_trie_retrieve(m_pGroups, group_name, &object))
   229 	{
   230 		return INVALID_GROUP_ID;
   231 	}
   232 
   233 	GroupId id = (GroupId)object;
   234 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   235 
   236 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   237 	{
   238 		return INVALID_GROUP_ID;
   239 	}
   240 
   241 	return id;
   242 }
   243 
   244 void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled)
   245 {
   246 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   247 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   248 	{
   249 		return;
   250 	}
   251 
   252 	if (flag < Admin_None || flag >= AdminFlags_TOTAL)
   253 	{
   254 		return;
   255 	}
   256 
   257 	pGroup->addflags[flag] = enabled;
   258 }
   259 
   260 bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag)
   261 {
   262 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   263 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   264 	{
   265 		return false;
   266 	}
   267 
   268 	if (flag < Admin_None || flag >= AdminFlags_TOTAL)
   269 	{
   270 		return false;
   271 	}
   272 
   273 	return pGroup->addflags[flag];
   274 }
   275 
   276 unsigned int AdminCache::GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total)
   277 {
   278 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   279 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   280 	{
   281 		return 0;
   282 	}
   283 
   284 	unsigned int r = 0;
   285 
   286 	for (unsigned int i = Admin_None + 1;
   287 		 i < AdminFlags_TOTAL && r < total;
   288 		 i++)
   289 	{
   290 		if (pGroup->addflags[i])
   291 		{
   292 			flags[r++] = (AdminFlag)i;
   293 		}
   294 	}
   295 
   296 	return r;
   297 }
   298 
   299 void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled)
   300 {
   301 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   302 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   303 	{
   304 		return;
   305 	}
   306 
   307 	if (type == Immunity_Default)
   308 	{
   309 		pGroup->immune_default = enabled;
   310 	} else if (type == Immunity_Global) {
   311 		pGroup->immune_global = enabled;
   312 	} 
   313 }
   314 
   315 bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type)
   316 {
   317 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   318 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   319 	{
   320 		return false;
   321 	}
   322 
   323 	if (type == Immunity_Default)
   324 	{
   325 		return pGroup->immune_default;
   326 	} else if (type == Immunity_Global) {
   327 		return pGroup->immune_global;
   328 	}
   329 
   330 	return false;
   331 }
   332 
   333 void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id)
   334 {
   335 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   336 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   337 	{
   338 		return;
   339 	}
   340 
   341 	AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id);
   342 	if (!pOther || pOther->magic != GRP_MAGIC_SET)
   343 	{
   344 		return;
   345 	}
   346 
   347 	/* We always need to resize the immunity table */
   348 	int *table, tblidx;
   349 	if (pOther->immune_table == -1)
   350 	{
   351 		tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table);
   352 		table[0] = 0;
   353 	} else {
   354 		int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
   355 		tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table);
   356 		/* Get the old address again in caes of resize */
   357 		old_table = (int *)m_pMemory->GetAddress(pOther->immune_table);
   358 		table[0] = old_table[0];
   359 		for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++)
   360 		{
   361 			table[i] = old_table[i];
   362 		}
   363 	}
   364 
   365 	/* Assign */
   366 	pOther->immune_table = tblidx;
   367 
   368 	/* Add to the array */
   369 	table[0]++;
   370 	table[table[0]] = other_id;
   371 }
   372 
   373 unsigned int AdminCache::GetGroupImmunityCount(GroupId id)
   374 {
   375 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   376 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   377 	{
   378 		return 0;
   379 	}
   380 
   381 	if (pGroup->immune_table == -1)
   382 	{
   383 		return 0;
   384 	}
   385 
   386 	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
   387 
   388 	return table[0];
   389 }
   390 
   391 GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number)
   392 {
   393 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   394 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   395 	{
   396 		return INVALID_GROUP_ID;
   397 	}
   398 
   399 	if (pGroup->immune_table == -1)
   400 	{
   401 		return INVALID_GROUP_ID;
   402 	}
   403 
   404 	int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table);
   405 	if (number >= (unsigned int)table[0])
   406 	{
   407 		return INVALID_GROUP_ID;
   408 	}
   409 
   410 	return table[1 + number];
   411 }
   412 
   413 void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule)
   414 {
   415 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   416 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   417 	{
   418 		return;
   419 	}
   420 
   421 	Trie *pTrie = NULL;
   422 	if (type == Override_Command)
   423 	{
   424 		if (pGroup->pCmdTable == NULL)
   425 		{
   426 			pGroup->pCmdTable = sm_trie_create();
   427 		}
   428 		pTrie = pGroup->pCmdTable;
   429 	} else if (type == Override_CommandGroup) {
   430 		if (pGroup->pCmdGrpTable == NULL)
   431 		{
   432 			pGroup->pCmdGrpTable = sm_trie_create();
   433 		}
   434 		pTrie = pGroup->pCmdGrpTable;
   435 	} else {
   436 		return;
   437 	}
   438 
   439 	sm_trie_insert(pTrie, name, (void *)(int)rule);
   440 }
   441 
   442 bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule)
   443 {
   444 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   445 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   446 	{
   447 		return false;
   448 	}
   449 
   450 	Trie *pTrie = NULL;
   451 	if (type == Override_Command)
   452 	{
   453 		if (pGroup->pCmdTable == NULL)
   454 		{
   455 			return false;
   456 		}
   457 		pTrie = pGroup->pCmdTable;
   458 	} else if (type == Override_CommandGroup) {
   459 		if (pGroup->pCmdGrpTable == NULL)
   460 		{
   461 			return false;
   462 		}
   463 		pTrie = pGroup->pCmdGrpTable;
   464 	} else {
   465 		return false;
   466 	}
   467 
   468 	void *object;
   469 	if (!sm_trie_retrieve(pTrie, name, &object))
   470 	{
   471 		return false;
   472 	}
   473 
   474 	if (pRule)
   475 	{
   476 		*pRule = (OverrideRule)(int)object;
   477 	}
   478 	
   479 	return true;
   480 }
   481 
   482 void AdminCache::InvalidateGroup(GroupId id)
   483 {
   484 	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   485 	AdminGroup *pOther;
   486 
   487 	if (!pGroup || pGroup->magic != GRP_MAGIC_SET)
   488 	{
   489 		return;
   490 	}
   491 
   492 	const char *str = m_pStrings->GetString(pGroup->nameidx);
   493 	sm_trie_delete(m_pGroups, str);
   494 
   495 	/* Unlink from the live dbllink list */
   496 	if (id == m_FirstGroup && id == m_LastGroup)
   497 	{
   498 		m_LastGroup = INVALID_GROUP_ID;
   499 		m_FirstGroup = INVALID_GROUP_ID;
   500 	} else if (id == m_FirstGroup) {
   501 		m_FirstGroup = pGroup->next_grp;
   502 		pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup);
   503 		pOther->prev_grp = INVALID_GROUP_ID;
   504 	} else if (id == m_LastGroup) {
   505 		m_LastGroup = pGroup->prev_grp;
   506 		pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup);
   507 		pOther->next_grp = INVALID_GROUP_ID;
   508 	} else {
   509 		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp);
   510 		pOther->next_grp = pGroup->next_grp;
   511 		pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp);
   512 		pOther->prev_grp = pGroup->prev_grp;
   513 	}
   514 
   515 	/* Free any used memory to be safe */
   516 	if (pGroup->pCmdGrpTable)
   517 	{
   518 		sm_trie_destroy(pGroup->pCmdGrpTable);
   519 		pGroup->pCmdGrpTable = NULL;
   520 	}
   521 	if (pGroup->pCmdTable)
   522 	{
   523 		sm_trie_destroy(pGroup->pCmdTable);
   524 		pGroup->pCmdTable = NULL;
   525 	}
   526 
   527 	/* Link into the free list */
   528 	pGroup->magic = GRP_MAGIC_UNSET;
   529 	pGroup->next_grp = m_FreeGroupList;
   530 	m_FreeGroupList = id;
   531 
   532 	/* :TODO: remove this group from any users */
   533 }
   534 
   535 void AdminCache::InvalidateGroupCache()
   536 {
   537 	/* Nuke the free list */
   538 	m_FreeGroupList = -1;
   539 
   540 	/* Nuke reverse lookups */
   541 	sm_trie_clear(m_pGroups);
   542 
   543 	/* Free memory on groups */
   544 	GroupId cur = m_FirstGroup;
   545 	AdminGroup *pGroup;
   546 	while (cur != INVALID_GROUP_ID)
   547 	{
   548 		pGroup = (AdminGroup *)m_pMemory->GetAddress(cur);
   549 		assert(pGroup->magic == GRP_MAGIC_SET);
   550 		if (pGroup->pCmdGrpTable)
   551 		{
   552 			sm_trie_destroy(pGroup->pCmdGrpTable);
   553 		}
   554 		if (pGroup->pCmdTable)
   555 		{
   556 			sm_trie_destroy(pGroup->pCmdTable);
   557 		}
   558 		cur = pGroup->next_grp;
   559 	}
   560 
   561 	m_FirstGroup = INVALID_GROUP_ID;
   562 	m_LastGroup = INVALID_GROUP_ID;
   563 
   564 	/* :TODO: dump the admin cache */
   565 
   566 	/* Reset the memory table */
   567 	m_pMemory->Reset();
   568 }