From 1583bea1549e51069c32bfb830bf556b1cebf2e3 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Thu, 18 Apr 2019 07:00:07 -0400 Subject: [PATCH 1/4] Return object index from EN_addnode and EN_addlink (issue #432) Adds an output argument to EN_addnode and EN_addlink that returns the index of the newly added object. Also refactors the validity check on object ID names. --- CMakeLists.txt | 4 +- doc/modules.dox | 4 +- doc/toolkit-examples.dox | 43 +++++++-------- doc/toolkit-usage.dox | 15 +++--- include/epanet2.bas | 4 +- include/epanet2.def | 4 +- include/epanet2.h | 4 +- include/epanet2.vb | 4 +- include/epanet2_2.h | 7 ++- include/epanet_py.h | 4 +- src/epanet.c | 101 ++++++++++++++--------------------- src/epanet2.c | 8 +-- src/epanet_py.c | 8 +-- src/funcs.h | 3 +- src/project.c | 14 ++++- tests/test_link.cpp | 26 ++++----- tests/test_net_builder.cpp | 46 ++++++++-------- win_build/WinSDK/epanet2.def | 4 +- 18 files changed, 149 insertions(+), 154 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eaf8fd..93fbda1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,8 +83,8 @@ ENDIF (MSVC) # configure file groups -file(GLOB EPANET_SOURCES RELATIVE ${PROJECT_SOURCE_DIR} src/*.c src/util/cstr_helper.c) -file(GLOB EPANET_LIB_ALL RELATIVE ${PROJECT_SOURCE_DIR} src/* src/util/cstr_helper.*) +file(GLOB EPANET_SOURCES RELATIVE ${PROJECT_SOURCE_DIR} src/*.c) +file(GLOB EPANET_LIB_ALL RELATIVE ${PROJECT_SOURCE_DIR} src/*) # exclude epanet python API from the default build list(REMOVE_ITEM EPANET_LIB_ALL "src/epanet_py.c") source_group("Library" FILES ${EPANET_LIB_ALL}) diff --git a/doc/modules.dox b/doc/modules.dox index 77369fc..6a990be 100644 --- a/doc/modules.dox +++ b/doc/modules.dox @@ -141,7 +141,7 @@ These are symbolic constants used as function arguments. /** @addtogroup Nodes @{ -@fn int EN_addnode(EN_Project ph, char *id, int nodeType) +@fn int EN_addnode(EN_Project ph, char *id, int nodeType, int *index) @fn int EN_deletenode(EN_Project ph, int index, int actionCode) @fn int EN_getnodeindex(EN_Project ph, char *id, int *index) @fn int EN_getnodeid(EN_Project ph, int index, char *id) @@ -175,7 +175,7 @@ These are symbolic constants used as function arguments. /** @addtogroup Links @{ -@fn int EN_addlink(EN_Project ph, char *id, int linkType, char *fromNode, char *toNode) +@fn int EN_addlink(EN_Project ph, char *id, int linkType, char *fromNode, char *toNode, int *index) @fn int EN_deletelink(EN_Project ph, int index, int actionCode) @fn int EN_getlinkindex(EN_Project ph, char *id, int *index) @fn int EN_getlinkid(EN_Project ph, int index, char *id) diff --git a/doc/toolkit-examples.dox b/doc/toolkit-examples.dox index df55699..0d66e0d 100644 --- a/doc/toolkit-examples.dox +++ b/doc/toolkit-examples.dox @@ -53,51 +53,52 @@ void netbuilder() { // Create a project that uses gpm for flow units and // the Hazen-Williams formula for head loss + int index; EN_Project ph; EN_createproject(&ph); EN_init(ph, "", "", EN_GPM, EN_HW); // Add the first junction node to the project with // an elevation of 700 ft and a demand of 0 - EN_addnode(ph, "J1", EN_JUNCTION); - EN_setjuncdata(ph, 1, 700, 0, ""); + EN_addnode(ph, "J1", EN_JUNCTION, &index); + EN_setjuncdata(ph, index, 700, 0, ""); // Add the remaining two junctions with elevations of // 710 ft and demands of 250 and 500 gpm, respectively - EN_addnode(ph, "J2", EN_JUNCTION); - EN_setjuncdata(ph, 2, 710, 250, ""); - EN_addnode(ph, "J3", EN_JUNCTION); - EN_setjuncdata(ph, 3, 710, 500, ""); + EN_addnode(ph, "J2", EN_JUNCTION, &index); + EN_setjuncdata(ph, index, 710, 250, ""); + EN_addnode(ph, "J3", EN_JUNCTION, &index); + EN_setjuncdata(ph, index, 710, 500, ""); // Add the reservoir at an elevation of 650 ft - EN_addnode(ph, "R1", EN_RESERVOIR); - EN_setnodevalue(ph, 4, EN_ELEVATION, 650); + EN_addnode(ph, "R1", EN_RESERVOIR, &index); + EN_setnodevalue(ph, index, EN_ELEVATION, 650); // Add the tank node at elevation of 850 ft, initial water level // at 120 ft, minimum level at 100 ft, maximum level at 150 ft // and a diameter of 50.5 ft - EN_addnode(ph, "T1", EN_TANK); - EN_settankdata(ph, 5, 850, 120, 100, 150, 50.5, 0, ""); + EN_addnode(ph, "T1", EN_TANK, &index); + EN_settankdata(ph, index, 850, 120, 100, 150, 50.5, 0, ""); // Add the pipes to the project, setting their length, // diameter, and roughness values - EN_addlink(ph, "P1", EN_PIPE, "J1", "J2"); - EN_setpipedata(ph, 1, 10560, 12, 100, 0); - EN_addlink(ph, "P2", EN_PIPE, "J1", "T1"); - EN_setpipedata(ph, 2, 5280, 14, 100, 0); - EN_addlink(ph, "P3", EN_PIPE, "J1", "J3"); - EN_setpipedata(ph, 3, 5280, 14, 100, 0); - EN_addlink(ph, "P4", EN_PIPE, "J2", "J3"); - EN_setpipedata(ph, 4, 5280, 14, 100, 0); + EN_addlink(ph, "P1", EN_PIPE, "J1", "J2", &index); + EN_setpipedata(ph, index, 10560, 12, 100, 0); + EN_addlink(ph, "P2", EN_PIPE, "J1", "T1", &index); + EN_setpipedata(ph, index, 5280, 14, 100, 0); + EN_addlink(ph, "P3", EN_PIPE, "J1", "J3", &index); + EN_setpipedata(ph, index, 5280, 14, 100, 0); + EN_addlink(ph, "P4", EN_PIPE, "J2", "J3", &index); + EN_setpipedata(ph, index, 5280, 14, 100, 0); // Add a pump to the project - EN_addlink(ph, "PUMP", EN_PUMP, "R1", "J1"); + EN_addlink(ph, "PUMP", EN_PUMP, "R1", "J1", &index); // Create a single point head curve (index = 1) and - // assign it to the pump (index = 5) + // assign it to the pump EN_addcurve(ph, "C1"); EN_setcurvevalue(ph, 1, 1, 1500, 250); - EN_setlinkvalue(ph, 5, EN_PUMP_HCURVE, 1); + EN_setlinkvalue(ph, index, EN_PUMP_HCURVE, 1); // Save the project for future use EN_saveinpfile(ph, "example2.inp"); diff --git a/doc/toolkit-usage.dox b/doc/toolkit-usage.dox index b6de2d2..db1a8a3 100644 --- a/doc/toolkit-usage.dox +++ b/doc/toolkit-usage.dox @@ -55,27 +55,28 @@ if (errcode == 0) EN_deleteproject(&ph); \endcode -Note that after an input file has been loaded in this fashion the resulting network can have objects added or deleted, and their properties set using various Toolkit functions . +After an input file has been loaded in this fashion the resulting network can have objects added or deleted, and their properties set using the various Toolkit functions . -The second method for supplying network data to a project is to use the Toolkit's functions to add objects and to set their properties via code. In this case the @ref EN_init function should be called immediately after creating a project, passing in the names of a report and binary output files (both optional) as well as the choices of flow units and head loss formulas to use. After that the various `EN_add` functions, such as @ref EN_addnode, @ref EN_addlink, @ref EN_addpattern, @ref EN_addcontrol, etc., can be called to add new objects to the network. Here is a partial example: +The second method for supplying network data to a project is to use the Toolkit's functions to add objects and to set their properties via code. In this case the @ref EN_init function should be called immediately after creating a project, passing in the names of a report and binary output files (both optional) as well as the choices of flow units and head loss formulas to use. After that the various `EN_add` functions, such as @ref EN_addnode, @ref EN_addlink, @ref EN_addpattern, @ref EN_addcontrol, etc., can be called to add new objects to the network. Here is a partial example of constructing a network from code: \code {.c} +int index; EN_Project ph; EN_createproject(&ph); EN_init(ph, "net1.rpt", "", EN_GPM, EN_HW); -EN_addnode(ph, "J1", EN_JUNCTION); -EN_addnode(ph, "J2", EN_JUNCTION); -EN_addlink(ph, "P1", EN_PIPE, "J1", "J2"); +EN_addnode(ph, "J1", EN_JUNCTION, &index); +EN_addnode(ph, "J2", EN_JUNCTION, &index); +EN_addlink(ph, "P1", EN_PIPE, "J1", "J2", &index); // additional function calls to complete building the network \endcode -See the @ref Example2 for a more complete example. While adding objects their properties can be set as described in the next section. Attemtping to change a network's structure by adding or deleting nodes and links while the Toolkit's hydraulic or water quality solvers are open will result in an error condition. +See the @ref Example2 for a more complete example. The labels used to name objects cannot contain spaces, semi-colons, or double quotes nor exceed @ref EN_MAXID characters in length. While adding objects their properties can be set as described in the next section. Attemtping to change a network's structure by adding or deleting nodes and links while the Toolkit's hydraulic or water quality solvers are open will result in an error condition. @section Properties Setting Object Properties The Toolkit contains several functions for retrieving and setting the properties of a network's objects and its analysis options. The names of retrieval functions all begin with `EN_get` (e.g., @ref EN_getnodevalue, @ref EN_getoption, etc.) while the functions used for setting parameter values begin with `EN_set` (e.g., @ref EN_setnodevalue, @ref EN_setoption, etc.). -Most of these functions use an index number to refer to a specific network component (such as a node, link, time pattern or data curve). This number is simply the position of the component in the list of all components of similar type (e.g., node 10 is the tenth node, starting from 1, in the network) and is not the same as the ID label assigned to the component. A series of functions exist to determine a component's index number given its ID label (see @ref EN_getnodeindex, @ref EN_getlinkindex, @ref EN_getpatternindex, and @ref EN_getcurveindex). Likewise, functions exist to retrieve a component's ID label given its index number (see @ref EN_getlinkid, @ref EN_getnodeid, @ref EN_getpatternid, and @ref EN_getcurveid). The @ref EN_getcount function can be used to determine the number of different components in the network. Be aware that a component's index can change as elements are added or deleted from the network. +Most of these functions use an index number to refer to a specific network component (such as a node, link, time pattern or data curve). This number is simply the position of the component in the list of all components of similar type (e.g., node 10 is the tenth node, starting from 1, in the network) and is not the same as the ID label assigned to the component. A series of functions exist to determine a component's index number given its ID label (see @ref EN_getnodeindex, @ref EN_getlinkindex, @ref EN_getpatternindex, and @ref EN_getcurveindex). Likewise, functions exist to retrieve a component's ID label given its index number (see @ref EN_getlinkid, @ref EN_getnodeid, @ref EN_getpatternid, and @ref EN_getcurveid). The @ref EN_getcount function can be used to determine the number of different components in the network. Be aware that a component's index can change as elements are added or deleted from the network. The @ref EN_addnode and @ref EN_addlink functions return the index of the newly added node or link as a convenience for immediately setting their properties. The code below is an example of using the property retrieval and setting functions. It changes all links with diameter of 10 inches to 12 inches. diff --git a/include/epanet2.bas b/include/epanet2.bas index c09fd4a..11d8312 100644 --- a/include/epanet2.bas +++ b/include/epanet2.bas @@ -291,7 +291,7 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENsetqualtype Lib "epanet2.dll" (ByVal qualType As Long, ByVal chemName As String, ByVal chemUnits As String, ByVal traceNode As String) As Long 'Node Functions - Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Long) As Long + Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Long, index As Long) As Long Declare Function ENdeletenode Lib "epanet2.dll" (ByVal index As Long, ByVal actionCode As Long) As Long Declare Function ENgetnodeindex Lib "epanet2.dll" (ByVal id As String, index As Long) As Long Declare Function ENgetnodeid Lib "epanet2.dll" (ByVal index As Long, ByVal id As String) As Long @@ -316,7 +316,7 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENsetdemandname Lib "epanet2.dll" (ByVal nodeIndex As Long, ByVal demandIndex As Long, ByVal demandName As String) As Long 'Link Functions - Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Long, ByVal fromNode As String, ByVal toNode As String) As Long + Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Long, ByVal fromNode As String, ByVal toNode As String, index As Long) As Long Declare Function ENdeletelink Lib "epanet2.dll" (ByVal index As Long, ByVal actionCode As Long) As Long Declare Function ENgetlinkindex Lib "epanet2.dll" (ByVal id As String, index As Long) As Long Declare Function ENgetlinkid Lib "epanet2.dll" (ByVal index As Long, ByVal id As String) As Long diff --git a/include/epanet2.def b/include/epanet2.def index f9374ef..ebd08f9 100644 --- a/include/epanet2.def +++ b/include/epanet2.def @@ -3,8 +3,8 @@ LIBRARY EPANET2.DLL EXPORTS ENaddcontrol = _ENaddcontrol@24 ENaddcurve = _ENaddcurve@4 - ENaddlink = _ENaddlink@16 - ENaddnode = _ENaddnode@8 + ENaddlink = _ENaddlink@20 + ENaddnode = _ENaddnode@12 ENaddpattern = _ENaddpattern@4 ENaddrule = _ENaddrule@4 ENclearreport = _ENclearreport@0 diff --git a/include/epanet2.h b/include/epanet2.h index 2bbc94f..837d12c 100644 --- a/include/epanet2.h +++ b/include/epanet2.h @@ -190,7 +190,7 @@ extern "C" { ********************************************************************/ - int DLLEXPORT ENaddnode(char *id, int nodeType); + int DLLEXPORT ENaddnode(char *id, int nodeType, int *index); int DLLEXPORT ENdeletenode(int index, int actionCode); @@ -252,7 +252,7 @@ extern "C" { ********************************************************************/ - int DLLEXPORT ENaddlink(char *id, int linkType, char *fromNode, char *toNode); + int DLLEXPORT ENaddlink(char *id, int linkType, char *fromNode, char *toNode, int *index); int DLLEXPORT ENdeletelink(int index, int actionCode); diff --git a/include/epanet2.vb b/include/epanet2.vb index 58cad9f..70132f1 100644 --- a/include/epanet2.vb +++ b/include/epanet2.vb @@ -296,7 +296,7 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENsetqualtype Lib "epanet2.dll" (ByVal qualType As Int32, ByVal chemName As String, ByVal chemUnits As String, ByVal traceNode As String) As Int32 'Node Functions - Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Int32) As Int32 + Declare Function ENaddnode Lib "epanet2.dll" (ByVal id As String, ByVal nodeType As Int32, Index As Int32) As Int32 Declare Function ENdeletenode Lib "epanet2.dll" (ByVal index As Int32, ByVal actionCode As Int32) As Int32 Declare Function ENgetnodeindex Lib "epanet2.dll" (ByVal id As String, index As Int32) As Int32 Declare Function ENgetnodeid Lib "epanet2.dll" (ByVal index As Int32, ByVal id As String) As Int32 @@ -321,7 +321,7 @@ Public Const EN_R_IS_ACTIVE = 3 Declare Function ENsetdemandname Lib "epanet2.dll" (ByVal nodeIndex As Int32, ByVal demandIndex As Int32, ByVal demandName As String) As Int32 'Link Functions - Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Int32, ByVal fromNode As String, ByVal toNode As String) As Int32 + Declare Function ENaddlink Lib "epanet2.dll" (ByVal id As String, ByVal linkType As Int32, ByVal fromNode As String, ByVal toNode As String, Index As Int32) As Int32 Declare Function ENdeletelink Lib "epanet2.dll" (ByVal index As Int32, ByVal actionCode As Int32) As Int32 Declare Function ENgetlinkindex Lib "epanet2.dll" (ByVal id As String, index As Int32) As Int32 Declare Function ENgetlinkid Lib "epanet2.dll" (ByVal index As Int32, ByVal id As String) As Int32 diff --git a/include/epanet2_2.h b/include/epanet2_2.h index f6ad002..051e623 100644 --- a/include/epanet2_2.h +++ b/include/epanet2_2.h @@ -752,11 +752,12 @@ typedef struct Project *EN_Project; @param ph an EPANET project handle. @param id the ID name of the node to be added. @param nodeType the type of node being added (see @ref EN_NodeType) + @param[out] index the index of the newly added node @return an error code. When a new node is created all of it's properties (see @ref EN_NodeProperty) are set to 0. */ - int DLLEXPORT EN_addnode(EN_Project ph, char *id, int nodeType); + int DLLEXPORT EN_addnode(EN_Project ph, char *id, int nodeType, int *index); /** @brief Deletes a node from a project. @@ -1027,6 +1028,7 @@ typedef struct Project *EN_Project; @param linkType The type of link being added (see @ref EN_LinkType) @param fromNode The ID name of the link's starting node. @param toNode The ID name of the link's ending node. + @param[out] index the index of the newly added link. @return an error code. A new pipe is assigned a diameter of 10 inches (or 254 mm), a length of 100 @@ -1039,7 +1041,8 @@ typedef struct Project *EN_Project; See @ref EN_LinkProperty. */ - int DLLEXPORT EN_addlink(EN_Project ph, char *id, int linkType, char *fromNode, char *toNode); + int DLLEXPORT EN_addlink(EN_Project ph, char *id, int linkType, char *fromNode, + char *toNode, int *index); /** @brief Deletes a link from the project. diff --git a/include/epanet_py.h b/include/epanet_py.h index a559d6e..0104d95 100644 --- a/include/epanet_py.h +++ b/include/epanet_py.h @@ -81,7 +81,7 @@ int EXPORT_PY_API anlys_getqualtype(Handle ph, int *qualcode, int *tracenode); int EXPORT_PY_API anlys_setqualtype(Handle ph, EN_QualityType qualcode, char *chemname, char *chemunits, char *tracenode); -int EXPORT_PY_API node_add(Handle ph, char *id, EN_NodeType nodeType); +int EXPORT_PY_API node_add(Handle ph, char *id, EN_NodeType nodeType, int *index); int EXPORT_PY_API node_delete(Handle ph, int index, int actionCode); int EXPORT_PY_API node_getindex(Handle ph, char *id, int *index); int EXPORT_PY_API node_getid(Handle ph, int index, char *id); @@ -104,7 +104,7 @@ int EXPORT_PY_API dmnd_getname(Handle ph, int nodeIndex, int demandIdx, char *de int EXPORT_PY_API dmnd_setname(Handle ph, int nodeIndex, int demandIdx, char *demandName); -int EXPORT_PY_API link_add(Handle ph, char *id, EN_LinkType linkType, char *fromNode, char *toNode); +int EXPORT_PY_API link_add(Handle ph, char *id, EN_LinkType linkType, char *fromNode, char *toNode, int *index); int EXPORT_PY_API link_delete(Handle ph, int index, int actionCode); int EXPORT_PY_API link_getindex(Handle ph, char *id, int *index); int EXPORT_PY_API link_getid(Handle ph, int index, char *id); diff --git a/src/epanet.c b/src/epanet.c index 6a9c546..f6c7065 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 04/03/2019 + Last Updated: 04/18/2019 ****************************************************************************** */ @@ -30,8 +30,6 @@ #include "text.h" #include "enumstxt.h" -#include "util/cstr_helper.h" - #ifdef _WIN32 #define snprintf _snprintf #endif @@ -1707,11 +1705,11 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName, ********************************************************************/ -int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) +int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType, int *index) /*---------------------------------------------------------------- ** Input: id = node ID name ** nodeType = type of node (see EN_NodeType) -** Output: none +** Output: index = index of newly added node ** Returns: error code ** Purpose: adds a new node to a project **---------------------------------------------------------------- @@ -1721,27 +1719,23 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) Hydraul *hyd = &p->hydraul; Quality *qual = &p->quality; - int i, nIdx; - int index; - int size; + int i, nIdx, size; struct Sdemand *demand; Stank *tank; Snode *node; Scontrol *control; // Cannot modify network structure while solvers are active + *index = 0; if (!p->Openflag) return 102; if (hyd->OpenHflag || qual->OpenQflag) return 262; - // Check if id contains invalid characters - if (!cstr_isvalid(id)) return 252; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; // Check if a node with same id already exists if (EN_getnodeindex(p, id, &i) == 0) return 215; - // Check that id name is not too long - if (strlen(id) > MAXID) return 250; - // Grow node-related arrays to accomodate the new node size = (net->Nnodes + 2) * sizeof(Snode); net->Node = (Snode *)realloc(net->Node, size); @@ -1765,28 +1759,28 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) node->D = demand; // shift rest of Node array - for (index = net->Nnodes; index >= net->Njuncs; index--) + for (i = net->Nnodes; i >= net->Njuncs; i--) { - hashtable_update(net->NodeHashTable, net->Node[index].ID, index + 1); - net->Node[index + 1] = net->Node[index]; + hashtable_update(net->NodeHashTable, net->Node[i].ID, i + 1); + net->Node[i + 1] = net->Node[i]; } // shift indices of Tank array - for (index = 1; index <= net->Ntanks; index++) + for (i = 1; i <= net->Ntanks; i++) { - net->Tank[index].Node += 1; + net->Tank[i].Node += 1; } // shift indices of Links, if necessary - for (index = 1; index <= net->Nlinks; index++) + for (i = 1; i <= net->Nlinks; i++) { - if (net->Link[index].N1 > net->Njuncs - 1) net->Link[index].N1 += 1; - if (net->Link[index].N2 > net->Njuncs - 1) net->Link[index].N2 += 1; + if (net->Link[i].N1 > net->Njuncs - 1) net->Link[i].N1 += 1; + if (net->Link[i].N2 > net->Njuncs - 1) net->Link[i].N2 += 1; } // shift indices of tanks/reservoir nodes in controls - for (index = 1; index <= net->Ncontrols; ++index) + for (i = 1; i <= net->Ncontrols; ++i) { - control = &net->Control[index]; + control = &net->Control[i]; if (control->Node > net->Njuncs - 1) control->Node += 1; } @@ -1841,6 +1835,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) // Insert new node into hash table hashtable_insert(net->NodeHashTable, node->ID, nIdx); + *index = nIdx; return 0; } @@ -2015,13 +2010,10 @@ int DLLEXPORT EN_setnodeid(EN_Project p, int index, char *newid) */ { Network *net = &p->network; - size_t n; // Check for valid arguments if (index <= 0 || index > net->Nnodes) return 203; - n = strlen(newid); - if (n < 1 || n > MAXID) return 209; - if (!cstr_isvalid(newid)) return 252; + if (!namevalid(newid)) return 252; // Check if another node with same name exists if (hashtable_find(net->NodeHashTable, newid) > 0) return 215; @@ -2844,8 +2836,8 @@ int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex, if (!p->Openflag) return 102; if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203; - // Check that demandName is not too long - if (strlen(demandName) > MAXID) return 250; + // Check that demandName is not too long + if (strlen(demandName) > MAXID) return 252; // Locate demand category record and assign demandName to it for (d = p->network.Node[nodeIndex].D; @@ -2920,13 +2912,13 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex, ********************************************************************/ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType, - char *fromNode, char *toNode) + char *fromNode, char *toNode, int *index) /*---------------------------------------------------------------- ** Input: id = link ID name ** type = link type (see EN_LinkType) ** fromNode = name of link's starting node ** toNode = name of link's ending node -** Output: none +** Output: index = position of new link in Link array ** Returns: error code ** Purpose: adds a new link to a project **---------------------------------------------------------------- @@ -2941,11 +2933,12 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType, Spump *pump; // Cannot modify network structure while solvers are active + *index = 0; if (!p->Openflag) return 102; if (p->hydraul.OpenHflag || p->quality.OpenQflag) return 262; - // Check if id contains invalid characters - if (!cstr_isvalid(id)) return 252; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; // Check if a link with same id already exists if (EN_getlinkindex(p, id, &i) == 0) return 215; @@ -2958,9 +2951,6 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType, n2 = hashtable_find(net->NodeHashTable, toNode); if (n1 == 0 || n2 == 0) return 203; - // Check that id name is not too long - if (strlen(id) > MAXID) return 250; - // Check that valve link has legal connections if (linkType > PUMP) { @@ -2970,6 +2960,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType, // Grow link-related arrays to accomodate the new link net->Nlinks++; + p->parser.MaxLinks = net->Nlinks; n = net->Nlinks; size = (n + 1) * sizeof(Slink); net->Link = (Slink *)realloc(net->Link, size); @@ -3049,6 +3040,7 @@ int DLLEXPORT EN_addlink(EN_Project p, char *id, int linkType, link->Comment = NULL; hashtable_insert(net->LinkHashTable, link->ID, n); + *index = n; return 0; } @@ -3202,13 +3194,10 @@ int DLLEXPORT EN_setlinkid(EN_Project p, int index, char *newid) */ { Network *net = &p->network; - size_t n; // Check for valid arguments if (index <= 0 || index > net->Nlinks) return 204; - n = strlen(newid); - if (n < 1 || n > MAXID) return 211; - if (!cstr_isvalid(newid)) return 252; + if (!namevalid(newid)) return 252; // Check if another link with same name exists if (hashtable_find(net->LinkHashTable, newid) > 0) return 215; @@ -3306,10 +3295,7 @@ int DLLEXPORT EN_setlinktype(EN_Project p, int *index, int linkType, int actionC EN_deletelink(p, i, actionCode); // Create a new link of new type and old id - errcode = EN_addlink(p, id, linkType, id1, id2); - - // Find the index of this new link - EN_getlinkindex(p, id, index); + errcode = EN_addlink(p, id, linkType, id1, id2, index); return errcode; } @@ -3959,11 +3945,8 @@ int DLLEXPORT EN_addpattern(EN_Project p, char *id) if (!p->Openflag) return 102; if (EN_getpatternindex(p, id, &i) == 0) return 215; - // Check is id name contains invalid characters - if (!cstr_isvalid(id)) return 252; - - // Check that id name is not too long - if (strlen(id) > MAXID) return 250; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; // Expand the project's array of patterns n = net->Npats + 1; @@ -4086,10 +4069,8 @@ int DLLEXPORT EN_setpatternid(EN_Project p, int index, char *id) if (!p->Openflag) return 102; if (index < 1 || index > p->network.Npats) return 205; - // Check is id name contains invalid characters - if (!cstr_isvalid(id)) return 252; - - if (strlen(id) > MAXID) return 250; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; for (i = 1; i <= p->network.Npats; i++) { @@ -4235,11 +4216,8 @@ int DLLEXPORT EN_addcurve(EN_Project p, char *id) if (!p->Openflag) return 102; if (EN_getcurveindex(p, id, &i) == 0) return 215; - // Check is id name contains invalid characters - if (!cstr_isvalid(id)) return 252; - - // Check that id name is not too long - if (strlen(id) > MAXID) return 250; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; // Expand the array of curves n = net->Ncurves + 1; @@ -4358,10 +4336,9 @@ int DLLEXPORT EN_setcurveid(EN_Project p, int index, char *id) if (!p->Openflag) return 102; if (index < 1 || index > p->network.Ncurves) return 205; - // Check is id name contains invalid characters - if (!cstr_isvalid(id)) return 252; - - if (strlen(id) > MAXID) return 250; + // Check if id name contains invalid characters + if (!namevalid(id)) return 252; + for (i = 1; i <= p->network.Ncurves; i++) { if (i != index && strcmp(id, p->network.Curve[i].ID) == 0) return 215; diff --git a/src/epanet2.c b/src/epanet2.c index 2490c64..928e30c 100644 --- a/src/epanet2.c +++ b/src/epanet2.c @@ -294,9 +294,9 @@ int DLLEXPORT ENsetqualtype(int qualType, char *chemName, char *chemUnits, ********************************************************************/ -int DLLEXPORT ENaddnode(char *id, int nodeType) +int DLLEXPORT ENaddnode(char *id, int nodeType, int *index) { - return EN_addnode(_defaultProject, id, nodeType); + return EN_addnode(_defaultProject, id, nodeType, index); } int DLLEXPORT ENdeletenode(int index, int actionCode) @@ -431,9 +431,9 @@ int DLLEXPORT ENsetdemandname(int nodeIndex, int demandIndex, char *demandName) ********************************************************************/ -int DLLEXPORT ENaddlink(char *id, int linkType, char *fromNode, char *toNode) +int DLLEXPORT ENaddlink(char *id, int linkType, char *fromNode, char *toNode, int *index) { - return EN_addlink(_defaultProject, id, linkType, fromNode, toNode); + return EN_addlink(_defaultProject, id, linkType, fromNode, toNode, index); } int DLLEXPORT ENdeletelink(int index, int actionCode) diff --git a/src/epanet_py.c b/src/epanet_py.c index 6cc3302..9f663d1 100644 --- a/src/epanet_py.c +++ b/src/epanet_py.c @@ -326,10 +326,10 @@ int EXPORT_PY_API anlys_setqualtype(Handle ph, EN_QualityType qualcode, char *ch -int EXPORT_PY_API node_add(Handle ph, char *id, EN_NodeType nodeType) +int EXPORT_PY_API node_add(Handle ph, char *id, EN_NodeType nodeType, int *index) { handle_t *pr = (handle_t *)ph; - return set_error(pr->error, EN_addnode(pr->project, id, nodeType)); + return set_error(pr->error, EN_addnode(pr->project, id, nodeType, index)); } int EXPORT_PY_API node_delete(Handle ph, int index, int actionCode) @@ -446,10 +446,10 @@ int EXPORT_PY_API dmnd_setname(Handle ph, int nodeIndex, int demandIdx, char *de -int EXPORT_PY_API link_add(Handle ph, char *id, EN_LinkType linkType, char *fromNode, char *toNode) +int EXPORT_PY_API link_add(Handle ph, char *id, EN_LinkType linkType, char *fromNode, char *toNode, int *index) { handle_t *pr = (handle_t *)ph; - return set_error(pr->error, EN_addlink(pr->project, id, linkType, fromNode, toNode)); + return set_error(pr->error, EN_addlink(pr->project, id, linkType, fromNode, toNode, index)); } int EXPORT_PY_API link_delete(Handle ph, int index, int actionCode) diff --git a/src/funcs.h b/src/funcs.h index ac17b55..529cb12 100755 --- a/src/funcs.h +++ b/src/funcs.h @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 04/03/2019 + Last Updated: 04/18/2019 ****************************************************************************** */ #ifndef FUNCS_H @@ -44,6 +44,7 @@ int resizecurve(Scurve *, int); int getcomment(Network *, int, int, char *); int setcomment(Network *, int, int, const char *); +int namevalid(const char *); char *getTmpName(char *); char *xstrcpy(char **, const char *, const size_t n); int strcomp(const char *, const char *); diff --git a/src/project.c b/src/project.c index f340e8a..f24ca25 100644 --- a/src/project.c +++ b/src/project.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 04/03/2019 + Last Updated: 04/18/2019 ****************************************************************************** */ @@ -988,6 +988,18 @@ int setcomment(Network *network, int object, int index, const char *newcomment) } } +int namevalid(const char *name) +//---------------------------------------------------------------- +// Input: name = name used to ID an object +// Output: returns TRUE if name is valid, FALSE if not +// Purpose: checks that an object's ID name is valid. +//---------------------------------------------------------------- +{ + size_t n = strlen(name); + if (n < 1 || n > MAXID || strpbrk(name, " \";")) return FALSE; + return TRUE; +} + char *getTmpName(char *fname) //---------------------------------------------------------------- // Input: fname = file name string diff --git a/tests/test_link.cpp b/tests/test_link.cpp index 2a24512..a352417 100644 --- a/tests/test_link.cpp +++ b/tests/test_link.cpp @@ -26,14 +26,14 @@ BOOST_FIXTURE_TEST_CASE(test_adddelete_link, FixtureInitClose) int index; // Build a network - EN_addnode(ph, (char *)"N1", EN_JUNCTION); - EN_addnode(ph, (char *)"N2", EN_JUNCTION); - EN_addnode(ph, (char *)"N3", EN_RESERVOIR); + EN_addnode(ph, (char *)"N1", EN_JUNCTION, &index); + EN_addnode(ph, (char *)"N2", EN_JUNCTION, &index); + EN_addnode(ph, (char *)"N3", EN_RESERVOIR, &index); - error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1"); + error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1", &index); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3"); + error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3", &index); BOOST_REQUIRE(error == 0); error = EN_getlinkindex(ph, (char *)"L2", &index); @@ -41,7 +41,7 @@ BOOST_FIXTURE_TEST_CASE(test_adddelete_link, FixtureInitClose) error = EN_deletelink(ph, index, EN_UNCONDITIONAL); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 0); error = EN_getlinkindex(ph, (char *)"L1", &index); @@ -60,20 +60,20 @@ BOOST_FIXTURE_TEST_CASE(test_link_id_isvalid, FixtureInitClose) int index; // Build a network - EN_addnode(ph, (char *)"N1", EN_JUNCTION); - EN_addnode(ph, (char *)"N2", EN_JUNCTION); - EN_addnode(ph, (char *)"N3", EN_RESERVOIR); + EN_addnode(ph, (char *)"N1", EN_JUNCTION, &index); + EN_addnode(ph, (char *)"N2", EN_JUNCTION, &index); + EN_addnode(ph, (char *)"N3", EN_RESERVOIR, &index); - error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L 2", EN_PIPE, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L 2", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 252); - error = EN_addlink(ph, (char *)"L\"2", EN_PIPE, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L\"2", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 252); - error = EN_addlink(ph, (char *)"L;2", EN_PIPE, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L;2", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 252); EN_getlinkindex(ph, (char *)"L1", &index); diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index c4dafc4..698d4c3 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -128,7 +128,7 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) //BOOST_REQUIRE(error == 0); for (i = 0; i < 9; i++) { - error = EN_addnode(ph, juncs[i], EN_JUNCTION); + error = EN_addnode(ph, juncs[i], EN_JUNCTION, &ind); BOOST_REQUIRE(error == 0); error = EN_setnodevalue(ph, i + 1, EN_ELEVATION, e[i]); BOOST_REQUIRE(error == 0); @@ -141,14 +141,14 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) //error = EN_setdemandpattern(ph, i + 1, 1, 1); //BOOST_REQUIRE(error == 0); } - error = EN_addnode(ph, (char *)"9", EN_RESERVOIR); + error = EN_addnode(ph, (char *)"9", EN_RESERVOIR, &ind); BOOST_REQUIRE(error == 0); error = EN_setcoord(ph, 10, 10, 70); BOOST_REQUIRE(error == 0); error = EN_setnodevalue(ph, 10, EN_ELEVATION, 800); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"2", EN_TANK); + error = EN_addnode(ph, (char *)"2", EN_TANK, &ind); BOOST_REQUIRE(error == 0); error = EN_setcoord(ph, 11, 50, 90); BOOST_REQUIRE(error == 0); @@ -165,29 +165,29 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) error = EN_setnodevalue(ph, 11, EN_MIXFRACTION, 1); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"10", EN_PIPE, (char *)"10", (char *)"11"); + error = EN_addlink(ph, (char *)"10", EN_PIPE, (char *)"10", (char *)"11", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"11", EN_PIPE, (char *)"11", (char *)"12"); + error = EN_addlink(ph, (char *)"11", EN_PIPE, (char *)"11", (char *)"12", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"12", EN_PIPE, (char *)"12", (char *)"13"); + error = EN_addlink(ph, (char *)"12", EN_PIPE, (char *)"12", (char *)"13", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"21", EN_PIPE, (char *)"21", (char *)"22"); + error = EN_addlink(ph, (char *)"21", EN_PIPE, (char *)"21", (char *)"22", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"22", EN_PIPE, (char *)"22", (char *)"23"); + error = EN_addlink(ph, (char *)"22", EN_PIPE, (char *)"22", (char *)"23", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"31", EN_PIPE, (char *)"31", (char *)"32"); + error = EN_addlink(ph, (char *)"31", EN_PIPE, (char *)"31", (char *)"32", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"110", EN_PIPE, (char *)"2", (char *)"12"); + error = EN_addlink(ph, (char *)"110", EN_PIPE, (char *)"2", (char *)"12", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"111", EN_PIPE, (char *)"11", (char *)"21"); + error = EN_addlink(ph, (char *)"111", EN_PIPE, (char *)"11", (char *)"21", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"112", EN_PIPE, (char *)"12", (char *)"22"); + error = EN_addlink(ph, (char *)"112", EN_PIPE, (char *)"12", (char *)"22", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"113", EN_PIPE, (char *)"13", (char *)"23"); + error = EN_addlink(ph, (char *)"113", EN_PIPE, (char *)"13", (char *)"23", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"121", EN_PIPE, (char *)"21", (char *)"31"); + error = EN_addlink(ph, (char *)"121", EN_PIPE, (char *)"21", (char *)"31", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"122", EN_PIPE, (char *)"22", (char *)"32"); + error = EN_addlink(ph, (char *)"122", EN_PIPE, (char *)"22", (char *)"32", &ind); BOOST_REQUIRE(error == 0); for (i = 0; i < 12; i++) { @@ -197,7 +197,7 @@ BOOST_FIXTURE_TEST_CASE(test_build_net1, FixtureInitClose) BOOST_REQUIRE(error == 0); } - error = EN_addlink(ph, (char *)"9", EN_PUMP, (char *)"9", (char *)"10"); + error = EN_addlink(ph, (char *)"9", EN_PUMP, (char *)"9", (char *)"10", &ind); BOOST_REQUIRE(error == 0); error = EN_addcurve(ph, (char *)"1"); BOOST_REQUIRE(error == 0); @@ -306,19 +306,19 @@ BOOST_FIXTURE_TEST_CASE(test_save_net2, FixtureInitClose) double q1_1, q2_1; // q1_2, q2_2; // Build a network - error = EN_addnode(ph, (char *)"N1", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N1", EN_JUNCTION, &ind); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N2", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N2", EN_JUNCTION, &ind); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR); + error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR, &ind); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N4", EN_TANK); + error = EN_addnode(ph, (char *)"N4", EN_TANK, &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1"); + error = EN_addlink(ph, (char *)"L1", EN_PUMP, (char *)"N3", (char *)"N1", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3"); + error = EN_addlink(ph, (char *)"L2", EN_PIPE, (char *)"N1", (char *)"N3", &ind); BOOST_REQUIRE(error == 0); - error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2"); + error = EN_addlink(ph, (char *)"L3", EN_PIPE, (char *)"N1", (char *)"N2", &ind); BOOST_REQUIRE(error == 0); error = EN_addcurve(ph, (char *)"C1"); BOOST_REQUIRE(error == 0); diff --git a/win_build/WinSDK/epanet2.def b/win_build/WinSDK/epanet2.def index f9374ef..ebd08f9 100644 --- a/win_build/WinSDK/epanet2.def +++ b/win_build/WinSDK/epanet2.def @@ -3,8 +3,8 @@ LIBRARY EPANET2.DLL EXPORTS ENaddcontrol = _ENaddcontrol@24 ENaddcurve = _ENaddcurve@4 - ENaddlink = _ENaddlink@16 - ENaddnode = _ENaddnode@8 + ENaddlink = _ENaddlink@20 + ENaddnode = _ENaddnode@12 ENaddpattern = _ENaddpattern@4 ENaddrule = _ENaddrule@4 ENclearreport = _ENclearreport@0 From cc22eefeaea6a222927f8e38e834c3931dbf20b8 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Thu, 18 Apr 2019 07:11:17 -0400 Subject: [PATCH 2/4] Fixed compilation errors --- src/report.c | 2 +- tests/test_net_builder.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/report.c b/src/report.c index c35d73f..0e7336d 100644 --- a/src/report.c +++ b/src/report.c @@ -237,7 +237,7 @@ void writesummary(Project *pr) Parser *parser = &pr->parser; Times *time = &pr->times; - char s[MAXFNAME + 1]; + char s[MAXLINE + 1]; int i; int nres = 0; diff --git a/tests/test_net_builder.cpp b/tests/test_net_builder.cpp index 698d4c3..5163ea3 100644 --- a/tests/test_net_builder.cpp +++ b/tests/test_net_builder.cpp @@ -304,6 +304,7 @@ BOOST_FIXTURE_TEST_CASE(test_save_net2, FixtureInitClose) //char id[EN_MAXID+1]; double p1_1, p2_1; // p1_2, p2_2; double q1_1, q2_1; // q1_2, q2_2; + int ind; // Build a network error = EN_addnode(ph, (char *)"N1", EN_JUNCTION, &ind); From 6b0e421a39c137f59a774ea1d20917567c6f3bab Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Thu, 18 Apr 2019 07:39:39 -0400 Subject: [PATCH 3/4] Update test_node.cpp --- tests/test_node.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_node.cpp b/tests/test_node.cpp index e7139ae..4912c87 100644 --- a/tests/test_node.cpp +++ b/tests/test_node.cpp @@ -23,9 +23,9 @@ BOOST_FIXTURE_TEST_CASE(test_adddelete_node, FixtureInitClose) { int index; - error = EN_addnode(ph, (char *)"N2", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N2", EN_JUNCTION, &index); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR); + error = EN_addnode(ph, (char *)"N3", EN_RESERVOIR, &index); BOOST_REQUIRE(error == 0); error = EN_getnodeindex(ph, (char *)"N2", &index); @@ -33,7 +33,7 @@ BOOST_FIXTURE_TEST_CASE(test_adddelete_node, FixtureInitClose) error = EN_deletenode(ph, index, EN_UNCONDITIONAL); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N4", EN_TANK); + error = EN_addnode(ph, (char *)"N4", EN_TANK, &index); BOOST_REQUIRE(error == 0); error = EN_getnodeindex(ph, (char *)"N4", &index); @@ -51,16 +51,16 @@ BOOST_FIXTURE_TEST_CASE(test_node_validate_id, FixtureInitClose) { int index; - error = EN_addnode(ph, (char *)"N2", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N2", EN_JUNCTION, &index); BOOST_REQUIRE(error == 0); - error = EN_addnode(ph, (char *)"N 3", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N 3", EN_JUNCTION, &index); BOOST_REQUIRE(error == 252); - error = EN_addnode(ph, (char *)"N\"3", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N\"3", EN_JUNCTION, &index); BOOST_REQUIRE(error == 252); - error = EN_addnode(ph, (char *)"N;3", EN_JUNCTION); + error = EN_addnode(ph, (char *)"N;3", EN_JUNCTION, &index); BOOST_REQUIRE(error == 252); EN_getnodeindex(ph, (char *)"N2", &index); From a4ac34d5d63e156345dea1905adde85981201a9e Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Thu, 18 Apr 2019 17:12:56 -0400 Subject: [PATCH 4/4] Updated criteria for valid object ID name --- src/project.c | 2 +- tests/test_curve.cpp | 2 +- tests/test_link.cpp | 2 +- tests/test_node.cpp | 2 +- tests/test_pattern.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/project.c b/src/project.c index f24ca25..faa3eaf 100644 --- a/src/project.c +++ b/src/project.c @@ -996,7 +996,7 @@ int namevalid(const char *name) //---------------------------------------------------------------- { size_t n = strlen(name); - if (n < 1 || n > MAXID || strpbrk(name, " \";")) return FALSE; + if (n < 1 || n > MAXID || strpbrk(name, " ;") || name[0] == '"') return FALSE; return TRUE; } diff --git a/tests/test_curve.cpp b/tests/test_curve.cpp index 6e80cd5..6712cdf 100644 --- a/tests/test_curve.cpp +++ b/tests/test_curve.cpp @@ -77,7 +77,7 @@ BOOST_FIXTURE_TEST_CASE(test_curve_id_isvalid, FixtureInitClose) error = EN_addcurve(ph, (char *)"C 2"); BOOST_REQUIRE(error == 252); - error = EN_addcurve(ph, (char *)"C\"2"); + error = EN_addcurve(ph, (char *)"\"C2"); BOOST_REQUIRE(error == 252); error = EN_addcurve(ph, (char *)"C;2"); diff --git a/tests/test_link.cpp b/tests/test_link.cpp index a352417..b853a08 100644 --- a/tests/test_link.cpp +++ b/tests/test_link.cpp @@ -70,7 +70,7 @@ BOOST_FIXTURE_TEST_CASE(test_link_id_isvalid, FixtureInitClose) error = EN_addlink(ph, (char *)"L 2", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 252); - error = EN_addlink(ph, (char *)"L\"2", EN_PIPE, (char *)"N1", (char *)"N2", &index); + error = EN_addlink(ph, (char *)"\"L2", EN_PIPE, (char *)"N1", (char *)"N2", &index); BOOST_REQUIRE(error == 252); error = EN_addlink(ph, (char *)"L;2", EN_PIPE, (char *)"N1", (char *)"N2", &index); diff --git a/tests/test_node.cpp b/tests/test_node.cpp index 4912c87..d0f0cdb 100644 --- a/tests/test_node.cpp +++ b/tests/test_node.cpp @@ -57,7 +57,7 @@ BOOST_FIXTURE_TEST_CASE(test_node_validate_id, FixtureInitClose) error = EN_addnode(ph, (char *)"N 3", EN_JUNCTION, &index); BOOST_REQUIRE(error == 252); - error = EN_addnode(ph, (char *)"N\"3", EN_JUNCTION, &index); + error = EN_addnode(ph, (char *)"\"N3", EN_JUNCTION, &index); BOOST_REQUIRE(error == 252); error = EN_addnode(ph, (char *)"N;3", EN_JUNCTION, &index); diff --git a/tests/test_pattern.cpp b/tests/test_pattern.cpp index ef2eb71..13d0510 100644 --- a/tests/test_pattern.cpp +++ b/tests/test_pattern.cpp @@ -157,7 +157,7 @@ BOOST_FIXTURE_TEST_CASE(test_pat_id_isvalid, FixtureInitClose) error = EN_addpattern(ph, (char *)"P 2"); BOOST_REQUIRE(error == 252); - error = EN_addpattern(ph, (char *)"P\"2"); + error = EN_addpattern(ph, (char *)"\"P2"); BOOST_REQUIRE(error == 252); error = EN_addpattern(ph, (char *)"P;2");