Merge pull request #303 from LRossman/dev-lrossman
Fix #211 for EN_setreport
This commit is contained in:
@@ -129,8 +129,6 @@ Both network files are available [here](https://doi.org/10.23719/1375314).
|
||||
## New API functions
|
||||
|Function|Description|
|
||||
|--|--|
|
||||
|`ENaddlink`| |
|
||||
|`ENaddnode`| |
|
||||
|`ENgetcurvetype`| |
|
||||
|`ENgetdemandmodel`||
|
||||
|`ENsetdemandmodel`||
|
||||
@@ -156,6 +154,8 @@ Both network files are available [here](https://doi.org/10.23719/1375314).
|
||||
|`ENaddlink`||
|
||||
|`ENdeletelink`||
|
||||
|`ENdeletenode`||
|
||||
| `ENsetnodeid` ||
|
||||
| `ENsetlinkid` ||
|
||||
|`ENgetdemandname`||
|
||||
|`ENsetdemandname`||
|
||||
|
||||
|
||||
@@ -250,7 +250,9 @@ Public Const EN_G_CURVE = 4 ' General\default curve
|
||||
Declare Function ENsetflowunits Lib "epanet2.dll" (ByVal code As Long) As Long
|
||||
Declare Function ENaddcontrol Lib "epanet2.dll" (Cindex As Long, ByVal Ctype As Long, ByVal Lindex As Long, ByVal setting As Single, ByVal Nindex As Long, ByVal Level As Single) As Long
|
||||
Declare Function ENsetcontrol Lib "epanet2.dll" (ByVal Cindex As Long, ByVal Ctype As Long, ByVal Lindex As Long, ByVal setting As Single, ByVal Nindex As Long, ByVal Level As Single) As Long
|
||||
Declare Function ENsetnodeid Lib "epanet2.dll" (ByVal index As Long, ByVal newid As String) As Long
|
||||
Declare Function ENsetnodevalue Lib "epanet2.dll" (ByVal index As Long, ByVal code As Long, ByVal value As Single) As Long
|
||||
Declare Function ENsetlinkid Lib "epanet2.dll" (ByVal index As Long, ByVal newid As String) As Long
|
||||
Declare Function ENsetlinkvalue Lib "epanet2.dll" (ByVal index As Long, ByVal code As Long, ByVal value As Single) As Long
|
||||
Declare Function ENaddpattern Lib "epanet2.dll" (ByVal id As String) As Long
|
||||
Declare Function ENsetpattern Lib "epanet2.dll" (ByVal index As Long, F As Any, ByVal N As Long) As Long
|
||||
|
||||
@@ -842,6 +842,14 @@ extern "C" {
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetcontrol(int cindex, int ctype, int lindex, EN_API_FLOAT_TYPE setting, int nindex, EN_API_FLOAT_TYPE level);
|
||||
|
||||
/**
|
||||
@brief Change the ID name for a node.
|
||||
@param index The index of a node. First node is index 1.
|
||||
@param newid A string containing the node's new ID name.
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetnodeid(int index, char *newid);
|
||||
|
||||
/**
|
||||
@brief Set a property value for a node.
|
||||
@@ -852,6 +860,14 @@ extern "C" {
|
||||
@see EN_NodeProperty
|
||||
*/
|
||||
int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v);
|
||||
|
||||
/**
|
||||
@brief Change the ID name for a link.
|
||||
@param index The index of a link. First link is index 1.
|
||||
@param newid A string containing the link's new ID name.
|
||||
@return Error code.
|
||||
*/
|
||||
int DLLEXPORT ENsetlinkid(int index, char *newid);
|
||||
|
||||
/**
|
||||
@brief Set a property value for a link.
|
||||
@@ -1297,7 +1313,9 @@ extern "C" {
|
||||
|
||||
int DLLEXPORT EN_addcontrol(EN_ProjectHandle ph, int *cindex, int ctype, int lindex, EN_API_FLOAT_TYPE setting, int nindex, EN_API_FLOAT_TYPE level);
|
||||
int DLLEXPORT EN_setcontrol(EN_ProjectHandle ph, int cindex, int ctype, int lindex, EN_API_FLOAT_TYPE setting, int nindex, EN_API_FLOAT_TYPE level);
|
||||
int DLLEXPORT EN_setnodeid(EN_ProjectHandle ph, int index, char *newid);
|
||||
int DLLEXPORT EN_setnodevalue(EN_ProjectHandle ph, int index, int code, EN_API_FLOAT_TYPE v);
|
||||
int DLLEXPORT EN_setlinkid(EN_ProjectHandle ph, int index, char *newid);
|
||||
int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code, EN_API_FLOAT_TYPE v);
|
||||
int DLLEXPORT EN_addpattern(EN_ProjectHandle ph, char *id);
|
||||
int DLLEXPORT EN_setpattern(EN_ProjectHandle ph, int index, EN_API_FLOAT_TYPE *f, int len);
|
||||
|
||||
@@ -227,7 +227,9 @@ Public Const EN_CUSTOM = 2 ' user-defined custom curve
|
||||
Declare Function ENgetversion Lib "epanet2.dll" (ByRef Value As Int32) As Int32
|
||||
|
||||
Declare Function ENsetcontrol Lib "epanet2.dll" (ByVal Cindex As Int32, ByVal CtlType As Int32, ByVal Lindex As Int32, ByVal Setting As Single, ByVal Nindex As Int32, ByVal Level As Single) As Int32
|
||||
Declare Function ENsetnodeid Lib "epanet2.dll" (ByVal index As Int32, ByVal newid As String) As Int32
|
||||
Declare Function ENsetnodevalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Code As Int32, ByVal Value As Single) As Int32
|
||||
Declare Function ENsetlinkid Lib "epanet2.dll" (ByVal index As Int32, ByVal newid As String) As Int32
|
||||
Declare Function ENsetlinkvalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Code As Int32, ByVal Value As Single) As Int32
|
||||
Declare Function ENsetpattern Lib "epanet2.dll" (ByVal Index as Int32, ByRef F as Single, ByVal N as Int32) as Int32
|
||||
Declare Function ENsetpatternvalue Lib "epanet2.dll" (ByVal Index As Int32, ByVal Period As Int32, ByVal Value As Single) As Int32
|
||||
|
||||
123
src/epanet.c
123
src/epanet.c
@@ -89,9 +89,9 @@ This module calls the following functions that reside in other modules:
|
||||
writelogo()
|
||||
writereport()
|
||||
HASH.C
|
||||
ENHashTablecreate()
|
||||
ENHashTableFind()
|
||||
ENHashTableFree()
|
||||
hashtable_create()
|
||||
hashtable_find()
|
||||
hashtable_free()
|
||||
|
||||
The macro ERRCODE(x) is defined in TYPES.H. It says if the current
|
||||
value of the error code variable (errcode) is not fatal (< 100) then
|
||||
@@ -437,10 +437,18 @@ int DLLEXPORT ENaddcontrol(int *cindex, int ctype, int lindex,
|
||||
level);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENsetnodeid(int index, char *newid) {
|
||||
return EN_setnodeid(_defaultModel, index, newid);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENsetnodevalue(int index, int code, EN_API_FLOAT_TYPE v) {
|
||||
return EN_setnodevalue(_defaultModel, index, code, v);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENsetlinkid(int index, char *newid) {
|
||||
return EN_setlinkid(_defaultModel, index, newid);
|
||||
}
|
||||
|
||||
int DLLEXPORT ENsetlinkvalue(int index, int code, EN_API_FLOAT_TYPE v) {
|
||||
return EN_setlinkvalue(_defaultModel, index, code, v);
|
||||
}
|
||||
@@ -842,14 +850,12 @@ int DLLEXPORT EN_close(EN_ProjectHandle ph)
|
||||
out_file_t *out;
|
||||
|
||||
EN_Project *p = (EN_Project*)ph;
|
||||
|
||||
if (p->Openflag) {
|
||||
writetime(p, FMT105);
|
||||
}
|
||||
freedata(p);
|
||||
|
||||
|
||||
out = &p->out_files;
|
||||
|
||||
if (out->TmpOutFile != out->OutFile) {
|
||||
if (out->TmpOutFile != NULL) {
|
||||
fclose(out->TmpOutFile);
|
||||
@@ -879,7 +885,7 @@ int DLLEXPORT EN_close(EN_ProjectHandle ph)
|
||||
remove(out->HydFname);
|
||||
if (out->Outflag == SCRATCH)
|
||||
remove(out->OutFname);
|
||||
|
||||
|
||||
p->Openflag = FALSE;
|
||||
p->hydraulics.OpenHflag = FALSE;
|
||||
p->save_options.SaveHflag = FALSE;
|
||||
@@ -1377,9 +1383,10 @@ int DLLEXPORT EN_setreport(EN_ProjectHandle ph, char *s) {
|
||||
|
||||
if (!p->Openflag)
|
||||
return set_error(p->error_handle, 102);
|
||||
if (strlen(s) > MAXLINE)
|
||||
if (strlen(s) >= MAXLINE)
|
||||
return set_error(p->error_handle, 250);
|
||||
strcpy(s1, s);
|
||||
strcat(s1, "\n");
|
||||
if (setreport(p, s1) > 0)
|
||||
return set_error(p->error_handle, 250);
|
||||
else
|
||||
@@ -2891,6 +2898,34 @@ int DLLEXPORT EN_setcontrol(EN_ProjectHandle ph, int cindex, int ctype, int lind
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_setnodeid(EN_ProjectHandle ph, int index, char *newid)
|
||||
{
|
||||
EN_Project *p = (EN_Project*)ph;
|
||||
EN_Network *net = &p->network;
|
||||
size_t n;
|
||||
|
||||
// Check for valid arguments
|
||||
if (index <= 0 || index > net->Nnodes)
|
||||
{
|
||||
return set_error(p->error_handle, 203);
|
||||
}
|
||||
n = strlen(newid);
|
||||
if (n < 1 || n > MAXID) return set_error(p->error_handle, 209);
|
||||
if (strcspn(newid, " ;") < n) return set_error(p->error_handle, 209);
|
||||
|
||||
// Check if another node with same name exists
|
||||
if (hashtable_find(net->NodeHashTable, newid) > 0)
|
||||
{
|
||||
return set_error(p->error_handle, 215);
|
||||
}
|
||||
|
||||
// Replace the existing node ID with the new value
|
||||
hashtable_delete(net->NodeHashTable, net->Node[index].ID);
|
||||
strncpy(net->Node[index].ID, newid, MAXID);
|
||||
hashtable_insert(net->NodeHashTable, net->Node[index].ID, index);
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_setnodevalue(EN_ProjectHandle ph, int index, int code, EN_API_FLOAT_TYPE v)
|
||||
/*----------------------------------------------------------------
|
||||
** Input: index = node index
|
||||
@@ -3157,6 +3192,34 @@ int DLLEXPORT EN_setnodevalue(EN_ProjectHandle ph, int index, int code, EN_API_F
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_setlinkid(EN_ProjectHandle ph, int index, char *newid)
|
||||
{
|
||||
EN_Project *p = (EN_Project*)ph;
|
||||
EN_Network *net = &p->network;
|
||||
size_t n;
|
||||
|
||||
// Check for valid arguments
|
||||
if (index <= 0 || index > net->Nlinks)
|
||||
{
|
||||
return set_error(p->error_handle, 204);
|
||||
}
|
||||
n = strlen(newid);
|
||||
if (n < 1 || n > MAXID) return set_error(p->error_handle, 211);
|
||||
if (strcspn(newid, " ;") < n) return set_error(p->error_handle, 211);
|
||||
|
||||
// Check if another link with same name exists
|
||||
if (hashtable_find(net->LinkHashTable, newid) > 0)
|
||||
{
|
||||
return set_error(p->error_handle, 215);
|
||||
}
|
||||
|
||||
// Replace the existing link ID with the new value
|
||||
hashtable_delete(net->LinkHashTable, net->Link[index].ID);
|
||||
strncpy(net->Link[index].ID, newid, MAXID);
|
||||
hashtable_insert(net->LinkHashTable, net->Link[index].ID, index);
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
int DLLEXPORT EN_setlinkvalue(EN_ProjectHandle ph, int index, int code,
|
||||
EN_API_FLOAT_TYPE v)
|
||||
|
||||
@@ -4260,8 +4323,8 @@ int allocdata(EN_Project *p)
|
||||
parser_data_t *par;
|
||||
|
||||
/* Allocate node & link ID hash tables */
|
||||
p->network.NodeHashTable = ENHashTableCreate();
|
||||
p->network.LinkHashTable = ENHashTableCreate();
|
||||
p->network.NodeHashTable = hashtable_create();
|
||||
p->network.LinkHashTable = hashtable_create();
|
||||
ERRCODE(MEMCHECK(p->network.NodeHashTable));
|
||||
ERRCODE(MEMCHECK(p->network.LinkHashTable));
|
||||
|
||||
@@ -4433,14 +4496,14 @@ void freedata(EN_Project *p)
|
||||
}
|
||||
free(net->Node);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory for other network objects */
|
||||
free(net->Link);
|
||||
free(net->Tank);
|
||||
free(net->Pump);
|
||||
free(net->Valve);
|
||||
free(net->Control);
|
||||
|
||||
|
||||
/* Free memory for time patterns */
|
||||
if (net->Pattern != NULL) {
|
||||
for (j = 0; j <= par->MaxPats; j++)
|
||||
@@ -4456,20 +4519,19 @@ void freedata(EN_Project *p)
|
||||
}
|
||||
free(net->Curve);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory for node coordinates */
|
||||
if (p->parser.Coordflag == TRUE) {
|
||||
free(net->Coord);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory for rule base (see RULES.C) */
|
||||
freerules(p);
|
||||
|
||||
|
||||
/* Free hash table memory */
|
||||
if (net->NodeHashTable != NULL)
|
||||
ENHashTableFree(net->NodeHashTable);
|
||||
if (net->LinkHashTable != NULL)
|
||||
ENHashTableFree(net->LinkHashTable);
|
||||
if (net->NodeHashTable != NULL) hashtable_free(net->NodeHashTable);
|
||||
|
||||
if (net->LinkHashTable != NULL) hashtable_free(net->LinkHashTable);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4572,7 +4634,7 @@ int findnode(EN_Network *n, char *id)
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
return (ENHashTableFind(n->NodeHashTable, id));
|
||||
return (hashtable_find(n->NodeHashTable, id));
|
||||
}
|
||||
|
||||
int findlink(EN_Network *n, char *id)
|
||||
@@ -4584,7 +4646,7 @@ int findlink(EN_Network *n, char *id)
|
||||
**----------------------------------------------------------------
|
||||
*/
|
||||
{
|
||||
return (ENHashTableFind(n->LinkHashTable, id));
|
||||
return (hashtable_find(n->LinkHashTable, id));
|
||||
}
|
||||
|
||||
int findtank(EN_Network *n, int index)
|
||||
@@ -4990,7 +5052,7 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
|
||||
|
||||
// shift rest of Node array
|
||||
for (index = net->Nnodes; index >= net->Njuncs; index--) {
|
||||
ENHashTableUpdate(net->NodeHashTable, net->Node[index].ID, index + 1);
|
||||
hashtable_update(net->NodeHashTable, net->Node[index].ID, index + 1);
|
||||
net->Node[index + 1] = net->Node[index];
|
||||
net->Coord[index + 1] = net->Coord[index];
|
||||
}
|
||||
@@ -5106,7 +5168,7 @@ int DLLEXPORT EN_addnode(EN_ProjectHandle ph, char *id, EN_NodeType nodeType) {
|
||||
coord->Y = 0;
|
||||
|
||||
/* Insert new node into hash table */
|
||||
ENHashTableInsert(net->NodeHashTable, node->ID, nIdx); /* see HASH.C */
|
||||
hashtable_insert(net->NodeHashTable, node->ID, nIdx); /* see HASH.C */
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
@@ -5129,8 +5191,8 @@ int DLLEXPORT EN_addlink(EN_ProjectHandle ph, char *id, EN_LinkType linkType, ch
|
||||
return set_error(p->error_handle, 215);
|
||||
|
||||
/* Lookup the from and to nodes */
|
||||
N1 = ENHashTableFind(net->NodeHashTable, fromNode);
|
||||
N2 = ENHashTableFind(net->NodeHashTable, toNode);
|
||||
N1 = hashtable_find(net->NodeHashTable, fromNode);
|
||||
N2 = hashtable_find(net->NodeHashTable, toNode);
|
||||
|
||||
if (N1 == 0 || N2 == 0) {
|
||||
return set_error(p->error_handle, 203);
|
||||
@@ -5212,7 +5274,7 @@ int DLLEXPORT EN_addlink(EN_ProjectHandle ph, char *id, EN_LinkType linkType, ch
|
||||
link->Rpt = 0;
|
||||
strcpy(link->Comment, "");
|
||||
|
||||
ENHashTableInsert(net->LinkHashTable, link->ID, n);
|
||||
hashtable_insert(net->LinkHashTable, link->ID, n);
|
||||
return set_error(p->error_handle, 0);
|
||||
}
|
||||
|
||||
@@ -5235,15 +5297,14 @@ int DLLEXPORT EN_deletelink(EN_ProjectHandle ph, int index) {
|
||||
link = &net->Link[index];
|
||||
|
||||
// remove from hash table
|
||||
ENHashTableDelete(net->LinkHashTable, link->ID);
|
||||
ENHashTableFind(net->LinkHashTable, link->ID);
|
||||
hashtable_delete(net->LinkHashTable, link->ID);
|
||||
|
||||
// shift link and pump arrays to re-sort link indices
|
||||
net->Nlinks--;
|
||||
for (i = index; i <= net->Nlinks - 1; i++) {
|
||||
net->Link[i] = net->Link[i + 1];
|
||||
// update hashtable
|
||||
ENHashTableUpdate(net->LinkHashTable, net->Link[i].ID, i);
|
||||
hashtable_update(net->LinkHashTable, net->Link[i].ID, i);
|
||||
}
|
||||
for (i = 1; i <= net->Npumps; i++) {
|
||||
if (net->Pump[i].Link > index) {
|
||||
@@ -5296,14 +5357,14 @@ int DLLEXPORT EN_deletenode(EN_ProjectHandle ph, int index) {
|
||||
// TODO: check for existing controls/rules that reference this node?
|
||||
|
||||
// remove from hash table
|
||||
ENHashTableDelete(net->NodeHashTable, net->Node[index].ID);
|
||||
hashtable_delete(net->NodeHashTable, net->Node[index].ID);
|
||||
|
||||
// shift node and coord array to remove node
|
||||
for (i = index; i <= net->Nnodes - 1; i++) {
|
||||
net->Node[i] = net->Node[i + 1];
|
||||
net->Coord[i] = net->Coord[i + 1];
|
||||
// update hashtable
|
||||
ENHashTableUpdate(net->NodeHashTable, net->Node[i].ID, i);
|
||||
hashtable_update(net->NodeHashTable, net->Node[i].ID, i);
|
||||
}
|
||||
|
||||
// update tank array
|
||||
|
||||
268
src/hash.c
268
src/hash.c
@@ -1,21 +1,20 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
** hash.c
|
||||
**
|
||||
** Implementation of a simple Hash Table for string storage & retrieval
|
||||
** 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 6/19/03
|
||||
** Last Updated on 10/19/18
|
||||
**
|
||||
** The hash table data structure (HTable) is defined in "hash.h".
|
||||
** Interface Functions:
|
||||
** HTcreate() - creates a hash table
|
||||
** HTinsert() - inserts a string & its index value into a hash table
|
||||
** HTfind() - retrieves the index value of a string from a table
|
||||
** HTfree() - frees a hash table
|
||||
** hashtable_create - creates a hash table
|
||||
** hashtable_insert - inserts a string & its data value into a table
|
||||
** hashtable_find - retrieves the data value associated with a string
|
||||
** hashtable_findkey - retrieves the key associated with a data value
|
||||
** hashtable_delete - deletes an entry from a table
|
||||
** hashtable_free - frees a hash table
|
||||
**
|
||||
*********************************************************************
|
||||
** NOTE: This is a modified version of the original HASH.C module.
|
||||
*********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __APPLE__
|
||||
@@ -26,144 +25,153 @@
|
||||
#include <string.h>
|
||||
#include "hash.h"
|
||||
|
||||
unsigned int _enHash(char *str);
|
||||
unsigned int _enHash(char *str)
|
||||
{
|
||||
unsigned int hash = 5381;
|
||||
unsigned int retHash;
|
||||
int c;
|
||||
while ((c = *str++)) {
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
}
|
||||
retHash = hash % ENHASHTABLEMAXSIZE;
|
||||
|
||||
return retHash;
|
||||
}
|
||||
#define HASHTABLEMAXSIZE 128000
|
||||
|
||||
ENHashTable *ENHashTableCreate()
|
||||
typedef struct DataEntryStruct
|
||||
{
|
||||
int i;
|
||||
ENHashTable *ht = (ENHashTable *) calloc(ENHASHTABLEMAXSIZE, sizeof(ENHashTable));
|
||||
if (ht != NULL) {
|
||||
for (i=0; i<ENHASHTABLEMAXSIZE; i++) {
|
||||
ht[i] = NULL;
|
||||
char *key;
|
||||
int data;
|
||||
struct DataEntryStruct *next;
|
||||
} DataEntry;
|
||||
|
||||
unsigned int gethash(char *str)
|
||||
{
|
||||
unsigned int hash = 5381;
|
||||
unsigned int retHash;
|
||||
int c;
|
||||
while ((c = *str++))
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
}
|
||||
}
|
||||
return(ht);
|
||||
retHash = hash % HASHTABLEMAXSIZE;
|
||||
return retHash;
|
||||
}
|
||||
|
||||
int ENHashTableInsert(ENHashTable *ht, char *key, int data)
|
||||
char *dupstr(const char *s)
|
||||
{
|
||||
size_t len;
|
||||
unsigned int i = _enHash(key);
|
||||
ENHashEntry *entry;
|
||||
if ( i >= ENHASHTABLEMAXSIZE ) {
|
||||
return(0);
|
||||
}
|
||||
entry = (ENHashEntry *) malloc(sizeof(ENHashEntry));
|
||||
if (entry == NULL) {
|
||||
return(0);
|
||||
}
|
||||
len = strlen(key) + 1;
|
||||
entry->key = calloc(len, sizeof(char));
|
||||
strncpy(entry->key, key, len);
|
||||
entry->data = data;
|
||||
entry->next = ht[i];
|
||||
ht[i] = entry;
|
||||
return(1);
|
||||
size_t size = strlen(s) + 1;
|
||||
char *p = malloc(size);
|
||||
if (p) memcpy(p, s, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Abel Heinsbroek: Added function to update the hash table value for a given key */
|
||||
int ENHashTableUpdate(ENHashTable *ht, char *key, int new_data)
|
||||
HashTable *hashtable_create()
|
||||
{
|
||||
unsigned int i = _enHash(key);
|
||||
ENHashEntry *entry;
|
||||
if ( i >= ENHASHTABLEMAXSIZE ) {
|
||||
return(NOTFOUND);
|
||||
}
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if ( strcmp(entry->key,key) == 0 ) {
|
||||
entry->data = new_data;
|
||||
return(1);
|
||||
int i;
|
||||
HashTable *ht = (HashTable *) calloc(HASHTABLEMAXSIZE, sizeof(HashTable));
|
||||
if (ht != NULL)
|
||||
{
|
||||
for (i = 0; i < HASHTABLEMAXSIZE; i++) ht[i] = NULL;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
return(NOTFOUND);
|
||||
return ht;
|
||||
}
|
||||
|
||||
int ENHashTableDelete(ENHashTable *ht, char *key) {
|
||||
unsigned int i = _enHash(key);
|
||||
ENHashEntry *entry;
|
||||
if ( i >= ENHASHTABLEMAXSIZE ) {
|
||||
return(NOTFOUND);
|
||||
}
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (strcmp(entry->key, key) == 0) {
|
||||
entry->key = "";
|
||||
return(1);
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
return(NOTFOUND);
|
||||
}
|
||||
|
||||
int ENHashTableFind(ENHashTable *ht, char *key)
|
||||
int hashtable_insert(HashTable *ht, char *key, int data)
|
||||
{
|
||||
unsigned int i = _enHash(key);
|
||||
|
||||
ENHashEntry *entry;
|
||||
if ( i >= ENHASHTABLEMAXSIZE ) {
|
||||
return(NOTFOUND);
|
||||
}
|
||||
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if ( strcmp(entry->key,key) == 0 ) {
|
||||
return(entry->data);
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
return(NOTFOUND);
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry;
|
||||
if ( i >= HASHTABLEMAXSIZE ) return 0;
|
||||
entry = (DataEntry *) malloc(sizeof(DataEntry));
|
||||
if (entry == NULL) return(0);
|
||||
entry->key = dupstr(key);
|
||||
entry->data = data;
|
||||
entry->next = ht[i];
|
||||
ht[i] = entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *ENHashTableFindKey(ENHashTable *ht, char *key)
|
||||
int hashtable_update(HashTable *ht, char *key, int new_data)
|
||||
{
|
||||
unsigned int i = _enHash(key);
|
||||
ENHashEntry *entry;
|
||||
if ( i >= ENHASHTABLEMAXSIZE ) {
|
||||
return(NULL);
|
||||
}
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if ( strcmp(entry->key,key) == 0 ) {
|
||||
return(entry->key);
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void ENHashTableFree(ENHashTable *ht)
|
||||
{
|
||||
ENHashEntry *entry, *nextentry;
|
||||
int i;
|
||||
for (i=0; i<ENHASHTABLEMAXSIZE; i++)
|
||||
{
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry;
|
||||
|
||||
if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND;
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
nextentry = entry->next;
|
||||
free(entry->key);
|
||||
free(entry);
|
||||
entry = nextentry;
|
||||
if ( strcmp(entry->key, key) == 0 )
|
||||
{
|
||||
entry->data = new_data;
|
||||
return 1;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
free(ht);
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
int hashtable_delete(HashTable *ht, char *key)
|
||||
{
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry, *preventry;
|
||||
|
||||
if ( i >= HASHTABLEMAXSIZE ) return NOTFOUND;
|
||||
|
||||
preventry = NULL;
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (strcmp(entry->key, key) == 0)
|
||||
{
|
||||
if (preventry == NULL) ht[i] = entry->next;
|
||||
else preventry->next = entry->next;
|
||||
free(entry->key);
|
||||
free(entry);
|
||||
return 1;
|
||||
}
|
||||
preventry = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if ( strcmp(entry->key, key) == 0 )
|
||||
{
|
||||
return entry->data;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
char *hashtable_findkey(HashTable *ht, char *key)
|
||||
{
|
||||
unsigned int i = gethash(key);
|
||||
DataEntry *entry;
|
||||
if ( i >= HASHTABLEMAXSIZE ) return NULL;
|
||||
entry = ht[i];
|
||||
while (entry != NULL)
|
||||
{
|
||||
if ( strcmp(entry->key, key) == 0 ) return entry->key;
|
||||
entry = entry->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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->key);
|
||||
free(entry);
|
||||
entry = nextentry;
|
||||
}
|
||||
ht[i] = NULL;
|
||||
}
|
||||
free(ht);
|
||||
}
|
||||
|
||||
24
src/hash.h
24
src/hash.h
@@ -7,24 +7,16 @@
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
#define ENHASHTABLEMAXSIZE 128000
|
||||
#define NOTFOUND 0
|
||||
|
||||
typedef struct HTentryStruct
|
||||
{
|
||||
char *key;
|
||||
int data;
|
||||
struct HTentryStruct *next;
|
||||
} ENHashEntry;
|
||||
typedef struct DataEntryStruct *HashTable;
|
||||
|
||||
typedef ENHashEntry *ENHashTable;
|
||||
HashTable *hashtable_create(void);
|
||||
int hashtable_insert(HashTable *, char *, int);
|
||||
int hashtable_find(HashTable *, char *);
|
||||
char *hashtable_findkey(HashTable *, char *);
|
||||
void hashtable_free(HashTable *);
|
||||
int hashtable_update(HashTable *ht, char *key, int new_data);
|
||||
int hashtable_delete(HashTable *ht, char *key);
|
||||
|
||||
ENHashTable *ENHashTableCreate(void);
|
||||
int ENHashTableInsert(ENHashTable *, char *, int);
|
||||
int ENHashTableFind(ENHashTable *, char *);
|
||||
char *ENHashTableFindKey(ENHashTable *, char *);
|
||||
void ENHashTableFree(ENHashTable *);
|
||||
int ENHashTableUpdate(ENHashTable *ht, char *key, int new_data);
|
||||
int ENHashTableDelete(ENHashTable *ht, char *key);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -104,9 +104,9 @@ void setdefaults(EN_Project *pr)
|
||||
time_options_t *time = &pr->time_options;
|
||||
out_file_t *out = &pr->out_files;
|
||||
|
||||
strncpy(pr->Title[0], "", MAXMSG);
|
||||
strncpy(pr->Title[1], "", MAXMSG);
|
||||
strncpy(pr->Title[2], "", MAXMSG);
|
||||
strncpy(pr->Title[0], "", TITLELEN);
|
||||
strncpy(pr->Title[1], "", TITLELEN);
|
||||
strncpy(pr->Title[2], "", TITLELEN);
|
||||
strncpy(out->TmpDir, "", MAXFNAME);
|
||||
strncpy(out->TmpFname, "", MAXFNAME);
|
||||
strncpy(out->HydFname, "", MAXFNAME);
|
||||
|
||||
@@ -292,7 +292,7 @@ int newline(EN_Project *pr, int sect, char *line)
|
||||
n = (int)strlen(line);
|
||||
if (line[n - 1] == 10)
|
||||
line[n - 1] = ' ';
|
||||
strncpy(pr->Title[par->Ntitle], line, MAXMSG);
|
||||
strncpy(pr->Title[par->Ntitle], line, TITLELEN);
|
||||
par->Ntitle++;
|
||||
}
|
||||
return (0);
|
||||
@@ -472,7 +472,7 @@ int addnodeID(EN_Network *net, int n, char *id)
|
||||
return (0); /* see EPANET.C */
|
||||
}
|
||||
strncpy(net->Node[n].ID, id, MAXID);
|
||||
ENHashTableInsert(net->NodeHashTable, net->Node[n].ID, n); /* see HASH.C */
|
||||
hashtable_insert(net->NodeHashTable, net->Node[n].ID, n); /* see HASH.C */
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ int addlinkID(EN_Network *net, int n, char *id)
|
||||
return (0); /* see EPANET.C */
|
||||
}
|
||||
strncpy(net->Link[n].ID, id, MAXID);
|
||||
ENHashTableInsert(net->LinkHashTable, net->Link[n].ID, n); /* see HASH.C */
|
||||
hashtable_insert(net->LinkHashTable, net->Link[n].ID, n); /* see HASH.C */
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,9 +87,9 @@ int savenetdata(EN_Project *pr)
|
||||
fwrite(ibuf, sizeof(INT4), 15, outFile);
|
||||
|
||||
/* Write string variables to outFile */
|
||||
fwrite(pr->Title[0], sizeof(char), MAXMSG + 1, outFile);
|
||||
fwrite(pr->Title[1], sizeof(char), MAXMSG + 1, outFile);
|
||||
fwrite(pr->Title[2], sizeof(char), MAXMSG + 1, outFile);
|
||||
fwrite(pr->Title[0], sizeof(char), TITLELEN + 1, outFile);
|
||||
fwrite(pr->Title[1], sizeof(char), TITLELEN + 1, outFile);
|
||||
fwrite(pr->Title[2], sizeof(char), TITLELEN + 1, outFile);
|
||||
fwrite(par->InpFname, sizeof(char), MAXFNAME + 1, outFile);
|
||||
fwrite(rep->Rpt2Fname, sizeof(char), MAXFNAME + 1, outFile);
|
||||
fwrite(qu->ChemName, sizeof(char), MAXID + 1, outFile);
|
||||
|
||||
12
src/types.h
12
src/types.h
@@ -48,8 +48,9 @@ typedef int INT4;
|
||||
#define ENGINE_VERSION 201
|
||||
#define EOFMARK 0x1A /* Use 0x04 for UNIX systems */
|
||||
#define MAXTITLE 3 /* Max. # title lines */
|
||||
#define TITLELEN 79 // Max. # characters in a title line
|
||||
#define MAXID 31 /* Max. # characters in ID name */
|
||||
#define MAXMSG 79 /* Max. # characters in message text */
|
||||
#define MAXMSG 255 /* Max. # characters in message text */
|
||||
#define MAXLINE 255 /* Max. # characters read from input line */
|
||||
#define MAXFNAME 259 /* Max. # characters in file name */
|
||||
#define MAXTOKS 40 /* Max. items per line of input */
|
||||
@@ -873,9 +874,10 @@ typedef struct {
|
||||
Scurve *Curve; /* Curve data */
|
||||
Scoord *Coord; /* Coordinate data */
|
||||
Scontrol *Control; /* Control data */
|
||||
ENHashTable *NodeHashTable,
|
||||
*LinkHashTable; /* Hash tables for ID labels */
|
||||
Padjlist *Adjlist; /* Node adjacency lists */
|
||||
HashTable
|
||||
*NodeHashTable,
|
||||
*LinkHashTable; /* Hash tables for ID labels */
|
||||
Padjlist *Adjlist; /* Node adjacency lists */
|
||||
|
||||
} EN_Network;
|
||||
|
||||
@@ -900,7 +902,7 @@ typedef struct EN_Project {
|
||||
Openflag, /// Toolkit open flag
|
||||
Warnflag, /// Warning flag
|
||||
Msg[MAXMSG+1], /// General-purpose string: errors, messages
|
||||
Title[MAXTITLE][MAXMSG+1], /// Problem title
|
||||
Title[MAXTITLE][TITLELEN+1],/// Project title
|
||||
MapFname[MAXFNAME+1]; /// Map file name
|
||||
|
||||
error_handle_t* error_handle; //Simple error manager
|
||||
|
||||
87
tests/test_setid.cpp
Normal file
87
tests/test_setid.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
// 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.
|
||||
A node and link name are changed, the network is saved, reopened and the new names are checked.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE "toolkit"
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <string>
|
||||
#include "epanet2.h"
|
||||
|
||||
#define DATA_PATH_INP "./net1.inp"
|
||||
#define DATA_PATH_RPT "./test.rpt"
|
||||
#define DATA_PATH_OUT "./test.out"
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE (test_toolkit)
|
||||
|
||||
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 = 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 = EN_setnodeid(ph, 3, (char *)newid.c_str());
|
||||
BOOST_REQUIRE(error > 0);
|
||||
|
||||
// Test of legal node name change
|
||||
newid = "Node3";
|
||||
error = EN_setnodeid(ph, 3, (char *)newid.c_str());
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
// Test of illegal link name change
|
||||
newid = "Illegal; link name";
|
||||
error = EN_setlinkid(ph, 3, (char *)newid.c_str());
|
||||
BOOST_REQUIRE(error > 0);
|
||||
|
||||
// Test of legal link name change
|
||||
newid = "Link3";
|
||||
error = EN_setlinkid(ph, 3, (char *)newid.c_str());
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
// Save the project
|
||||
error = EN_saveinpfile(ph, "net1_setid.inp");
|
||||
BOOST_REQUIRE(error == 0);
|
||||
|
||||
error = EN_close(ph);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
EN_deleteproject(&ph);
|
||||
|
||||
// Re-open the saved project
|
||||
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 = EN_getnodeindex(ph, "Node3", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_REQUIRE(index == 3);
|
||||
|
||||
// Check that 3rd link has its new name
|
||||
error = EN_getlinkindex(ph, "Link3", &index);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
BOOST_REQUIRE(index == 3);
|
||||
|
||||
error = EN_close(ph);
|
||||
BOOST_REQUIRE(error == 0);
|
||||
EN_deleteproject(&ph);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user