From f7346cef5febab6b3e32846ad0f7de6407b7246f Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Fri, 19 Oct 2018 10:36:39 -0400 Subject: [PATCH] Modified re-factored version of hash.c --- src/epanet.c | 1 - src/hash.c | 43 ++++++++++++++++++++++++------------------- tests/test_setid.cpp | 35 +++++++++++++++++++++-------------- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 2c9017b..1229139 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -850,7 +850,6 @@ int DLLEXPORT EN_close(EN_ProjectHandle ph) out_file_t *out; EN_Project *p = (EN_Project*)ph; - if (p->Openflag) { writetime(p, FMT105); } diff --git a/src/hash.c b/src/hash.c index 2d007e2..99c4cb4 100755 --- a/src/hash.c +++ b/src/hash.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------- ** hash.c ** - ** Implementation of a simple Hash Table that uses a string pointer - ** as a key and an associated integer as data. + ** Implementation of a simple Hash Table that uses a string as a key + ** and an associated integer as data. ** ** Written by L. Rossman - ** Last Updated on 10/17/18 + ** Last Updated on 10/19/18 ** ** Interface Functions: ** hashtable_create - creates a hash table @@ -47,6 +47,14 @@ unsigned int gethash(char *str) return retHash; } +char *dupstr(const char *s) +{ + size_t size = strlen(s) + 1; + char *p = malloc(size); + if (p) memcpy(p, s, size); + return p; +} + HashTable *hashtable_create() { int i; @@ -65,7 +73,7 @@ int hashtable_insert(HashTable *ht, char *key, int data) if ( i >= HASHTABLEMAXSIZE ) return 0; entry = (DataEntry *) malloc(sizeof(DataEntry)); if (entry == NULL) return(0); - entry->key = key; + entry->key = dupstr(key); entry->data = data; entry->next = ht[i]; ht[i] = entry; @@ -76,6 +84,7 @@ int hashtable_update(HashTable *ht, char *key, int new_data) { unsigned int i = gethash(key); DataEntry *entry; + if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; entry = ht[i]; while (entry != NULL) @@ -97,23 +106,15 @@ int hashtable_delete(HashTable *ht, char *key) if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; - // Check if first entry in bucket i to be deleted + preventry = NULL; entry = ht[i]; - if (strcmp(entry->key, key) == 0) - { - ht[i] = entry->next; - free(entry); - return 1; - } - - // Check remaining entries in bucket i - preventry = ht[i]; - entry = ht[i]->next; while (entry != NULL) { if (strcmp(entry->key, key) == 0) { - preventry->next = entry->next; + if (preventry == NULL) ht[i] = entry->next; + else preventry->next = entry->next; + free(entry->key); free(entry); return 1; } @@ -127,6 +128,7 @@ int hashtable_find(HashTable *ht, char *key) { unsigned int i = gethash(key); DataEntry *entry; + if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND; entry = ht[i]; while (entry != NULL) @@ -158,15 +160,18 @@ void hashtable_free(HashTable *ht) { DataEntry *entry, *nextentry; int i; + for (i = 0; i < HASHTABLEMAXSIZE; i++) { entry = ht[i]; while (entry != NULL) { - nextentry = entry->next; - free(entry); - entry = nextentry; + nextentry = entry->next; + free(entry->key); + free(entry); + entry = nextentry; } + ht[i] = NULL; } free(ht); } diff --git a/tests/test_setid.cpp b/tests/test_setid.cpp index 2b3693e..ee9e1da 100644 --- a/tests/test_setid.cpp +++ b/tests/test_setid.cpp @@ -1,4 +1,5 @@ // Test of ENsetid EPANET API Function +#define _CRT_SECURE_NO_DEPRECATE /* This is a test for the API functions that change a node or link ID name. @@ -11,9 +12,9 @@ A node and link name are changed, the network is saved, reopened and the new nam #include #include "epanet2.h" -#define DATA_PATH_INP "net1.inp" -#define DATA_PATH_RPT "test.rpt" -#define DATA_PATH_OUT "" +#define DATA_PATH_INP "./net1.inp" +#define DATA_PATH_RPT "./test.rpt" +#define DATA_PATH_OUT "./test.out" using namespace std; @@ -24,57 +25,63 @@ BOOST_AUTO_TEST_CASE(test_setid) int error = 0; int index; string newid; + + EN_ProjectHandle ph = NULL; + EN_createproject(&ph); std::string path_inp = std::string(DATA_PATH_INP); std::string path_rpt = std::string(DATA_PATH_RPT); std::string path_out = std::string(DATA_PATH_OUT); - error = ENopen(path_inp.c_str(), path_rpt.c_str(), ""); + error = EN_open(ph, path_inp.c_str(), path_rpt.c_str(), ""); BOOST_REQUIRE(error == 0); // Test of illegal node name change newid = "Illegal; node name"; - error = ENsetnodeid(3, (char *)newid.c_str()); + error = EN_setnodeid(ph, 3, (char *)newid.c_str()); BOOST_REQUIRE(error > 0); // Test of legal node name change newid = "Node3"; - error = ENsetnodeid(3, (char *)newid.c_str()); + error = EN_setnodeid(ph, 3, (char *)newid.c_str()); BOOST_REQUIRE(error == 0); // Test of illegal link name change newid = "Illegal; link name"; - error = ENsetlinkid(3, (char *)newid.c_str()); + error = EN_setlinkid(ph, 3, (char *)newid.c_str()); BOOST_REQUIRE(error > 0); // Test of legal link name change newid = "Link3"; - error = ENsetlinkid(3, (char *)newid.c_str()); + error = EN_setlinkid(ph, 3, (char *)newid.c_str()); BOOST_REQUIRE(error == 0); // Save the project - error = ENsaveinpfile("net1_setid.inp"); + error = EN_saveinpfile(ph, "net1_setid.inp"); BOOST_REQUIRE(error == 0); - error = ENclose(); + error = EN_close(ph); BOOST_REQUIRE(error == 0); + EN_deleteproject(&ph); // Re-open the saved project - error = ENopen("net1_setid.inp", path_rpt.c_str(), ""); + EN_createproject(&ph); + error = EN_open(ph, "net1_setid.inp", path_rpt.c_str(), ""); BOOST_REQUIRE(error == 0); // Check that 3rd node has its new name - error = ENgetnodeindex("Node3", &index); + error = EN_getnodeindex(ph, "Node3", &index); BOOST_REQUIRE(error == 0); BOOST_REQUIRE(index == 3); // Check that 3rd link has its new name - error = ENgetlinkindex("Link3", &index); + error = EN_getlinkindex(ph, "Link3", &index); BOOST_REQUIRE(error == 0); BOOST_REQUIRE(index == 3); - error = ENclose(); + error = EN_close(ph); BOOST_REQUIRE(error == 0); + EN_deleteproject(&ph); } BOOST_AUTO_TEST_SUITE_END()