gwenhywfar  5.14.1
tree2.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Thu Jul 04 2019
3  copyright : (C) 2019 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 #include "tree2_p.h"
32 #include <gwenhywfar/quicksort.h>
33 #include <gwenhywfar/misc.h>
34 #include <gwenhywfar/debug.h>
35 
36 #include <stdlib.h>
37 
38 
39 
40 static int _compare(const void *a, const void *b, void *f);
41 
42 
43 
44 
46 {
48 
50  el->data=d;
51 
52  return el;
53 }
54 
55 
56 
58 {
59  if (el) {
60  if (el->firstChild) {
61  DBG_ERROR(GWEN_LOGDOMAIN, "Tree element still has children");
62  assert(0);
63  }
64  GWEN_FREE_OBJECT(el);
65  }
66 }
67 
68 
69 
71 {
72 
73  /* unlink from previous */
74  if (el->prevElement)
75  el->prevElement->nextElement=el->nextElement;
76 
77  /* unlink from next */
78  if (el->nextElement)
79  el->nextElement->prevElement=el->prevElement;
80 
81  /* unlink from parent */
82  if (el->parent) {
83  if (el->parent->firstChild==el)
84  el->parent->firstChild=el->nextElement;
85  if (el->parent->lastChild==el)
86  el->parent->lastChild=el->prevElement;
87  }
88 
89  el->nextElement=NULL;
90  el->prevElement=NULL;
91  el->parent=NULL;
92 }
93 
94 
95 
96 void GWEN_Tree2_Replace(GWEN_TREE2_ELEMENT *elToReplace, GWEN_TREE2_ELEMENT *elReplacement)
97 {
98  elReplacement->nextElement=NULL;
99  elReplacement->prevElement=NULL;
100  elReplacement->parent=NULL;
101 
102  /* relink with previous */
103  if (elToReplace->prevElement)
104  elToReplace->prevElement->nextElement=elReplacement;
105  elReplacement->prevElement=elToReplace->prevElement;
106 
107  /* relink with next */
108  if (elToReplace->nextElement)
109  elToReplace->nextElement->prevElement=elReplacement;
110  elReplacement->nextElement=elToReplace->nextElement;
111 
112  /* relink with parent */
113  if (elToReplace->parent) {
114  elReplacement->parent=elToReplace->parent;
115  if (elToReplace->parent->firstChild==elToReplace)
116  elToReplace->parent->firstChild=elReplacement;
117  if (elToReplace->parent->lastChild==elToReplace)
118  elToReplace->parent->lastChild=elReplacement;
119  }
120 
121  elToReplace->nextElement=NULL;
122  elToReplace->prevElement=NULL;
123  elToReplace->parent=NULL;
124 }
125 
126 
127 
129 {
130  if (where->firstChild==NULL)
131  where->firstChild=el;
132 
133  el->prevElement=where->lastChild;
134  if (where->lastChild)
135  where->lastChild->nextElement=el;
136  where->lastChild=el;
137 
138  el->parent=where;
139 }
140 
141 
142 
144 {
145  el->nextElement=where->firstChild;
146  where->firstChild=el;
147 
148  if (where->lastChild==NULL)
149  where->lastChild=el;
150 
151  el->parent=where;
152 }
153 
154 
155 
157 {
158  if (el->prevElement)
159  return el->prevElement->data;
160  return 0;
161 }
162 
163 
164 
166 {
167  if (el->nextElement)
168  return el->nextElement->data;
169  return 0;
170 }
171 
172 
173 
175 {
176  if (el->firstChild) /* look down */
177  return el->firstChild->data;
178  else if (el->nextElement) /* look right */
179  return el->nextElement->data;
180  else {
181  /* look for a parent which has a right neighbour */
182  while (el && el->parent) {
183  if (el->parent->nextElement) /* look right of parent */
184  return el->parent->nextElement->data;
185  /* parent has no right neighbour, consult its parent */
186  el=el->parent;
187  }
188  }
189 
190  return NULL;
191 }
192 
193 
194 
196 {
197  uint32_t num=0;
198 
199  if (el) {
200  const GWEN_TREE2_ELEMENT *child;
201 
202  child=el->firstChild;
203  while(child) {
204  num++;
205  child=child->nextElement;
206  }
207  }
208  return 0;
209 }
210 
211 
212 
214 {
215  if (el->firstChild)
216  return el->firstChild->data;
217  return NULL;
218 }
219 
220 
221 
223 {
224  if (el->lastChild)
225  return el->lastChild->data;
226  return NULL;
227 }
228 
229 
230 
232 {
233  if (el->parent)
234  return el->parent->data;
235  return NULL;
236 }
237 
238 
239 
241 {
242  int numChildren;
243 
244  numChildren=GWEN_Tree2Element_GetChildrenCount(el);
245  if (numChildren) {
246  GWEN_TREE2_ELEMENT **tmpEntries;
247 
248  tmpEntries=(GWEN_TREE2_ELEMENT **)malloc((numChildren+1)* sizeof(GWEN_TREE2_ELEMENT *));
249  if (tmpEntries) {
250  GWEN_TREE2_ELEMENT *child;
251  GWEN_TREE2_ELEMENT **sortArrayPtr;
252  int i;
253 
254  sortArrayPtr=tmpEntries;
255  while( (child=el->firstChild) ) {
256  GWEN_Tree2_Unlink(child);
257  *(sortArrayPtr++)=child;
258  }
259 
260  GWEN_QuickSort((void**)tmpEntries, numChildren, sizeof(GWEN_TREE2_ELEMENT*), _compare, cb);
261 
262  sortArrayPtr=tmpEntries;
263  for (i=0; i<numChildren; i++) {
264  GWEN_Tree2_AddChild(el, *(sortArrayPtr++));
265  }
266  free(tmpEntries);
267  }
268  }
269 }
270 
271 
272 
273 int _compare(const void *a, const void *b, void *f)
274 {
276  const GWEN_TREE2_ELEMENT *elA;
277  const GWEN_TREE2_ELEMENT *elB;
278 
279  cb=(GWEN_TREE2_COMPARE_CB) f;
280  elA=(GWEN_TREE2_ELEMENT*) a;
281  elB=(GWEN_TREE2_ELEMENT*) b;
282  return cb(elA->data, elB->data);
283 }
284 
285 
286 
uint32_t GWEN_Tree2Element_GetChildrenCount(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:195
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
int(* GWEN_TREE2_COMPARE_CB)(void *p1, void *p2)
Definition: tree2.h:157
void GWEN_Tree2_AddChild(GWEN_TREE2_ELEMENT *where, GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:128
struct GWEN_TREE2_ELEMENT GWEN_TREE2_ELEMENT
Definition: tree2.h:155
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
void * GWEN_Tree2Element_GetParent(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:231
void * GWEN_Tree2Element_GetLastChild(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:222
#define GWEN_LOGDOMAIN
Definition: logger.h:32
void GWEN_Tree2Element_free(GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:57
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
void GWEN_Tree2_Unlink(GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:70
void GWEN_Tree2Element_SortChildren(GWEN_TREE2_ELEMENT *el, GWEN_TREE2_COMPARE_CB cb)
Definition: tree2.c:240
void * GWEN_Tree2Element_GetNext(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:165
void GWEN_QuickSort(void *array, int numElems, int sizeElems, GWEN_QUICKSORT_COMPARE_CB cb, void *arg)
Definition: quicksort.c:49
void GWEN_Tree2_InsertChild(GWEN_TREE2_ELEMENT *where, GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:143
void GWEN_Tree2_Replace(GWEN_TREE2_ELEMENT *elToReplace, GWEN_TREE2_ELEMENT *elReplacement)
Definition: tree2.c:96
void * GWEN_Tree2Element_GetFirstChild(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:213
void * GWEN_Tree2Element_GetBelow(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:174
void * GWEN_Tree2Element_GetPrevious(const GWEN_TREE2_ELEMENT *el)
Definition: tree2.c:156
static int _compare(const void *a, const void *b, void *f)
Definition: tree2.c:273
GWEN_TREE2_ELEMENT * GWEN_Tree2Element_new(void *d)
Definition: tree2.c:45