/** * Remove an entry in the table * * @param key The key of the entry to remove * @return The previous value associated with the key, `NULL` i the key was not used */ void* itk_hash_table_remove(__this__, void* key) { long key_hash = hash(this, key); long index = truncate_hash(this, key_hash); itk_hash_entry* bucket = *(this->buckets + index); itk_hash_entry* last = NULL; void* rc; while (bucket) { if (TEST_KEY(this, bucket, key, key_hash)) { if (last == NULL) *(this->buckets + index) = bucket->next; else last->next = bucket->next; this->size--; rc = bucket->value; free(bucket); return rc; } last = bucket; bucket = bucket->next; } return NULL; }
static int populate_table(ft_instance_t ft, int count, of_match_t *match) { int idx; of_flow_add_t *flow_add_base; of_flow_add_t *flow_add; ft_entry_t *entry; flow_add_base = of_flow_add_new(OF_VERSION_1_0); TEST_ASSERT(of_flow_add_OF_VERSION_1_0_populate(flow_add_base, 1) != 0); of_flow_add_flags_set(flow_add_base, 0); TEST_OK(of_flow_add_match_get(flow_add_base, match)); for (idx = 0; idx < count; ++idx) { TEST_ASSERT((flow_add = of_object_dup((of_object_t *)flow_add_base)) != NULL); match->fields.eth_type = TEST_ETH_TYPE(idx); TEST_OK(of_flow_add_match_set(flow_add, match)); TEST_INDIGO_OK(FT_ADD(ft, TEST_KEY(idx), flow_add, &entry)); TEST_ASSERT(check_table_entry_states(ft) == 0); } CHECK_FLOW_COUNT(&ft->status, TEST_FLOW_COUNT); of_flow_add_delete(flow_add_base); return 0; }
/** * Add an entry to the table * * @param key The key of the entry to add * @param value The value of the entry to add * @return The previous value associated with the key, `NULL` i the key was not used */ void* itk_hash_table_put(__this__, void* key, void* value) { long key_hash = hash(this, key); long index = truncate_hash(this, key_hash); itk_hash_entry* bucket = *(this->buckets + index); void* rc; while (bucket) if (TEST_KEY(this, bucket, key, key_hash)) { rc = bucket->value; bucket->value = value; return rc; } else bucket = bucket->next; if (++(this->size) > this->threshold) { rehash(this); index = truncate_hash(this, key_hash); } bucket = malloc(sizeof(itk_hash_entry)); bucket->value = value; bucket->key = key; bucket->hash = key_hash; bucket->next = *(this->buckets + index); *(this->buckets + index) = bucket; return NULL; }
/** * Undo above */ static int depopulate_table(ft_instance_t ft) { int idx; ft_entry_t *entry; int count; count = ft->status.current_count; for (idx = 0; idx < count; ++idx) { entry = ft_id_lookup(ft, TEST_KEY(idx)); TEST_ASSERT(entry != NULL); TEST_ASSERT(entry->match.fields.eth_type == TEST_ETH_TYPE(idx)); FT_DELETE_ID(ft, TEST_KEY(idx), 1); /* Does callback */ TEST_ASSERT(check_table_entry_states(ft) == 0); } return 0; }
/** * Look up a value in the table * * @param key The key associated with the value * @return The value associated with the key, `NULL` i the key was not used */ void* itk_hash_table_get(__this__, void* key) { long key_hash = hash(this, key); long index = truncate_hash(this, key_hash); itk_hash_entry* bucket = *(this->buckets + index); while (bucket) { if (TEST_KEY(this, bucket, key, key_hash)) return bucket->value; bucket = bucket->next; } return NULL; }
/** * Check whether a key is used in the table * * @param key The key * @return Whether the key is used */ bool_t itk_hash_table_contains_key(__this__, void* key) { long key_hash = hash(this, key); long index = truncate_hash(this, key_hash); itk_hash_entry* bucket = *(this->buckets + index); while (bucket) { if (TEST_KEY(this, bucket, key, key_hash)) return true; bucket = bucket->next; } return false; }
static void test_ctrl_string_transformation(struct xkb_keymap *keymap) { char buf[256]; struct xkb_state *state = xkb_state_new(keymap); xkb_mod_index_t ctrl; assert(state); /* See xkb_state_key_get_utf8() for what's this all about. */ ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); assert(ctrl != XKB_MOD_INVALID); /* First without. */ TEST_KEY(KEY_A, "a", 0x61); TEST_KEY(KEY_B, "b", 0x62); TEST_KEY(KEY_C, "c", 0x63); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); /* And with. */ xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); TEST_KEY(KEY_A, "\x01", 0x01); TEST_KEY(KEY_B, "\x02", 0x02); TEST_KEY(KEY_C, "\x03", 0x03); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); /* Switch to ru layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + 8) == 1); /* Non ASCII. */ xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); TEST_KEY(KEY_A, "\x01", 0x01); TEST_KEY(KEY_B, "\x02", 0x02); xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); xkb_state_unref(state); }
static void test_get_utf8_utf32(struct xkb_keymap *keymap) { char buf[256]; struct xkb_state *state = xkb_state_new(keymap); assert(state); #define TEST_KEY(key, expected_utf8, expected_utf32) do { \ assert(xkb_state_key_get_utf8(state, key + 8, NULL, 0) == strlen(expected_utf8)); \ assert(xkb_state_key_get_utf8(state, key + 8, buf, sizeof(buf)) == strlen(expected_utf8)); \ assert(memcmp(buf, expected_utf8, sizeof(expected_utf8)) == 0); \ assert(xkb_state_key_get_utf32(state, key + 8) == expected_utf32); \ } while (0) /* Simple ASCII. */ TEST_KEY(KEY_A, "a", 0x61); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); /* Invalid. */ TEST_KEY(XKB_KEYCODE_INVALID - 8, "", 0); TEST_KEY(300, "", 0); /* No string. */ TEST_KEY(KEY_LEFTCTRL, "", 0); TEST_KEY(KEY_NUMLOCK, "", 0); /* Multiple keysyms. */ TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); /* Check truncation. */ memset(buf, 'X', sizeof(buf)); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 0) == strlen("HELLO")); assert(memcmp(buf, "X", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 1) == strlen("HELLO")); assert(memcmp(buf, "", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 2) == strlen("HELLO")); assert(memcmp(buf, "H", 2) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 3) == strlen("HELLO")); assert(memcmp(buf, "HE", 3) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 5) == strlen("HELLO")); assert(memcmp(buf, "HELL", 5) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 6) == strlen("HELLO")); assert(memcmp(buf, "HELLO", 6) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + 8, buf, 7) == strlen("HELLO")); assert(memcmp(buf, "HELLO\0X", 7) == 0); /* Switch to ru layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + 8) == 1); /* Non ASCII. */ TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_A, "ф", 0x0444); TEST_KEY(KEY_Z, "я", 0x044F); /* Switch back to us layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + 8) == 0); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); TEST_KEY(KEY_A, "A", 0x41); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "!", 0x21); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); xkb_state_unref(state); }