Skip to content

Commit

Permalink
map changes (WIP) (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe authored Oct 24, 2023
1 parent 88f4740 commit 06ce01c
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 18 deletions.
10 changes: 5 additions & 5 deletions include/fuse/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fuse_map_t *fuse_map_new_ex(fuse_t *fuse, size_t size, const char *file, int lin
void fuse_map_destroy(fuse_t *fuse, fuse_map_t *self);

/** @brief Return statistics about the map
*
*
* Test for the number of elements in the map. If the size argument is not NULL,
* then the current maximum number of elements in the map is passed back. If this
* equals the count then the map is full.
Expand All @@ -61,12 +61,12 @@ size_t fuse_map_stats(fuse_map_t *self, size_t *size);
*/
void *fuse_map_get(fuse_map_t *self, void *key);

/** @brief Set a key-value pair in the map
/** @brief Set a value in the map
*
* @param self The map
* @param key The key to insert. The key cannot be a NULL value.
* @param value The value to insert. If the value is NULL, then the key is removed from the map.
* @return True on success, or false if the map is full
* @param key The key, cannot be a NULL value.
* @param value The value. If the value is NULL, then the key is deleted from the map.
* @return Returns false if the map is full.
*/
bool fuse_map_set(fuse_map_t *self, void *key, void *value);

Expand Down
78 changes: 67 additions & 11 deletions src/fuse/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ fuse_map_t *fuse_map_new_ex(fuse_t *fuse, size_t size, const char *file, int lin

// Set the instance properties
memset(instance, 0, alloc_size);
instance->count = 0;
instance->size = size;
instance->nodes = (struct fuse_map_node *)(instance + 1);
instance->hashfunc = NULL;

// Return success
return instance;
Expand All @@ -50,7 +52,7 @@ size_t fuse_map_stats(fuse_map_t *self, size_t *size)

/** @brief This is the hash function for void* keys
*/
inline size_t fuse_map_hashfunc(void *key)
size_t fuse_map_hashfunc(void *key)
{
if (key == 0)
{
Expand All @@ -64,31 +66,85 @@ inline size_t fuse_map_hashfunc(void *key)
return x;
}

/** @brief Set a key-value pair in the map
/** @brief Get a value from the map
*
* @param self The map
* @param key The key to insert. The key cannot be a NULL value.
* @param value The value to insert. If the value is NULL, then the key is removed from the map.
* @return True on success, or false if the map is full
* @param key The key, cannot be a NULL value.
* @return The value. Returns NULL if the value does not exist
*/
bool fuse_map_set(fuse_map_t *self, void *key, void *value)
void *fuse_map_get(fuse_map_t *self, void *key)
{
assert(self);
assert(key);

// TODO
// Obtain the hash value for the key, and the index into the map
size_t hash = self->hashfunc ? self->hashfunc(key) : fuse_map_hashfunc(key);
size_t first = hash % self->size;
size_t index = first;

// Walk through the nodes in the map, starting at the index
while (self->nodes[index].key != 0)
{
if (self->nodes[index].key == key && self->nodes[index].value != 0)
{
return self->nodes[index].value;
}
index = (index + 1) % self->size;
if (index == first)
{
// Key not found
return NULL;
}
}

// Key not found
return NULL;
}

/** @brief Get a value from the map
/** @brief Set a value in the map
*
* @param self The map
* @param key The key, cannot be a NULL value.
* @return The value. Returns NULL if the value does not exist
* @param value The value. If the value is NULL, then the key is deleted from the map.
* @return Returns false if the map is full.
*/
void *fuse_map_get(fuse_map_t *self, void *key)
bool fuse_map_set(fuse_map_t *self, void *key, void* value)
{
assert(self);
assert(key);

// TODO
// Obtain the hash value for the key, and the index into the map
size_t hash = self->hashfunc ? self->hashfunc(key) : fuse_map_hashfunc(key);
size_t first = hash % self->size;
size_t index = first;

// Walk through the nodes in the map, starting at the index
while (self->nodes[index].key != 0)
{
// If the key already exists
if (self->nodes[index].key == key || self->nodes[index].value == 0)
{
self->nodes[index].value = value;
self->count += value ? 1 : -1;
return true;
}

index = (index + 1) % self->size;
if (index == first)
{
// Full table, cannot set key
return false;
}
}

// If the value is not null, then add the key to the map
if (value)
{
self->nodes[index].key = key;
self->nodes[index].value = value;
self->count++;
}

// Key not found
return true;
}
1 change: 1 addition & 0 deletions src/fuse/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct fuse_map_instance
size_t size; ///< The maximum number of nodes in the instance
size_t count; ///< The number of nodes in the instance
struct fuse_map_node *nodes; ///< The nodes in the instance
size_t (*hashfunc)(void *); ///< The hash function for the map
};

/* @brief Represents a node in a map
Expand Down
49 changes: 47 additions & 2 deletions tests/map/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
int TEST_001()
{
fuse_debugf(NULL, "Creating a fuse application\n");
fuse_t* fuse = fuse_new(FUSE_FLAG_DEBUG);
fuse_t *fuse = fuse_new(FUSE_FLAG_DEBUG);
assert(fuse);

// Create a map and then destroy it
fuse_debugf(NULL, "Creating a map of 10 items\n");
fuse_map_t* map = fuse_map_new(fuse, 10);
fuse_map_t *map = fuse_map_new(fuse, 10);
assert(map);

// Number of items should be zero
Expand All @@ -28,9 +28,54 @@ int TEST_001()
return fuse_destroy(fuse);
}

int TEST_002()
{
fuse_debugf(NULL, "Creating a fuse application\n");
fuse_t *fuse = fuse_new(FUSE_FLAG_DEBUG);
assert(fuse);

// Create a map
fuse_debugf(NULL, "Creating a map of 10 items\n");
fuse_map_t *map = fuse_map_new(fuse, 10);
assert(map);

// Add 10 items
for (int i = 1; i <= 10; i++)
{
fuse_debugf(NULL, "Adding item %d=> %d\n", i, i);
assert(fuse_map_set(map, (void *)i, (void *)i));
assert(fuse_map_stats(map, NULL) == i);
}

// Get 10 items
for (int i = 1; i <= 10; i++)
{
void* j = fuse_map_get(map, (void *)i);
assert(j == (void *)i);
fuse_debugf(NULL, "Getting item %d => %d\n", i, j);
}

// Deleting 10 items
for (int i = 1; i <= 10; i++)
{
assert(fuse_map_set(map, (void *)i, 0));
void* j = fuse_map_get(map, (void *)i);
fuse_debugf(NULL, "Deleting item %d => %d (should be zero)\n", i, j);
assert(j == 0);
assert(fuse_map_stats(map, NULL) == 10 - i);
}

// Destroy the map
fuse_map_destroy(fuse, map);

// Return
return fuse_destroy(fuse);
}

int main()
{
assert(TEST_001() == 0);
assert(TEST_002() == 0);

// Return success
return 0;
Expand Down

0 comments on commit 06ce01c

Please sign in to comment.