#include <stdlib.h> #include <stdio.h> #include <string.h> #include "chtbl.h" /* ---------------------------------------------------------------- */ /* Element stored into the hash table */ /* ---------------------------------------------------------------- */ struct user_data { char *string; /* allocated */ int size; /* number of characters in 'string' */ }; /* ---------------------------------------------------------------- */ /* Function used to hash the input key */ /* */ /* ##### WARNING !!!! ##### */ /* */ /* This function *MUST* return a positive value, otherwize you will */ /* generate a segmentation fault! */ /* ---------------------------------------------------------------- */ int hash_function (const void *key) { struct user_data *data; int index, i; data = (struct user_data*)key; index = 0; for (i=0; i<data->size; i++) { index *= (int)(data->string[i]); } if (index < 0) { index *= - 1; } return index; } /* ---------------------------------------------------------------- */ /* Function used to free all memory allocated for the user defined */ /* data. */ /* ---------------------------------------------------------------- */ void free_user_data (void *d) { struct user_data *data; data = (struct user_data*)d; free (data->string); free (data); return; } /* ---------------------------------------------------------------- */ /* Function used to compare user defined data */ /* Must return 1 if d1 == d2 */ /* Must return 0 if d1 != d2 */ /* ---------------------------------------------------------------- */ int compare_user_data (const void *d1, const void *d2) { struct user_data *data1, *data2; data1 = (struct user_data*)d1; data2 = (struct user_data*)d2; return !strcmp(data1->string, data2->string); } /* ---------------------------------------------------------------- */ /* Main entry point */ /* ---------------------------------------------------------------- */ int main (int argc, char *argv[]) { CHTbl htab; char buffer[32]; int number_of_linked_list, number_of_arguments, i, cr; struct user_data *data, sdata; /* -------------------------------------------------------------- */ /* Check command line arguments */ /* -------------------------------------------------------------- */ if (argc != 3) { fprintf (stderr, "\nUsage: hash_table.test <number of linked list> <total number of elements>\n"); return 1; } number_of_linked_list = atoi(argv[1]); number_of_arguments = atoi(argv[2]); /* -------------------------------------------------------------- */ /* Initialize the hash thable */ /* -------------------------------------------------------------- */ if ( chtbl_init ( &htab, number_of_linked_list, hash_function, compare_user_data, free_user_data ) == -1 ) { fprintf (stderr, "\nhash_table.test: Initialization failed (Can not allocate memory)\n"); return 1; } /* -------------------------------------------------------------- */ /* Load hash table with elements */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Insert elements in the hash table #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<number_of_arguments; i++) { /* ------------------------------------------------------------ */ /* Allocate memory for data structure */ /* ------------------------------------------------------------ */ data = (struct user_data*)malloc(sizeof(struct user_data)); if (data == NULL) { fprintf (stderr, "\nhash_table.test: Can not allocate memory\n"); return 1; } sprintf (buffer, "%d", i); data->string = (char*)malloc((strlen(buffer)+1)*sizeof(char)); if (data->string == NULL) { fprintf (stderr, "\nhash_table.test: Can not allocate memory\n"); return 1; } strcpy (data->string, buffer); data->size = strlen(data->string); /* ------------------------------------------------------------ */ /* Now, put the data into the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nInserting \"%s\"", data->string); cr = chtbl_insert (&htab, (void*)data); switch (cr) { case -1: { fprintf (stderr, "\nhash_table.test: Insertion failed (Can not allocate memory)\n"); return 1; }; break; case 1: { fprintf (stdout, "\nData was already in the hash table"); }; break; } } /* -------------------------------------------------------------- */ /* Now, walk through the hash table */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Print the content of the hash table #"); fprintf (stdout, "\n######################################################\n\n"); data = (struct user_data*) chtbl_next(&htab, REWIND_HASH); i = 0; while (data != NULL) { fprintf (stdout, "%d: %s (%d)\n", i, data->string, data->size); data = (struct user_data*) chtbl_next(&htab, CURRENT_HASH); i++; } fprintf (stdout, "\n"); /* -------------------------------------------------------------- */ /* Search for elements */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Search for elements #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<40; i++) { /* ------------------------------------------------------------ */ /* Initialize the data to look for */ /* Please note that we could have written: */ /* */ /* sdata.string = buffer */ /* */ /* => No dynamic allocation (so no need to free memory). */ /* ------------------------------------------------------------ */ sprintf (buffer, "%d", i); sdata.string = (char*)malloc((strlen(buffer)+1)*sizeof(char)); if (sdata.string == NULL) { fprintf (stderr, "\nhash_table.test: Can not allocate memory\n"); return 1; } strcpy (sdata.string, buffer); sdata.size = strlen (sdata.string); /* ------------------------------------------------------------ */ /* Lookup the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nLooking for [%s] ...", sdata.string); data = &sdata; cr = chtbl_lookup (&htab, (void**)&data); if (cr == 0) { fprintf (stdout, "Element found [%s, %d]", data->string, data->size); } else { fprintf (stdout, "Element NOT found"); } /* ------------------------------------------------------------ */ /* Free allocated memory */ /* Please note this could have been avoided by writting */ /* */ /* sdata.string = buffer */ /* ------------------------------------------------------------ */ free (sdata.string); } /* -------------------------------------------------------------- */ /* Remove elements from the hash table */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Remove elements #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<40; i++) { /* ------------------------------------------------------------ */ /* Initialize the data to look for */ /* ------------------------------------------------------------ */ sprintf (buffer, "%d", i); sdata.string = buffer; data = &sdata; /* ------------------------------------------------------------ */ /* Remove the element from the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nRemoving element [%s] ...", sdata.string); cr = chtbl_remove (&htab, (void**)&data); if (cr == -1) { fprintf (stdout, " The element was not in the hash table"); } else { fprintf (stdout, " Element removed"); /* --------------------------------------------------------- */ /* WARNING */ /* ======= */ /* */ /* Keep in mind that it is the user's reponsability to free */ /* the memory allocated for the element's data. */ /* --------------------------------------------------------- */ free_user_data (data); } } /* -------------------------------------------------------------- */ /* Now make sure that the elements has been removed */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Lookup removed elements #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<40; i++) { /* ------------------------------------------------------------ */ /* Initialize the data to look for */ /* ------------------------------------------------------------ */ sprintf (buffer, "%d", i); sdata.string = buffer; data = &sdata; /* ------------------------------------------------------------ */ /* Lookup the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nLooking for [%s] ...", sdata.string); data = &sdata; cr = chtbl_lookup (&htab, (void**)&data); if (cr == 0) { fprintf (stdout, "Element found [%s, %d]", data->string, data->size); } else { fprintf (stdout, "Element NOT found"); } } /* -------------------------------------------------------------- */ /* Insert few data for exhaustive research in all the hash table */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Insert elements in the hash table #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<5; i++) { /* ------------------------------------------------------------ */ /* Allocate memory for data structure */ /* ------------------------------------------------------------ */ data = (struct user_data*)malloc(sizeof(struct user_data)); if (data == NULL) { fprintf (stderr, "\nhash_table.test: Can not allocate memory\n"); return 1; } sprintf (buffer, "%d", i); data->string = (char*)malloc((strlen(buffer)+1)*sizeof(char)); if (data->string == NULL) { fprintf (stderr, "\nhash_table.test: Can not allocate memory\n"); return 1; } strcpy (data->string, buffer); data->size = strlen(data->string); /* ------------------------------------------------------------ */ /* Now, put the data into the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nInserting \"%s\"", data->string); cr = chtbl_insert (&htab, (void*)data); switch (cr) { case -1: { fprintf (stderr, "\nhash_table.test: Insertion faile (Can not allocate memory)\n"); return 1; }; break; case 1: { fprintf (stdout, "\nData was already in the hash table"); }; break; } } /* -------------------------------------------------------------- */ /* Lookup up all the hash table to find the data */ /* -------------------------------------------------------------- */ fprintf (stdout, "\n"); fprintf (stdout, "\n######################################################"); fprintf (stdout, "\n# Looking up ALL the hash table to find dat #"); fprintf (stdout, "\n######################################################\n\n"); for (i=0; i<number_of_arguments; i++) { sprintf (buffer, "%d", i); sdata.string = buffer; data = &sdata; /* ------------------------------------------------------------ */ /* Lookup the hash table */ /* ------------------------------------------------------------ */ fprintf (stdout, "\nLooking for [%s] in ALL hash table ...", sdata.string); if (chtbl_find(&htab, (void*)&data) == 0) { /* ---------------------------------------------------------- */ /* Data found in hash table */ /* ---------------------------------------------------------- */ fprintf (stdout, " FOUND [%s, %d]", data->string, data->size); } else { /* ---------------------------------------------------------- */ /* Data not found */ /* ---------------------------------------------------------- */ fprintf (stdout, " NOT FOUND [%s, %d]", data->string, data->size); } } /* -------------------------------------------------------------- */ /* Free all memory allocated for the hash table and exit */ /* -------------------------------------------------------------- */ chtbl_destroy (&htab); return 0; }