From 109276e379d5d26ccc1db4511df9ca818f45f635 Mon Sep 17 00:00:00 2001 From: Michael Tryby Date: Wed, 17 Apr 2019 17:24:34 -0400 Subject: [PATCH] Work in progress Implementing generic demand pattern lists. Compiles but does not run. --- src/demand.c | 30 ++++-- src/demand.h | 16 +-- src/epanet.c | 222 ++++++++++++++++++++++++--------------- src/hydraul.c | 13 ++- src/inpfile.c | 28 +++-- src/project.c | 37 +++++-- src/util/list.c | 65 ++++++------ src/util/list.h | 27 ++++- tests/util/test_list.cpp | 11 +- 9 files changed, 277 insertions(+), 172 deletions(-) diff --git a/src/demand.c b/src/demand.c index 5cba1d9..4215a05 100644 --- a/src/demand.c +++ b/src/demand.c @@ -3,7 +3,7 @@ Project: OWA EPANET Version: 2.2 Module: demand.c - Description: demand pattern list + Description: data for demand pattern list Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE @@ -25,12 +25,12 @@ typedef struct demand_data_s } demand_data_t; -demand_data_t *create_demand_data(double base_demand, int pat_index, char *cat_name) +demand_data_t *create_demand_data(double base_demand, int pattern_index, char *category_name) { demand_data_t *demand_data = (demand_data_t *)malloc(sizeof(demand_data_t)); demand_data->base_demand = base_demand; - demand_data->pattern_index = pat_index; + demand_data->pattern_index = pattern_index; if (cat_name) demand_data->category_name = strdup(cat_name); @@ -72,20 +72,30 @@ bool convert_units(list_node_t *lnode, double unit_conversion) double get_base_demand(demand_data_t *data) { - return data->base_demand; + return get_demand_data(lnode)->base_demand; } -void set_base_demand(demand_data_t *data, double base_demand) +void set_base_demand(list_node_t *lnode, double base_demand) { - data->base_demand = base_demand; + get_demand_data(lnode)->base_demand = base_demand; } -int get_pattern_index(demand_data_t *data) +int get_pattern_index(list_node_t *lnode) { - return data->pattern_index; + return get_demand_data(lnode)->pattern_index; } -char *get_category_name(demand_data_t *data) +void set_pattern_index(list_node_t *lnode, int pattern_index) { - return data->category_name; + get_demand_data(lnode)->pattern_index = pattern_index; +} + +char *get_category_name(list_node_t *lnode) +{ + return get_demand_data(lnode)->category_name; +} + +void set_category_name(list_node_t *lnode, char *category_name) +{ + get_demand_data(lnode)->category_name = strdup(category_name); } diff --git a/src/demand.h b/src/demand.h index bdfd8a2..775ed4a 100644 --- a/src/demand.h +++ b/src/demand.h @@ -3,7 +3,7 @@ Project: OWA EPANET Version: 2.2 Module: demand.h - Description: demand pattern list + Description: data for demand pattern list Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE @@ -30,19 +30,21 @@ void delete_demand_data(void *data); size_t get_demand_data_size(void); -demand_data_t *get_demand_data(list_node_t *lnode); - bool convert_units(list_node_t *lnode, double unit_conversion); -double get_base_demand(demand_data_t *data); +double get_base_demand(list_node_t *lnode); +void set_base_demand(list_node_t *lnode, double base_demand); -void set_base_demand(demand_data_t *data, double base_demand); +int get_pattern_index(list_node_t *lnode); +void set_pattern_index(list_node_t *lnode, int pattern_index); -int get_pattern_index(demand_data_t *data); +char *get_category_name(list_node_t *lnode); +void set_category_name(list_node_t *lnode, char *category_name); -char *get_category_name(demand_data_t *data); +// Make this private? +demand_data_t *get_demand_data(list_node_t *lnode); #endif /* DEMAND_H */ diff --git a/src/epanet.c b/src/epanet.c index 6a9c546..4d06e4b 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -31,6 +31,7 @@ #include "enumstxt.h" #include "util/cstr_helper.h" +#include "demand.h" #ifdef _WIN32 #define snprintf _snprintf @@ -1724,7 +1725,7 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) int i, nIdx; int index; int size; - struct Sdemand *demand; +// struct Sdemand *demand; Stank *tank; Snode *node; Scontrol *control; @@ -1757,12 +1758,12 @@ int DLLEXPORT EN_addnode(EN_Project p, char *id, int nodeType) nIdx = net->Njuncs; node = &net->Node[nIdx]; - demand = (struct Sdemand *)malloc(sizeof(struct Sdemand)); - demand->Base = 0.0; - demand->Pat = 0; - demand->Name = NULL; - demand->next = NULL; - node->D = demand; + //demand = (struct Sdemand *)malloc(sizeof(struct Sdemand)); + //demand->Base = 0.0; + //demand->Pat = 0; + //demand->Name = NULL; + //demand->next = NULL; + node->D = NULL; // shift rest of Node array for (index = net->Nnodes; index >= net->Njuncs; index--) @@ -1862,7 +1863,7 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode) int i, nodeType, tankindex; Snode *node; - Pdemand demand, nextdemand; + list_t *demand; // Cannot modify network structure while solvers are active if (!p->Openflag) return 102; @@ -1896,13 +1897,14 @@ int DLLEXPORT EN_deletenode(EN_Project p, int index, int actionCode) // Free memory allocated to node's demands, WQ source & comment demand = node->D; - while (demand != NULL) - { - nextdemand = demand->next; - free(demand->Name); - free(demand); - demand = nextdemand; - } + delete_list(demand); +// while (demand != NULL) + // { + // nextdemand = demand->next; + // free(demand->Name); + // free(demand); + // demand = nextdemand; + // } free(node->S); free(node->Comment); @@ -2072,7 +2074,7 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val Quality *qual = &p->quality; double v = 0.0; - Pdemand demand; + //Pdemand demand; Psource source; Snode *Node = net->Node; @@ -2102,10 +2104,14 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val // NOTE: primary demand category is last on demand list if (index <= nJuncs) { - for (demand = Node[index].D; demand != NULL; demand = demand->next) - { - v = (demand->Base); - } + list_t *demand = Node[index].D; + if (demand) + v = get_base_demand(tail_list(demand)); + + //for (demand = Node[index].D; demand != NULL; demand = demand->next) + //{ + // v = (demand->Base); + //} } v *= Ucf[FLOW]; break; @@ -2115,10 +2121,13 @@ int DLLEXPORT EN_getnodevalue(EN_Project p, int index, int property, double *val // NOTE: primary demand category is last on demand list if (index <= nJuncs) { - for (demand = Node[index].D; demand != NULL; demand = demand->next) - { - v = (double)(demand->Pat); - } + list_t *demand = Node[index].D; + if (demand) + v = get_pattern_index(tail_list(demand)); + //for (demand = Node[index].D; demand != NULL; demand = demand->next) + //{ + // v = (double)(demand->Pat); + //} } else v = (double)(Tank[index - nJuncs].Pat); break; @@ -2273,7 +2282,7 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu double *Ucf = p->Ucf; int i, j, n; - Pdemand demand; +// Pdemand demand; Psource source; double hTmp; @@ -2299,10 +2308,13 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu // NOTE: primary demand category is last on demand list if (index <= nJuncs) { - for (demand = Node[index].D; demand != NULL; demand = demand->next) - { - if (demand->next == NULL) demand->Base = value / Ucf[FLOW]; - } + list_t *demand = Node[index].D; + if (demand) + set_base_demand(tail_list(demand), value / Ucf[FLOW]); +// for (demand = Node[index].D; demand != NULL; demand = demand->next) +// { +// if (demand->next == NULL) demand->Base = value / Ucf[FLOW]; +// } } break; @@ -2312,10 +2324,13 @@ int DLLEXPORT EN_setnodevalue(EN_Project p, int index, int property, double valu if (j < 0 || j > nPats) return 205; if (index <= nJuncs) { - for (demand = Node[index].D; demand != NULL; demand = demand->next) - { - if (demand->next == NULL) demand->Pat = j; - } + list_t *demand = Node[index].D; + if (demand) + set_pattern_index(tail_list(demand), j); + //for (demand = Node[index].D; demand != NULL; demand = demand->next) + //{ + // if (demand->next == NULL) demand->Pat = j; + //} } else Tank[index - nJuncs].Pat = j; break; @@ -2512,7 +2527,7 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev, int i, patIndex = 0; Snode *Node = net->Node; - Pdemand demand; + //Pdemand demand; // Check that junction exists if (!p->Openflag) return 102; @@ -2534,14 +2549,25 @@ int DLLEXPORT EN_setjuncdata(EN_Project p, int index, double elev, // Assign values to junction's parameters Node[index].El = elev / p->Ucf[ELEV]; - for (demand = Node[index].D; demand != NULL; demand = demand->next) - { - if (demand->next == NULL) - { - demand->Base = dmnd / p->Ucf[FLOW]; - demand->Pat = patIndex; - } - } + + list_t *demand_list = Node[index].D; + if (!demand_list) { + demand_list = create_list(get_demand_data_size(), delete_demand_data); + if (!demand_list) return 101; + } + demand_data_t *demand_data = create_demand_data(dmnd / p->Ucf[FLOW], patIndex, NULL); + if (!demand_data) return 101; + + append_list(demand_list, &demand_data); + + //for (demand = Node[index].D; demand != NULL; demand = demand->next) + //{ + // if (demand->next == NULL) + // { + // demand->Base = dmnd / p->Ucf[FLOW]; + // demand->Pat = patIndex; + // } + //} return 0; } @@ -2722,16 +2748,20 @@ int DLLEXPORT EN_getnumdemands(EN_Project p, int nodeIndex, int *numDemands) **---------------------------------------------------------------- */ { - Pdemand d; - int n = 0; + //Pdemand d; + //int n = 0; // Check for valid arguments if (!p->Openflag) return 102; if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203; // Count the number of demand categories - for (d = p->network.Node[nodeIndex].D; d != NULL; d = d->next) n++; - *numDemands = n; + list_t *demand_list = p->network.Node[nodeIndex].D; + if (!demand_list) + *numDemands = 0; + else + *numDemands = size_list(demand_list); + return 0; } @@ -2746,8 +2776,8 @@ int DLLEXPORT EN_getbasedemand(EN_Project p, int nodeIndex, int demandIndex, **---------------------------------------------------------------- */ { - Pdemand d; - int n = 1; + //Pdemand d; + //int n; //= 1; // Check for valid arguments if (!p->Openflag) return 102; @@ -2756,10 +2786,13 @@ int DLLEXPORT EN_getbasedemand(EN_Project p, int nodeIndex, int demandIndex, // Retrieve demand for specified category if (nodeIndex <= p->network.Njuncs) { - for (d = p->network.Node[nodeIndex].D; n < demandIndex && d->next != NULL; - d = d->next) n++; - if (n != demandIndex) return 253; - *baseDemand = (double)(d->Base * p->Ucf[FLOW]); + // Locate demand category record and assign demandName to it + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + *baseDemand = get_base_demand(lnode) * p->Ucf[FLOW]; } else *baseDemand = (double)(0.0); return 0; @@ -2777,9 +2810,6 @@ int DLLEXPORT EN_setbasedemand(EN_Project p, int nodeIndex, int demandIndex, **---------------------------------------------------------------- */ { - Pdemand d; - int n = 1; - // Check for valid arguments if (!p->Openflag) return 102; if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203; @@ -2787,10 +2817,13 @@ int DLLEXPORT EN_setbasedemand(EN_Project p, int nodeIndex, int demandIndex, // Set baseline demand for specified category if (nodeIndex <= p->network.Njuncs) { - for (d = p->network.Node[nodeIndex].D; n < demandIndex && d->next != NULL; - d = d->next) n++; - if (n != demandIndex) return 253; - d->Base = baseDemand / p->Ucf[FLOW]; + // Locate demand category record and assign demandName to it + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + set_base_demand(lnode, baseDemand / p->Ucf[FLOW]); } return 0; } @@ -2806,8 +2839,8 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex, **---------------------------------------------------------------- */ { - Pdemand d; - int n = 1; + //Pdemand d; + //int n = 1; strcpy(demandName, ""); @@ -2816,12 +2849,19 @@ int DLLEXPORT EN_getdemandname(EN_Project p, int nodeIndex, int demandIndex, if (nodeIndex <= 0 || nodeIndex > p->network.Njuncs) return 203; // Locate demand category record and retrieve its name - for (d = p->network.Node[nodeIndex].D; - n < demandIndex && d->next != NULL; d = d->next) n++; - if (n != demandIndex) return 253; + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + demandName = get_category_name(lnode); - if (d->Name) strcpy(demandName, d->Name); - else demandName[0] = '\0'; + //for (d = p->network.Node[nodeIndex].D; + // n < demandIndex && d->next != NULL; d = d->next) n++; + //if (n != demandIndex) return 253; + + //if (d->Name) strcpy(demandName, d->Name); + //else demandName[0] = '\0'; return 0; } @@ -2837,8 +2877,8 @@ int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex, **---------------------------------------------------------------- */ { - Pdemand d; - int n = 1; + //Pdemand d; + //int n = 1; // Check for valid arguments if (!p->Openflag) return 102; @@ -2848,10 +2888,13 @@ int DLLEXPORT EN_setdemandname(EN_Project p, int nodeIndex, int demandIndex, if (strlen(demandName) > MAXID) return 250; // Locate demand category record and assign demandName to it - for (d = p->network.Node[nodeIndex].D; - n < demandIndex && d->next != NULL; d = d->next) n++; - if (n != demandIndex) return 253; - d->Name = xstrcpy(&d->Name, demandName, MAXID); + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + set_category_name(lnode, demandName); + return 0; } @@ -2867,16 +2910,21 @@ int DLLEXPORT EN_getdemandpattern(EN_Project p, int nodeIndex, int demandIndex, **---------------------------------------------------------------- */ { - Pdemand d; - int n = 1; + //Pdemand d; + //int n = 1; // Check for valid arguments if (!p->Openflag) return 102; if (nodeIndex <= 0 || nodeIndex > p->network.Nnodes) return 203; - for (d = p->network.Node[nodeIndex].D; - n < demandIndex && d->next != NULL; d = d->next) n++; - if (n != demandIndex) return 253; - *patIndex = d->Pat; + + // Locate demand category record and assign demandName to it + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + *patIndex = get_pattern_index(lnode); + return 0; } @@ -2894,8 +2942,8 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex, { Network *net = &p->network; - Pdemand d; - int n = 1; + //Pdemand d; + //int n = 1; // Check for valid arguments if (!p->Openflag) return 102; @@ -2903,12 +2951,14 @@ int DLLEXPORT EN_setdemandpattern(EN_Project p, int nodeIndex, int demandIndex, if (patIndex <= 0 || patIndex > net->Npats) return 205; // Locate demand category record and assign time pattern to it - if (nodeIndex <= net->Njuncs) - { - for (d = net->Node[nodeIndex].D; - n < demandIndex && d->next != NULL; d = d->next) n++; - if (n != demandIndex) return 253; - d->Pat = patIndex; + if (nodeIndex <= net->Njuncs) { + + list_t *dlist = p->network.Node[nodeIndex].D; + list_node_t *lnode = get_nth_list(dlist, demandIndex); + if (!lnode) + return 253; + else + set_pattern_index(lnode, patIndex); } return 0; } diff --git a/src/hydraul.c b/src/hydraul.c index 1e3532e..ac3357a 100755 --- a/src/hydraul.c +++ b/src/hydraul.c @@ -27,6 +27,9 @@ #include "funcs.h" #include "text.h" +#include "demand.h" + + const double QZERO = 1.e-6; // Equivalent to zero flow in cfs // Imported functions @@ -553,7 +556,7 @@ void demands(Project *pr) int i ,j, n; long k, p; double djunc, sum; - Pdemand demand; +// Pdemand demand; // Determine total elapsed number of pattern periods p = (time->Htime + time->Pstart) / time->Pstep; @@ -563,12 +566,14 @@ void demands(Project *pr) for (i = 1; i <= net->Njuncs; i++) { sum = 0.0; - for (demand = net->Node[i].D; demand != NULL; demand = demand->next) + list_t *dlist = net->Node[i].D; + list_node_t *lnode; + for (lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode)) { // pattern period (k) = (elapsed periods) modulus (periods per pattern) - j = demand->Pat; + j = get_pattern_index(lnode); k = p % (long) net->Pattern[j].Length; - djunc = (demand->Base) * net->Pattern[j].F[k] * hyd->Dmult; + djunc = (get_base_demand(lnode)) * net->Pattern[j].F[k] * hyd->Dmult; if (djunc > 0.0) hyd->Dsystem += djunc; sum += djunc; } diff --git a/src/inpfile.c b/src/inpfile.c index 946f364..53aee71 100644 --- a/src/inpfile.c +++ b/src/inpfile.c @@ -28,6 +28,8 @@ Last Updated: 04/03/2019 #include "hash.h" #include "text.h" +#include "demand.h" + // Defined in enumstxt.h in EPANET.C extern char *LinkTxt[]; extern char *FormTxt[]; @@ -137,7 +139,7 @@ int saveinpfile(Project *pr, const char *fname) int i, j, n; double d, kc, ke, km, ucf; char s[MAXLINE + 1], s1[MAXLINE + 1], s2[MAXLINE + 1]; - Pdemand demand; + //Pdemand demand; Psource source; FILE *f; Slink *link; @@ -329,17 +331,23 @@ int saveinpfile(Project *pr, const char *fname) fprintf(f, "\n\n"); fprintf(f, s_DEMANDS); ucf = pr->Ucf[DEMAND]; - for (i = 1; i <= net->Njuncs; i++) + + list_t *dlist; + list_node_t *lnode; + + for (i = 1; i <= net->Njuncs; i++) { node = &net->Node[i]; - for (demand = node->D; demand != NULL; demand = demand->next) - { - sprintf(s, " %-31s %14.6f", node->ID, ucf * demand->Base); - if ((j = demand->Pat) > 0) sprintf(s1, " %-31s", net->Pattern[j].ID); - else strcpy(s1, " "); - fprintf(f, "\n%s %-31s", s, s1); - if (demand->Name) fprintf(f, " ;%s", demand->Name); - } + if (dlist = node->D) { + for (lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode)) { + + sprintf(s, " %-31s %14.6f", node->ID, ucf * get_base_demand(lnode)); + if ((j = get_pattern_index(lnode)) > 0) sprintf(s1, " %-31s", net->Pattern[j].ID); + else strcpy(s1, " "); + fprintf(f, "\n%s %-31s", s, s1); + if (get_category_name(lnode)) fprintf(f, " ;%s", get_category_name(lnode)); + } + } } // Write [EMITTERS] section diff --git a/src/project.c b/src/project.c index f340e8a..9324bea 100644 --- a/src/project.c +++ b/src/project.c @@ -29,6 +29,8 @@ #include "types.h" #include "funcs.h" +#include "demand.h" + int openfiles(Project *pr, const char *f1, const char *f2, const char *f3) /*---------------------------------------------------------------- ** Input: f1 = pointer to name of input file @@ -385,7 +387,7 @@ void freedata(Project *pr) */ { int j; - Pdemand demand, nextdemand; + //Pdemand demand, nextdemand; // Free memory for computed results free(pr->hydraul.NodeDemand); @@ -404,14 +406,15 @@ void freedata(Project *pr) for (j = 1; j <= pr->parser.MaxNodes; j++) { // Free memory used for demand category list - demand = pr->network.Node[j].D; - while (demand != NULL) + list_t *demand = pr->network.Node[j].D; + delete_list(demand); + /*while (demand != NULL) { nextdemand = demand->next; free(demand->Name); free(demand); demand = nextdemand; - } + }*/ // Free memory used for WQ source data free(pr->network.Node[j].S); free(pr->network.Node[j].Comment); @@ -788,10 +791,20 @@ void adjustpattern(int *pat, int index) **---------------------------------------------------------------- */ { - if (*pat == index) *pat = 0; - else if (*pat > index) (*pat)--; + if (*pat == index) *pat = 0; + else if (*pat > index) (*pat)--; } + +void _adjustpattern(list_node_t *lnode, int index) +{ + int pat = get_pattern_index(lnode); + + if (pat == index) set_pattern_index(lnode, 0); + else if (pat > index) set_pattern_index(lnode, pat--); +} + + void adjustpatterns(Network *network, int index) /*---------------------------------------------------------------- ** Input: index = index of time pattern being deleted @@ -801,17 +814,19 @@ void adjustpatterns(Network *network, int index) */ { int j; - Pdemand demand; + //Pdemand demand; Psource source; // Adjust patterns used by junctions for (j = 1; j <= network->Njuncs; j++) { // Adjust demand patterns - for (demand = network->Node[j].D; demand != NULL; demand = demand->next) - { - adjustpattern(&demand->Pat, index); - } + list_t *dlist = network->Node[j].D; + list_node_t *lnode; + + for (lnode = first_list(dlist); done_list(lnode); lnode = next_list(lnode)) + _adjustpattern(lnode, index); + // Adjust WQ source patterns source = network->Node[j].S; if (source) adjustpattern(&source->Pat, index); diff --git a/src/util/list.c b/src/util/list.c index fc2237e..c74e2c2 100644 --- a/src/util/list.c +++ b/src/util/list.c @@ -108,8 +108,9 @@ void for_each_list(list_t *list, listIterator iterator) list_node_t *node = list->head; bool result = true; - while(node != NULL && result) { - result = iterator(node); + + while(node != NULL && result) { + result = (iterator); node = node->next; } } @@ -120,14 +121,17 @@ list_node_t *head_list(list_t *list, bool removeFromList) // { assert(list->head != NULL); - - list_node_t *node = list->head; - if(removeFromList) { - // Disconnecting head node - list->head = node->next; - list->logicalLength--; + + if (list) { + list_node_t *node = list->head; + if (removeFromList) { + // Disconnecting head node + list->head = node->next; + list->logicalLength--; + } + return node; } - return node; + return NULL; } list_node_t *tail_list(list_t *list) @@ -136,6 +140,18 @@ list_node_t *tail_list(list_t *list) return list->tail; } +list_node_t *get_nth_list(list_t *list, int index) +{ + int n; + list_node_t *lnode; + + for (n = 1, lnode = first_list(list); n < index && done_list(lnode); n++, lnode = next_list(lnode)); + if (n != index) + return NULL; + else + return lnode; +} + int size_list(list_t *list) { return list->logicalLength; @@ -146,6 +162,11 @@ void *get_data(list_node_t *lnode) return lnode->data; } +list_node_t *get_next(list_node_t *lnode) +{ + return lnode->next; +} + void delete_node(list_t *list, list_node_t *lnode) { if (list->freeFn) @@ -154,29 +175,3 @@ void delete_node(list_t *list, list_node_t *lnode) free(lnode->data); free(lnode); } - -// -// Iterator first/done/next operations provide containment for list abstraction -// http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Iterators.html -// Accessed on April 11, 2019 -// -list_node_t *first_list(list_t *list) -{ - if (list) - return list->head; - else - return NULL; -} - -bool done_list(list_node_t *lnode) -{ - return lnode != NULL; -} - -list_node_t *next_list(list_node_t *lnode) -{ - if (lnode) - return lnode->next; - else - return NULL; -} diff --git a/src/util/list.h b/src/util/list.h index 090fa4a..e2e9185 100644 --- a/src/util/list.h +++ b/src/util/list.h @@ -19,6 +19,7 @@ #include + #if defined(__cplusplus) extern "C" { #endif @@ -28,8 +29,8 @@ extern "C" { typedef struct list_node_s list_node_t; typedef struct list_s list_t; -typedef void(*freeFunction)(void *); -typedef bool(*listIterator)(list_node_t *); +typedef void (*freeFunction) (void *); +typedef bool (*listIterator) (list_node_t *); /** @@ -65,6 +66,11 @@ int size_list(list_t *list); */ void *get_data(list_node_t *lnode); +/** +@brief Returns next list node. +*/ +list_node_t *get_next(list_node_t *lnode); + /** @brief Frees memory associated with a list node. */ @@ -87,21 +93,32 @@ list_node_t *head_list(list_t *list, bool removeFromList); */ list_node_t *tail_list(list_t *list); +/** +@brief Returns nth node of the list or NULL. +*/ +list_node_t *get_nth_list(list_t *list, int index); + + +// +// Iterator first/done/next operations +// http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Iterators.html +// Accessed on April 11, 2019 +// /** @brief Returns list head node. */ -list_node_t *first_list(list_t *list); +static inline list_node_t *first_list(list_t *list) { return head_list(list, false); } /** @brief Returns true if end of list false otherwise. */ -bool done_list(list_node_t *lnode); +static inline bool done_list(list_node_t *lnode) { return lnode != NULL; } /** @brief Returns next node in the list. */ -list_node_t *next_list(list_node_t *lnode); +static inline list_node_t *next_list(list_node_t *lnode) { return get_next(lnode); } #if defined(__cplusplus) diff --git a/tests/util/test_list.cpp b/tests/util/test_list.cpp index 7844e6e..787c1ed 100644 --- a/tests/util/test_list.cpp +++ b/tests/util/test_list.cpp @@ -63,8 +63,9 @@ BOOST_AUTO_TEST_CASE(test_int_list){ append_list(list, &i); } BOOST_CHECK(size_list(list) == 10); - - for_each_list(list, iterate_int); + + listIterator iterator = (listIterator)iterate_int; + for_each_list(list, iterator); delete_list(list); } @@ -111,7 +112,8 @@ BOOST_FIXTURE_TEST_CASE(test_string_list, FixtureStrings) { BOOST_CHECK(size_list(list) == 5); - for_each_list(list, iterate_string); + listIterator iterator = (listIterator)iterate_string; + for_each_list(list, iterator); } @@ -196,7 +198,8 @@ BOOST_AUTO_TEST_CASE(test_struct_list){ BOOST_CHECK(size_list(list) == 3); - for_each_list(list, iterate_test_data); + listIterator iterator = (listIterator)iterate_test_data; + for_each_list(list, iterator); list_node_t *lnode;