MtPair* mt_hash_search(MtHash* hash, MtString* key) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtHashElement* element = &hash->buckets[index]; assert(element != NULL); // Key Collides if (element->data != NULL) { // If it is a tree, search the tree for the key if (element->is_tree) { return mt_tree_search((MtTree*) element->data, key); } else if (mt_string_compare(((MtPair*) element->data)->key, key) == 0) { return (MtPair*) element->data; } } // Nothing was found return NULL; }
void mt_hash_remove(MtHash* hash, MtString* key) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtPair* element = hash->buckets[index]; while (element != NULL) { if (mt_string_compare(key, element->key) == 0) { hash->buckets[index] = NULL; --hash->length; return; } ++index; index %= hash->size; element = hash->buckets[index]; } }
void mt_hash_insert(MtHash* hash, MtString* key, void* value) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); mt_hash_insert_pair(hash, mt_pair_new(key, value)); }
void hkl_hash_insert(HklHash* hash, HklString* key, void* value) { assert(hash != NULL); assert(key != NULL); // The string doesnt already have a hash // give it one if (key->hash == 0) key->hash = Murmur3(hkl_string_get_utf8(key), hkl_string_get_length(key)); size_t index = key->hash % hash->size; HklHashElement* element = &hash->buckets[index]; assert(element != NULL); // Collision if (element->data != NULL) { if (element->is_tree) { hkl_tree_insert((HklTree*) element->data, key, value); } else { // First Collision HklPair* pair = element->data; element->data = hkl_tree_new(); hkl_tree_move_pair((HklTree*) element->data, pair); hkl_tree_insert((HklTree*) element->data, key, value); ++hash->length; // Mark the element as a tree element->is_tree = true; } } // No Collision else { // Nothing exists here. Make a pair element->data = hkl_pair_new_from_data(key, value); // The number of entries of the table increases ++hash->length; // If the hash table is 75% full if (hash->length >= 0.75*hash->size) hkl_hash_double(hash); } }
void mt_hash_insert(MtHash* hash, MtString* key, void* value) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtHashElement* element = &hash->buckets[index]; assert(element != NULL); // Collision handling if (element->data != NULL) { if (element->is_tree) { // Collision, tree already made mt_tree_insert((MtTree *) element->data, key, value); } else { // First collision, make a tree MtPair* pair = element->data; element->data = mt_tree_new(); mt_tree_move_pair((MtTree *) element->data, pair); ++hash->length; mt_tree_insert((MtTree *) element->data, key, value); element->is_tree = true; } } // No collision else { element->data = mt_pair_new(key, value); ++hash->length; if (hash->length >= 0.75 * hash->size) mt_hash_double_size(hash); } }
void hkl_hash_remove(HklHash* hash, HklString *key) { assert(hash != NULL); assert(key != NULL); // The string doesnt already have a hash // give it one if (key->hash == 0) key->hash = Murmur3(hkl_string_get_utf8(key), hkl_string_get_length(key)); size_t index = key->hash % hash->size; HklHashElement* element = &hash->buckets[index]; assert(element != NULL); if (element->data != NULL) { if (element->is_tree) { HklTree* tree = element->data; // Keep track of the old tree size size_t old_size = tree->size; // Attempt to remove the element from the tree hkl_tree_remove(tree, key); // Subtract the difference between the old and new // tree sizes from the hash length assert((old_size - tree->size) <= 1); hash->length -= old_size - tree->size; } else { hkl_pair_free((HklPair*) element->data); --hash->length; } } }
HklPair* hkl_hash_search(const HklHash* hash, HklString *key) { assert(hash != NULL); assert(key != NULL); // The string doesnt already have a hash // give it one if (key->hash == 0) key->hash = Murmur3(hkl_string_get_utf8(key), hkl_string_get_length(key)); size_t index = key->hash % hash->size; HklHashElement* element = &hash->buckets[index]; assert(element != NULL); // Found a collision if (element->data != NULL) { if (element->is_tree) { return hkl_tree_search((HklTree*) element->data, key); } // I'm an idiot for not thinking to put this here... -Scott else if (hkl_string_compare(((HklPair*) element->data)->key, key) == 0) { return (HklPair*) element->data; } else { return NULL; } } else { // No such element, do nothing return NULL; } }
void mt_hash_remove(MtHash* hash, MtString* key) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtHashElement* element = &hash->buckets[index]; assert(element != NULL); if (element->data != NULL) { if (element->is_tree) { MtTree* tree = element->data; // Save the size before attempting to remove element from tree size_t old_size = tree->size; mt_tree_remove(tree, key); // Decrement the size of the hash by the difference in the // old and new sizes of the tree. This shouldn't ever be more than 1. assert((old_size - tree->size) <= 1); hash->length -= old_size - tree->size; } else { mt_pair_free((MtPair*) element->data); --hash->length; } } }
MtPair* mt_hash_search(MtHash* hash, MtString* key) { assert(hash != NULL); assert(key != NULL); if (key->hash == 0) key->hash = Murmur3(mt_string_get_utf8(key), mt_string_get_length(key)); size_t index = key->hash % hash->size; MtPair* element = hash->buckets[index]; while (element != NULL) { if (mt_string_compare(key, element->key) == 0) return element; ++index; index %= hash->size; element = hash->buckets[index]; } // Nothing was found return NULL; }
cell AMX_NATIVE_CALL amx_DC_CMD(AMX* amx, cell* params) { cell *addr; int len; amx_GetAddr(amx, params[2], &addr); amx_StrLen(addr, &len); if(len>127) len=127; ++len; char cmdtext[128]; amx_GetString(cmdtext, addr, 0, len); cmdtext[0] = '_'; // converting string to lower case int pos=0, cmd_end; do{ ++pos; if(('A' <= cmdtext[pos]) && (cmdtext[pos] <= 'Z')) cmdtext[pos] += ('a'-'A'); else if(cmdtext[pos] == '\0') break; else if(cmdtext[pos] == ' ') { cmd_end = pos; cmdtext[pos++] = '\0'; goto loop1_exit; } }while(1); cmd_end = 0; loop1_exit: // search for command index in all AMX instances int pubidx; cell retval, params_addr; int i; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && (amx_FindPublic(amx_List[i].amx, cmdtext, &pubidx) == AMX_ERR_NONE)) { // if current AMX instance has OnPlayerCommandReceived callback - invoke it if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } // if command wasn't found - perhaps this is an alternative command if(Alts_n != 0) { int hash; // remove extra space characters between command name and parameters //logprintf("attempting to find alt %s, len = %d", cmdtext, (cmdtext[pos])?(pos-1):(pos)); Murmur3(cmdtext, (cmdtext[pos])?(pos-1):(pos), &hash); if(cmdtext[pos]) { pos--; while(cmdtext[++pos] == ' '){} } //logprintf((char*)"Murmur3(%s) = 0x%X", cmdtext, hash); boost::unordered_map<int,int>::const_iterator alt; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && ((alt = Alts[i].find(hash)) != Alts[i].end())) { pubidx = alt->second; //logprintf("found alt: %s, amx = %d, idx = %d", cmdtext, (int)amx, pubidx); if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } } // if command not found - call OnPlayerCommandPerformed callback in gamemode AMX (success = -1) if(amx_List[0].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[0].amx, -1); amx_PushString(amx_List[0].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[0].amx, params[1]); amx_Exec(amx_List[0].amx, &retval, amx_List[0].OPCP); amx_Release(amx_List[0].amx, params_addr); } return 1; }
cell AMX_NATIVE_CALL amx_RegisterAlt(AMX* amx, cell* params) { int amx_n; for(amx_n=0; amx_n<=lastAMX; ++amx_n) if(amx == amx_List[amx_n].amx) break; if(amx_n>lastAMX) // if amx wasn't found in list return 0; cell *addr; int len; amx_GetAddr(amx, params[1], &addr); amx_StrLen(addr, &len); if(len>31) len=31; ++len; char cmd[32]; amx_GetString(cmd, addr, 0, len); cmd[0] = '_'; // converting string to lower case int pos=0; do{ ++pos; if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z')) cmd[pos] += ('a'-'A'); else if(cmd[pos] == '\0') break; else if((cmd[pos] == ' ') || (cmd[pos] == '\t')) { cmd[pos] = '\0'; break; } }while(1); int pubidx; if(amx_FindPublic(amx, cmd, &pubidx) != AMX_ERR_NONE) { //logprintf((char*)"RegisterAlt: Couldn't find function %s", cmd); return 1; } int alt_n = (params[0]/4), hash; //logprintf("RegisterAlt: alts = %d", alt_n-1); do{ if(amx_GetAddr(amx, params[alt_n], &addr) != AMX_ERR_NONE) continue; amx_StrLen(addr, &len); if(len>31) len=31; // command length must be up to 31 chars ++len; amx_GetString(cmd, addr, 0, len); cmd[0] = '_'; pos = 0; do{ ++pos; if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z')) cmd[pos] += ('a'-'A'); else if(cmd[pos] == '\0') break; else if((cmd[pos] == ' ') || (cmd[pos] == '\t')) { cmd[pos] = '\0'; break; } }while(1); //logprintf((char*)"%s, len = %d", cmd, pos); Murmur3(cmd, pos, &hash); //logprintf("RegisterAlt: Murmur3(%s) = 0x%X", cmd, hash); Alts[amx_n].insert(std::make_pair(hash, pubidx)); Alts_n++; //logprintf((char*)"RegisterAlt: new alt - %s, amx = %d, pubidx = %d", cmd, amx, pubidx); }while(--alt_n > 1); return 1; }