GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
misc-template.c
Go to the documentation of this file.
1/* LIBDGL -- a Directed Graph Library implementation
2 * SPDX-FileCopyrightText: 2002 Roberto Micarelli
3 * SPDX-FileCopyrightText: GRASS Development Team
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7/*
8 * best view with tabstop=4
9 */
10
11#include <grass/gis.h>
12
13/*
14 * Edge Traversing
15 */
19{
20#if defined(_DGL_V1)
22 return -pGraph->iErrno;
23#else
24 if (pGraph->Flags & DGL_GS_FLAT) {
25 if (pEP && pEP->pvAVL) {
26 if ((pT->pvAVLT = malloc(sizeof(struct avl_traverser))) == NULL) {
28 return -pGraph->iErrno;
29 }
30 avl_t_init(pT->pvAVLT, pEP->pvAVL);
31 pT->pnEdge = NULL;
32 pT->pEdgePrioritizer = pEP;
33 }
34 else {
35 pT->pvAVLT = NULL;
36 pT->pnEdge = NULL;
37 pT->pEdgePrioritizer = NULL;
38 }
39 }
40 else {
41 if ((pT->pvAVLT = malloc(sizeof(struct avl_traverser))) == NULL) {
43 return -pGraph->iErrno;
44 }
45 if (pEP && pEP->pvAVL) {
46 avl_t_init(pT->pvAVLT, pEP->pvAVL);
47 pT->pnEdge = NULL;
48 pT->pEdgePrioritizer = pEP;
49 }
50 else {
51 avl_t_init(pT->pvAVLT, pGraph->pEdgeTree);
52 pT->pnEdge = NULL;
53 pT->pEdgePrioritizer = NULL;
54 }
55 }
56 pT->pGraph = pGraph;
57 return 0;
58#endif
59}
60
62{
63#if defined(_DGL_V1)
64 pT->pGraph->iErrno = DGL_ERR_NotSupported;
65#else
66 if (pT->pvAVLT)
67 free(pT->pvAVLT);
68 pT->pvAVLT = NULL;
69 pT->pnEdge = NULL;
70 pT->pEdgePrioritizer = NULL;
71#endif
72}
73
75{
76#if defined(_DGL_V1)
77 pT->pGraph->iErrno = DGL_ERR_NotSupported;
78 return NULL;
79#else
80 dglGraph_s *pG = pT->pGraph;
81
82 pT->pnEdge = NULL;
83 if (pT->pvAVLT && pT->pEdgePrioritizer) {
84 dglEdgePrioritizer_s *pPri = pT->pEdgePrioritizer;
86
87 pItem = avl_t_first(pT->pvAVLT, pPri->pvAVL);
88 if (pItem) {
89 /*
90 printf("edge_t_first: cEdge=%ld\n", pItem->cnData);
91 */
92 pPri->cEdge = pItem->cnData;
93 pPri->iEdge = 0;
94 if (pPri->iEdge < pPri->cEdge) {
95 pT->pnEdge = DGL_GET_EDGE_FUNC(pG, pItem->pnData[pPri->iEdge]);
96 pPri->iEdge++;
97 }
98 }
99 pPri->pEdgePri32Item = pItem;
100 }
101 else if (pT->pvAVLT) {
103
104 if ((pEdgeItem = avl_t_first(pT->pvAVLT, pG->pEdgeTree)) == NULL) {
105 pT->pnEdge = NULL;
106 }
107 else {
108 pT->pnEdge = pEdgeItem->pv;
109 }
110 }
111 else {
112 if (pG->cEdge > 0)
113 pT->pnEdge = (dglInt32_t *)pG->pEdgeBuffer;
114 else
115 pT->pnEdge = NULL;
116 }
117 return pT->pnEdge;
118#endif
119}
120
122{
123#if defined(_DGL_V1)
124 pT->pGraph->iErrno = DGL_ERR_NotSupported;
125 return NULL;
126#else
127 dglGraph_s *pG = pT->pGraph;
128
129 pT->pnEdge = NULL;
130
131 if (pT->pvAVLT && pT->pEdgePrioritizer) {
132 dglEdgePrioritizer_s *pPri = pT->pEdgePrioritizer;
133 dglTreeEdgePri32_s *pItem = pPri->pEdgePri32Item;
134
135 if (pItem && pPri->iEdge < pPri->cEdge) {
136 pT->pnEdge = DGL_GET_EDGE_FUNC(pG, pItem->pnData[pPri->iEdge]);
137 pPri->iEdge++;
138 }
139 else {
140 if ((pItem = avl_t_next(pT->pvAVLT)) != NULL) {
141 pPri->cEdge = pItem->cnData;
142 pPri->iEdge = 0;
143 if (pPri->iEdge < pPri->cEdge) {
144 pT->pnEdge =
145 DGL_GET_EDGE_FUNC(pG, pItem->pnData[pPri->iEdge]);
146 pPri->iEdge++;
147 }
148 }
149 pPri->pEdgePri32Item = pItem;
150 }
151 }
152 else if (pT->pvAVLT) {
154
155 if ((pItem = avl_t_next(pT->pvAVLT)) != NULL) {
156 pT->pnEdge = pItem->pv;
157 }
158 }
159 else {
160 pT->pnEdge += DGL_NODE_WSIZE(pG->EdgeAttrSize);
161 if (pT->pnEdge >= (dglInt32_t *)(pG->pEdgeBuffer + pG->iEdgeBuffer)) {
162 pT->pnEdge = NULL;
163 }
164 }
165 return pT->pnEdge;
166#endif
167}
168
169/*
170 * Node Traversing
171 */
173{
174 if (pGraph->Flags & DGL_GS_FLAT) {
175 pT->pnNode = NULL;
176 pT->pvAVLT = NULL;
177 }
178 else {
179 if ((pT->pvAVLT = malloc(sizeof(struct avl_traverser))) == NULL) {
181 return -pGraph->iErrno;
182 }
183 avl_t_init(pT->pvAVLT, pGraph->pNodeTree);
184 pT->pnNode = NULL;
185 }
186 pT->pGraph = pGraph;
187 return 0;
188}
189
191{
192 if (pT->pvAVLT)
193 free(pT->pvAVLT);
194 pT->pvAVLT = NULL;
195 pT->pnNode = NULL;
196}
197
199{
201
202 if (pT->pvAVLT) {
203 if ((pNodeItem = avl_t_first(pT->pvAVLT, pT->pGraph->pNodeTree)) ==
204 NULL)
205 pT->pnNode = NULL;
206 else
208 }
209 else {
210 if (pT->pGraph->cNode > 0)
211 pT->pnNode = (dglInt32_t *)pT->pGraph->pNodeBuffer;
212 else
213 pT->pnNode = NULL;
214 }
215 return pT->pnNode;
216}
217
219{
221
222 if (pT->pvAVLT) {
223 if ((pNodeItem = avl_t_next(pT->pvAVLT)) == NULL)
224 pT->pnNode = NULL;
225 else
227 }
228 else {
229 pT->pnNode += DGL_NODE_WSIZE(pT->pGraph->NodeAttrSize);
230 if (pT->pnNode >=
231 (dglInt32_t *)(pT->pGraph->pNodeBuffer + pT->pGraph->iNodeBuffer))
232 pT->pnNode = NULL;
233 }
234 return pT->pnNode;
235}
236
238{
240
241 if (pT->pvAVLT) {
242 findItem.nKey = nNodeId;
243 if ((pNodeItem = avl_t_find(pT->pvAVLT, pT->pGraph->pNodeTree,
244 &findItem)) == NULL)
245 pT->pnNode = NULL;
246 else
248 }
249 else {
250 pT->pnNode = DGL_GET_NODE_FUNC(pT->pGraph, nNodeId);
251 }
252 return pT->pnNode;
253}
254
255/*
256 * Edgeset Traversing
257 */
259 dglInt32_t *pnEdgeset)
260{
261 pT->pGraph = pGraph;
262 pT->pnEdgeset = pnEdgeset;
263 pT->cEdge = (pnEdgeset) ? *pnEdgeset : 0;
264 pT->iEdge = 0;
265 return 0;
266}
267
271
273{
274#if defined(_DGL_V2)
277#endif
278
279 if (pT->cEdge == 0)
280 return NULL;
281 pT->iEdge = 1;
282#if defined(_DGL_V1)
283 return pT->pnEdgeset + 1;
284#endif
285#if defined(_DGL_V2)
286 pnOffset = pT->pnEdgeset + 1;
287 if (pT->pGraph->Flags & DGL_GS_FLAT) {
288 pT->pvCurrentItem = NULL;
289 return DGL_EDGEBUFFER_SHIFT(pT->pGraph, *pnOffset);
290 }
291 else {
292 EdgeItem.nKey = *pnOffset;
293 if ((pEdgeItem = avl_find(pT->pGraph->pEdgeTree, &EdgeItem)) != NULL) {
294 pT->pvCurrentItem = pEdgeItem;
295 return pEdgeItem->pv;
296 }
297 }
298#endif
299 return NULL;
300}
301
303{
304#if defined(_DGL_V2)
307#endif
308
309 if (pT->cEdge > 0 && pT->iEdge < pT->cEdge) {
310#if defined(_DGL_V1)
311 return DGL_EDGESET_EDGE_PTR(pT->pnEdgeset, pT->iEdge++,
312 pT->pGraph->EdgeAttrSize);
313#endif
314#if defined(_DGL_V2)
315 pnOffset = pT->pnEdgeset + 1 + pT->iEdge++;
316 if (pT->pGraph->Flags & DGL_GS_FLAT) {
317 return DGL_EDGEBUFFER_SHIFT(pT->pGraph, *pnOffset);
318 }
319 else {
320 EdgeItem.nKey = *pnOffset;
321 if ((pEdgeItem = avl_find(pT->pGraph->pEdgeTree, &EdgeItem)) !=
322 NULL) {
323 pT->pvCurrentItem = pEdgeItem;
324 return pEdgeItem->pv;
325 }
326 }
327#endif
328 }
329 return NULL;
330}
331
332/*
333 * Flatten the graph
334 */
336{
338
339#if defined(_DGL_V2)
340 register dglTreeEdge_s *ptreeEdge;
341 int i;
342#endif
343 register dglInt32_t *pEdge;
344 register dglInt32_t *pnode;
345 register dglInt32_t *pnodescan;
347#if !defined(_DGL_V1)
349#endif
350 int cOutEdgeset;
351 int cInEdgeset;
352
354
355 if (pgraph->Flags & DGL_GS_FLAT) {
357 return -pgraph->iErrno;
358 }
359
360 pgraph->pNodeBuffer = NULL; /* should be already */
361 pgraph->iNodeBuffer = 0;
362 pgraph->pEdgeBuffer = NULL;
363 pgraph->iEdgeBuffer = 0;
364
365#if defined(_DGL_V2)
366 /*
367 printf("flatten: traversing edges\n");
368 */
369 avl_t_init(&avlTraverser, pgraph->pEdgeTree);
370
371 for (ptreeEdge = avl_t_first(&avlTraverser, pgraph->pEdgeTree); ptreeEdge;
373 pEdge = ptreeEdge->pv;
374
375 /*
376 printf( "flatten: add edge %ld to edge buffer\n", DGL_EDGE_ID(pEdge)
377 );
378 */
379
380 pgraph->pEdgeBuffer = realloc(
381 pgraph->pEdgeBuffer,
382 pgraph->iEdgeBuffer + DGL_EDGE_SIZEOF(pgraph->EdgeAttrSize));
383
384 if (pgraph->pEdgeBuffer == NULL) {
386 return -pgraph->iErrno;
387 }
388
389 memcpy(pgraph->pEdgeBuffer + pgraph->iEdgeBuffer, pEdge,
390 DGL_EDGE_SIZEOF(pgraph->EdgeAttrSize));
391
392 pgraph->iEdgeBuffer += DGL_EDGE_SIZEOF(pgraph->EdgeAttrSize);
393 }
394#endif
395
396 /*
397 printf("flatten: traversing nodes\n");
398 */
399 avl_t_init(&avlTraverser, pgraph->pNodeTree);
400
401 for (ptreenode = avl_t_first(&avlTraverser, pgraph->pNodeTree); ptreenode;
405#if !defined(_DGL_V1)
407#endif
408
409 if (!(DGL_NODE_STATUS(pnode) & DGL_NS_ALONE)) {
413 pgraph->EdgeAttrSize)
414 : sizeof(dglInt32_t);
415
416#if !defined(_DGL_V1)
417 cInEdgeset =
418 (pInEdgeset)
420 pgraph->EdgeAttrSize)
421 : sizeof(dglInt32_t);
422#else
423 cInEdgeset = 0;
424#endif
425
426 pgraph->pEdgeBuffer =
427 realloc(pgraph->pEdgeBuffer,
428 pgraph->iEdgeBuffer + cOutEdgeset + cInEdgeset);
429
430 if (pgraph->pEdgeBuffer == NULL) {
432 return -pgraph->iErrno;
433 }
434
435 {
436 dglInt32_t nDummy = 0;
437
438 memcpy(pgraph->pEdgeBuffer + pgraph->iEdgeBuffer,
440#if !defined(_DGL_V1)
441 memcpy(pgraph->pEdgeBuffer + pgraph->iEdgeBuffer + cOutEdgeset,
443#endif
444 }
445
446 DGL_NODE_EDGESET_OFFSET(pnode) = pgraph->iEdgeBuffer;
447
448 pgraph->iEdgeBuffer += cOutEdgeset + cInEdgeset;
449 }
450
451 pgraph->pNodeBuffer = realloc(
452 pgraph->pNodeBuffer,
453 pgraph->iNodeBuffer + DGL_NODE_SIZEOF(pgraph->NodeAttrSize));
454
455 if (pgraph->pNodeBuffer == NULL) {
457 return -pgraph->iErrno;
458 }
459
460 memcpy(pgraph->pNodeBuffer + pgraph->iNodeBuffer, pnode,
461 DGL_NODE_SIZEOF(pgraph->NodeAttrSize));
462 pgraph->iNodeBuffer += DGL_NODE_SIZEOF(pgraph->NodeAttrSize);
463 }
464
465#if defined(_DGL_V2)
466 if (pgraph->pEdgeTree) {
468 pgraph->pEdgeTree = NULL;
469 }
470#endif
471
472 if (pgraph->pNodeTree) {
474 pgraph->pNodeTree = NULL;
475 }
476
477 pgraph->Flags |= DGL_GS_FLAT; /* flattened */
478
479 /*
480 * convert node-id to node-offset
481 */
486
487#if defined(_DGL_V2)
488 for (i = 0; i < pOutEdgeset[0]; i++) {
489 /*
490 printf("flatten: node %ld: scan out edge %ld/%ld - %ld\n",
491 DGL_NODE_ID(pnodescan), i+1, pOutEdgeset[0],
492 pOutEdgeset[i+1]);
493 */
495 if (pEdge == NULL) {
497 return -pgraph->iErrno;
498 }
499 /*
500 printf(" retrieved id %ld\n", DGL_EDGE_ID(pEdge) );
501 */
503 }
504
506
507 for (i = 0; i < pInEdgeset[0]; i++) {
508 /*
509 printf("flatten: node %ld: scan in edge %ld/%ld - %ld\n",
510 DGL_NODE_ID(pnodescan), i+1, pInEdgeset[0], pInEdgeset[i+1]);
511 */
513 if (pEdge == NULL) {
515 return -pgraph->iErrno;
516 }
517 /*
518 printf(" retrieved id %ld\n", DGL_EDGE_ID(pEdge) );
519 */
521 }
522#endif
523
524#if defined(_DGL_V2)
525 {
526 int iEdge;
527
529#else
531#endif
532 {
533 if ((pnode = DGL_GET_NODE_FUNC(
535 NULL) {
537 return -pgraph->iErrno;
538 }
541
542 if ((pnode = DGL_GET_NODE_FUNC(
544 NULL) {
546 return -pgraph->iErrno;
547 }
550 }
551#if defined(_DGL_V2)
552 }
553#endif
554 }
555 }
556
557 return 0;
558}
559
561{
562 register dglInt32_t *pHead;
563 register dglInt32_t *pTail;
564 register dglInt32_t *pEdge;
565 register dglInt32_t *pEdgeset;
566 int nret;
567
568 if (!(pgraph->Flags & DGL_GS_FLAT)) {
570 return -pgraph->iErrno;
571 }
572
573 /*
574 * unflag it now to avoid DGL_ADD_EDGE_FUNC() failure
575 */
576 pgraph->Flags &= ~DGL_GS_FLAT;
577 pgraph->cNode = 0;
578 pgraph->cEdge = 0;
579 pgraph->cHead = 0;
580 pgraph->cTail = 0;
581 pgraph->cAlone = 0;
582 pgraph->nnCost = (dglInt64_t)0;
583
584 if (pgraph->pNodeTree == NULL)
585 pgraph->pNodeTree =
587 if (pgraph->pNodeTree == NULL) {
589 return -pgraph->iErrno;
590 }
591#if defined(_DGL_V1)
592 pgraph->pEdgeTree = NULL;
593#else
594 if (pgraph->pEdgeTree == NULL)
595 pgraph->pEdgeTree =
597 if (pgraph->pEdgeTree == NULL) {
599 return -pgraph->iErrno;
600 }
601#endif
602
605 pEdgeset =
607
608#if defined(_DGL_V2)
609 {
610 int iEdge;
611
613#else
615#endif
616 {
619
625
626 if (nret < 0) {
627 goto error;
628 }
629 }
630#if defined(_DGL_V2)
631 }
632#endif
633 }
634 else if (DGL_NODE_STATUS(pHead) & DGL_NS_ALONE) {
637 if (nret < 0) {
638 goto error;
639 }
640 }
641 }
642
643 /* move away flat-state data
644 */
645 if (pgraph->pNodeBuffer)
646 free(pgraph->pNodeBuffer);
647 if (pgraph->pEdgeBuffer)
648 free(pgraph->pEdgeBuffer);
649 pgraph->pNodeBuffer = NULL;
650 pgraph->pEdgeBuffer = NULL;
651 return 0;
652
653error:
654 if (pgraph->pNodeTree)
656 if (pgraph->pEdgeTree)
658 pgraph->pNodeTree = NULL;
659 pgraph->pEdgeTree = NULL;
660 pgraph->Flags |= DGL_GS_FLAT;
661 return nret;
662}
#define NULL
Definition ccmath.h:32
#define G_UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:43
#define DGL_ERR_BadOnTreeGraph
Definition graph.h:253
#define DGL_NS_ALONE
Definition graph.h:49
#define DGL_ERR_MemoryExhausted
Definition graph.h:242
#define DGL_ERR_BadOnFlatGraph
Definition graph.h:252
#define DGL_NS_HEAD
Definition graph.h:47
#define DGL_ERR_NotSupported
Definition graph.h:247
#define DGL_GS_FLAT
Definition graph.h:24
#define DGL_ERR_HeadNodeNotFound
Definition graph.h:249
#define DGL_ERR_UnexpectedNullPointer
Definition graph.h:256
#define DGL_ERR_TailNodeNotFound
Definition graph.h:250
void * malloc(unsigned)
void free(void *)
dglByte_t * pEdgeBuffer
Definition graph.h:149
dglInt32_t cEdge
Definition graph.h:138
dglInt32_t EdgeAttrSize
Definition graph.h:131
dglInt32_t iEdgeBuffer
Definition graph.h:150
int iErrno
Definition graph.h:126
void * pNodeTree
Definition graph.h:145
void * pEdgeTree
Definition graph.h:146
dglInt32_t Flags
Definition graph.h:141
void dglTreeEdgeCancel(void *pvEdge, void *pvParam)
Definition tree.c:140
void * dglTreeGetAllocator(void)
Definition tree.c:394
void dglTreeNodeCancel(void *pvNode, void *pvParam)
Definition tree.c:33
int dglTreeEdgeCompare(const void *pvEdgeA, const void *pvEdgeB, void *pvParam)
Definition tree.c:147
#define avl_find
Definition tree.h:26
#define avl_create
Definition tree.h:19
#define avl_t_next
Definition tree.h:35
#define avl_t_find
Definition tree.h:32
#define avl_t_first
Definition tree.h:30
#define avl_destroy
Definition tree.h:21
#define avl_t_init
Definition tree.h:29
long long dglInt64_t
Definition type.h:25
long dglInt32_t
Definition type.h:24
#define DGL_EDGESET_EDGE_PTR
Definition v1-defs.h:137
#define DGL_EDGESET_T_FIRST_FUNC
Definition v1-defs.h:100
#define DGL_T_NODEITEM_InEdgesetPTR(p)
Definition v1-defs.h:161
#define DGL_EDGE_T_RELEASE_FUNC
Definition v1-defs.h:90
#define DGL_NODE_T_RELEASE_FUNC
Definition v1-defs.h:94
#define DGL_NODE_T_INITIALIZE_FUNC
Definition v1-defs.h:93
#define DGL_NODEBUFFER_OFFSET
Definition v1-defs.h:146
#define DGL_T_NODEITEM_TYPE
Definition v1-defs.h:156
#define DGL_NODE_STATUS
Definition v1-defs.h:114
#define DGL_EDGE_SIZEOF
Definition v1-defs.h:122
#define DGL_ADD_NODE_FUNC
Definition v1-defs.h:78
#define DGL_NODE_T_FIND_FUNC
Definition v1-defs.h:97
#define DGL_UNFLATTEN_FUNC
Definition v1-defs.h:103
#define DGL_NODE_ID
Definition v1-defs.h:115
#define DGL_NODE_EDGESET_OFFSET
Definition v1-defs.h:117
#define DGL_NODE_T_FIRST_FUNC
Definition v1-defs.h:95
#define DGL_T_NODEITEM_OutEdgesetPTR(p)
Definition v1-defs.h:159
#define DGL_EDGE_T_NEXT_FUNC
Definition v1-defs.h:92
#define DGL_T_NODEITEM_Compare
Definition v1-defs.h:163
#define DGL_EDGE_TAILNODE_OFFSET
Definition v1-defs.h:129
#define DGL_GET_NODE_FUNC
Definition v1-defs.h:80
#define DGL_EDGEBUFFER_SHIFT
Definition v1-defs.h:147
#define DGL_NODE_WSIZE
Definition v1-defs.h:113
#define DGL_EDGESET_EDGECOUNT
Definition v1-defs.h:136
#define DGL_EDGE_ATTR_PTR
Definition v1-defs.h:127
#define DGL_EDGESET_T_RELEASE_FUNC
Definition v1-defs.h:99
#define DGL_EDGEBUFFER_OFFSET
Definition v1-defs.h:148
#define DGL_EDGE_T_FIRST_FUNC
Definition v1-defs.h:91
#define DGL_NODE_T_NEXT_FUNC
Definition v1-defs.h:96
#define DGL_EDGESET_T_INITIALIZE_FUNC
Definition v1-defs.h:98
#define DGL_NODE_SIZEOF
Definition v1-defs.h:112
#define DGL_EDGESET_SIZEOF
Definition v1-defs.h:140
#define DGL_GET_EDGE_FUNC
Definition v1-defs.h:85
#define DGL_T_NODEITEM_NodePTR(p)
Definition v1-defs.h:157
#define DGL_NODE_ATTR_PTR
Definition v1-defs.h:116
#define DGL_EDGE_ID
Definition v1-defs.h:126
#define DGL_EDGE_HEADNODE_OFFSET
Definition v1-defs.h:128
#define DGL_ADD_EDGE_FUNC
Definition v1-defs.h:84
#define DGL_FOREACH_EDGE
Definition v1-defs.h:151
#define DGL_EDGESET_T_NEXT_FUNC
Definition v1-defs.h:101
#define DGL_FOREACH_NODE
Definition v1-defs.h:150
#define DGL_EDGE_COST
Definition v1-defs.h:125
#define DGL_NODEBUFFER_SHIFT
Definition v1-defs.h:145
#define DGL_FLATTEN_FUNC
Definition v1-defs.h:102
#define DGL_EDGE_T_INITIALIZE_FUNC
Definition v1-defs.h:89