void bind_key (const char* _arg) { if (!_arg) { csKeyMap* map = mapping; while (map) { Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Key %s bound to %s.", CS::Quote::Single (keyname (map)), CS::Quote::Single (map->cmd)); map = map->next; } return; } char* arg = new char[strlen(_arg) + 1]; strcpy (arg, _arg); char* space = strchr (arg, ' '); if (space) { *space = 0; csKeyMap* map = find_mapping (arg); if (map) { delete [] map->cmd; } else { map = new csKeyMap (); map->next = mapping; map->prev = 0; if (mapping) mapping->prev = map; mapping = map; map_key (arg, map); } map->cmd = new char [strlen (space+1)+1]; strcpy (map->cmd, space+1); *space = ' '; } else { csKeyMap* map = find_mapping (arg); if (map) Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Key bound to %s!", CS::Quote::Single (map->cmd)); else Sys->Report (CS_REPORTER_SEVERITY_NOTIFY, "Key not bound!"); } delete[] arg; }
void * hash_table_get (struct hash_table *ht, const void *key) { struct mapping *mp = find_mapping (ht, key); if (mp) return mp->value; else return NULL; }
int hash_table_get_pair (struct hash_table *ht, const void *lookup_key, void *orig_key, void *value) { struct mapping *mp = find_mapping (ht, lookup_key); if (mp) { if (orig_key) *(void **)orig_key = mp->key; if (value) *(void **)value = mp->value; return 1; } else return 0; }
int hash_table_remove (struct hash_table *ht, const void *key) { struct mapping *mp = find_mapping (ht, key); if (!mp) return 0; else { int size = ht->size; struct mapping *mappings = ht->mappings; mp->key = NULL; --ht->count; /* Rehash all the entries following MP. The alternative approach is to mark the entry as deleted, i.e. create a "tombstone". That makes remove faster, but leaves a lot of garbage and slows down hash_table_get and hash_table_put. */ mp = NEXT_MAPPING (mp, mappings, size); LOOP_NON_EMPTY (mp, mappings, size) { const void *key2 = mp->key; struct mapping *mp_new = mappings + HASH_POSITION (ht, key2); /* Find the new location for the key. */ LOOP_NON_EMPTY (mp_new, mappings, size) if (key2 == mp_new->key) /* The mapping MP (key2) is already where we want it (in MP_NEW's "chain" of keys.) */ goto next_rehash; *mp_new = *mp; mp->key = NULL; next_rehash: ; } return 1; } }
int hash_table_contains (struct hash_table *ht, const void *key) { return find_mapping (ht, key) != NULL; }
template <> bkrl::message_type bkrl::from_hash(hash_t const hash) { using mapping_t = string_ref_mapping<message_type> const; using mt = message_type; static mapping_t mappings[] = { {"none", mt::none} , {"welcome", mt::welcome} , {"direction_prompt", mt::direction_prompt} , {"canceled", mt::canceled} , {"door_no_door", mt::door_no_door} , {"door_is_open", mt::door_is_open} , {"door_is_closed", mt::door_is_closed} , {"door_blocked", mt::door_blocked} , {"stairs_no_stairs", mt::stairs_no_stairs} , {"stairs_no_down", mt::stairs_no_down} , {"stairs_no_up", mt::stairs_no_up} , {"get_no_items", mt::get_no_items} , {"get_which_prompt", mt::get_which_prompt} , {"get_ok", mt::get_ok} , {"drop_nothing", mt::drop_nothing} , {"drop_ok", mt::drop_ok} , {"attack_regular", mt::attack_regular} , {"kill_regular", mt::kill_regular} , {"title_inventory", mt::title_inventory} , {"title_wield_wear", mt::title_wield_wear} , {"title_get", mt::title_get} , {"title_drop", mt::title_drop} , {"title_equipment", mt::title_equipment} , {"title_take_off", mt::title_take_off} , {"inventory_nothing", mt::inventory_nothing} , {"take_off_nothing", mt::take_off_nothing} , {"take_off_ok", mt::take_off_ok} , {"wield_wear_conflict", mt::wield_wear_conflict} , {"wield_wear_nothing", mt::wield_wear_nothing} , {"wield_wear_ok", mt::wield_wear_ok} , {"header_items", mt::header_items} , {"header_slot", mt::header_slot} , {"eqslot_head", mt::eqslot_head} , {"eqslot_arms_upper", mt::eqslot_arms_upper} , {"eqslot_arms_lower", mt::eqslot_arms_lower} , {"eqslot_hands", mt::eqslot_hands} , {"eqslot_chest", mt::eqslot_chest} , {"eqslot_waist", mt::eqslot_waist} , {"eqslot_legs_upper", mt::eqslot_legs_upper} , {"eqslot_legs_lower", mt::eqslot_legs_lower} , {"eqslot_feet", mt::eqslot_feet} , {"eqslot_finger_left", mt::eqslot_finger_left} , {"eqslot_finger_right", mt::eqslot_finger_right} , {"eqslot_neck", mt::eqslot_neck} , {"eqslot_back", mt::eqslot_back} , {"eqslot_hand_main", mt::eqslot_hand_main} , {"eqslot_hand_off", mt::eqslot_hand_off} , {"eqslot_ammo", mt::eqslot_ammo} , {"dtype_slash", mt::dtype_slash} , {"dtype_pierce", mt::dtype_pierce} , {"dtype_blunt", mt::dtype_blunt} , {"dtype_fire", mt::dtype_fire} , {"dtype_cold", mt::dtype_cold} , {"dtype_electric", mt::dtype_electric} , {"dtype_acid", mt::dtype_acid} , {"itype_weapon", mt::itype_weapon} , {"itype_armor", mt::itype_armor} , {"itype_potion", mt::itype_potion} }; return find_mapping(mappings, hash, mt::invalid); }
/** * Creates a Mapping from a file. * * Each line in the file results in a SingleMapping (unless it begins in #, * in which case it either indicates the name of the mapping or is a comment). * * Within a single line, the first white-space delimited token represents * the name of the class, and the other tokens are attribute values. * * Any parse failure in the file will stop the entire Mapping-creation process * and result in NULL being returned. * * @param corpus The corpus for which the Mapping is valid (pointer). * @param attr_name String naming the attribute for which the mapping is valid. * @param file_name The filename of the map spec. * @param error_string A char * (not char[]), which is set to an error * string, or to NULL if all is OK. * @return The resulting Mapping object, or NULL in case of error. */ Mapping read_mapping(Corpus *corpus, char *attr_name, char *file_name, char **error_string) { FILE *fd; Attribute *attr; Mapping m = NULL; char s[CL_MAX_LINE_LENGTH]; if (corpus == NULL) { *error_string = "corpus argument missing"; return NULL; } if (attr_name == NULL) { *error_string = "attribute name argument missing"; return NULL; } if ((attr = find_attribute(corpus, attr_name, ATT_POS, NULL)) == NULL) { *error_string = "no such attribute in corpus"; return NULL; } if ((fd = fopen(file_name, "r")) == NULL) { *error_string = "Can't open mapping file"; return NULL; } m = cl_malloc(sizeof(MappingRecord)); m->corpus = corpus; m->mapping_name = NULL; m->attribute = attr; m->nr_classes = 0; m->classes = NULL; *error_string = "Not yet implemented"; if (!m->attribute) { *error_string = "no such attribute for corpus"; drop_mapping(&m); } while ( m && fgets(s, CL_MAX_LINE_LENGTH, fd) != NULL ) { if (s[0] && s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0'; /* NB. The following if-else takes up all the rest of this while-loop. */ if (s[0] == '#') { /* lines beginning with # */ /* if this line begins with the NAME_TOKEN... */ if (strncasecmp(s, NAME_TOKEN, strlen(NAME_TOKEN)) == 0) { /* set the name */ if (m->mapping_name) { *error_string = "Multiple mapping names declared"; drop_mapping(&m); } else if (!s[strlen(NAME_TOKEN)]) { *error_string = "Error in #NAME declaration"; drop_mapping(&m); } else { m->mapping_name = cl_strdup(s + strlen(NAME_TOKEN)); } } /* everything else beginning with # is a comment (and can thus be ignored) */ } else if (s[0]) { /* lines NOT beginning with # */ /* make new single mapping */ char *token; SingleMappingRecord *this_class = NULL; token = strtok(s, " \t\n"); if (token) { /* first token is class name, rest are attribute values */ /* test: class 'token' already defined? */ if (find_mapping(m, token) != NULL) { *error_string = "Class defined twice"; drop_mapping(&m); break; } /* create new class */ if (m->nr_classes == 0) { m->classes = (SingleMappingRecord *) cl_malloc(sizeof(SingleMappingRecord) * CLASS_REALLOC_THRESHOLD); } else if (m->nr_classes % CLASS_REALLOC_THRESHOLD == 0) { m->classes = (SingleMappingRecord *) cl_realloc(m->classes, sizeof(SingleMappingRecord) * (m->nr_classes + CLASS_REALLOC_THRESHOLD)); } /* else there is enough memory for this new class already! */ if (m->classes == NULL) { *error_string = "Memory allocation failure"; drop_mapping(&m); } else { m->classes[m->nr_classes].class_name = cl_strdup(token); m->classes[m->nr_classes].nr_tokens = 0; m->classes[m->nr_classes].tokens = NULL; this_class = &(m->classes[m->nr_classes]); } /* create single mappings : loop through remaining tokens on this line */ while (m && (token = strtok(NULL, " \t\n"))) { int id; /* test: token member of attribute values of my attribute? */ id = get_id_of_string(attr, token); if (id < 0 || cderrno != CDA_OK) { *error_string = "token not member of attribute"; drop_mapping(&m); break; } /* test: token already member of any class? */ if (map_token_to_class(m, token) != NULL) { *error_string = "token member of several classes"; drop_mapping(&m); break; } else if (this_class->tokens) { int i; for (i = 0; i < this_class->nr_tokens; i++) if (this_class->tokens[i] == id) { *error_string = "token member of several classes"; drop_mapping(&m); break; } } /* having passed all the tests, put token id into this mapping */ if (m) { if (this_class->nr_tokens == 0) { this_class->tokens = (int *) cl_malloc(sizeof(int) * TOKEN_REALLOC_THRESHOLD); } else if (this_class->nr_tokens % TOKEN_REALLOC_THRESHOLD == 0) { this_class->tokens = (int *) cl_realloc(this_class->tokens, sizeof(int) * (this_class->nr_tokens + TOKEN_REALLOC_THRESHOLD)); } if (this_class->tokens == NULL) { *error_string = "Memory allocation failure"; drop_mapping(&m); } else { this_class->tokens[this_class->nr_tokens] = id; this_class->nr_tokens++; } } } /* endwhile (loop for each token on a line) */ if (m) { m->nr_classes++; /* sort token IDs in increasing order */ qsort(this_class->tokens, this_class->nr_tokens, sizeof(int), intcompare); } } } } /* endwhile (main loop for each line in the mapping file */ fclose(fd); return m; }