xref: /php-src/ext/dom/lexbor/lexbor/core/bst.c (revision bffab33a)
1 /*
2  * Copyright (C) 2018 Alexander Borisov
3  *
4  * Author: Alexander Borisov <borisov@lexbor.com>
5  */
6 
7 #include "lexbor/core/bst.h"
8 #include "lexbor/core/conv.h"
9 
10 
11 lexbor_bst_t *
lexbor_bst_create(void)12 lexbor_bst_create(void)
13 {
14     return lexbor_calloc(1, sizeof(lexbor_bst_t));
15 }
16 
17 lxb_status_t
lexbor_bst_init(lexbor_bst_t * bst,size_t size)18 lexbor_bst_init(lexbor_bst_t *bst, size_t size)
19 {
20     lxb_status_t status;
21 
22     if (bst == NULL) {
23         return LXB_STATUS_ERROR_OBJECT_IS_NULL;
24     }
25 
26     if (size == 0) {
27         return LXB_STATUS_ERROR_WRONG_ARGS;
28     }
29 
30     bst->dobject = lexbor_dobject_create();
31     status = lexbor_dobject_init(bst->dobject, size,
32                                  sizeof(lexbor_bst_entry_t));
33     if (status != LXB_STATUS_OK) {
34         return status;
35     }
36 
37     bst->root = 0;
38     bst->tree_length = 0;
39 
40     return LXB_STATUS_OK;
41 }
42 
43 void
lexbor_bst_clean(lexbor_bst_t * bst)44 lexbor_bst_clean(lexbor_bst_t *bst)
45 {
46     if (bst != NULL) {
47         lexbor_dobject_clean(bst->dobject);
48 
49         bst->root = 0;
50         bst->tree_length = 0;
51     }
52 }
53 
54 lexbor_bst_t *
lexbor_bst_destroy(lexbor_bst_t * bst,bool self_destroy)55 lexbor_bst_destroy(lexbor_bst_t *bst, bool self_destroy)
56 {
57     if (bst == NULL) {
58         return NULL;
59     }
60 
61     bst->dobject = lexbor_dobject_destroy(bst->dobject, true);
62 
63     if (self_destroy) {
64         return lexbor_free(bst);
65     }
66 
67     return bst;
68 }
69 
70 lexbor_bst_entry_t *
lexbor_bst_entry_make(lexbor_bst_t * bst,size_t size)71 lexbor_bst_entry_make(lexbor_bst_t *bst, size_t size)
72 {
73     lexbor_bst_entry_t *new_entry = lexbor_dobject_calloc(bst->dobject);
74     if (new_entry == NULL) {
75         return NULL;
76     }
77 
78     new_entry->size = size;
79 
80     bst->tree_length++;
81 
82     return new_entry;
83 }
84 
85 lexbor_bst_entry_t *
lexbor_bst_insert(lexbor_bst_t * bst,lexbor_bst_entry_t ** scope,size_t size,void * value)86 lexbor_bst_insert(lexbor_bst_t *bst, lexbor_bst_entry_t **scope,
87                   size_t size, void *value)
88 {
89     lexbor_bst_entry_t *new_entry, *entry;
90 
91     new_entry = lexbor_dobject_calloc(bst->dobject);
92     if (new_entry == NULL) {
93         return NULL;
94     }
95 
96     new_entry->size  = size;
97     new_entry->value = value;
98 
99     bst->tree_length++;
100 
101     if (*scope == NULL) {
102         *scope = new_entry;
103         return new_entry;
104     }
105 
106     entry = *scope;
107 
108     while (entry != NULL) {
109         if (size == entry->size) {
110             if (entry->next) {
111                 new_entry->next = entry->next;
112             }
113 
114             entry->next = new_entry;
115             new_entry->parent = entry->parent;
116 
117             return new_entry;
118         }
119         else if (size > entry->size) {
120             if (entry->right == NULL) {
121                 entry->right = new_entry;
122                 new_entry->parent = entry;
123 
124                 return new_entry;
125             }
126 
127             entry = entry->right;
128         }
129         else {
130             if (entry->left == NULL) {
131                 entry->left = new_entry;
132                 new_entry->parent = entry;
133 
134                 return new_entry;
135             }
136 
137             entry = entry->left;
138         }
139     }
140 
141     return NULL;
142 }
143 
144 lexbor_bst_entry_t *
lexbor_bst_insert_not_exists(lexbor_bst_t * bst,lexbor_bst_entry_t ** scope,size_t size)145 lexbor_bst_insert_not_exists(lexbor_bst_t *bst, lexbor_bst_entry_t **scope,
146                              size_t size)
147 {
148     lexbor_bst_entry_t *entry;
149 
150     if (*scope == NULL) {
151         *scope = lexbor_bst_entry_make(bst, size);
152 
153         return *scope;
154     }
155 
156     entry = *scope;
157 
158     while (entry != NULL) {
159         if (size == entry->size) {
160             return entry;
161         }
162         else if (size > entry->size) {
163             if (entry->right == NULL) {
164                 entry->right = lexbor_bst_entry_make(bst, size);
165                 entry->right->parent = entry;
166 
167                 return entry->right;
168             }
169 
170             entry = entry->right;
171         }
172         else {
173             if (entry->left == NULL) {
174                 entry->left = lexbor_bst_entry_make(bst, size);
175                 entry->left->parent = entry;
176 
177                 return entry->left;
178             }
179 
180             entry = entry->left;
181         }
182     }
183 
184     return NULL;
185 }
186 
187 lexbor_bst_entry_t *
lexbor_bst_search(lexbor_bst_t * bst,lexbor_bst_entry_t * scope,size_t size)188 lexbor_bst_search(lexbor_bst_t *bst, lexbor_bst_entry_t *scope, size_t size)
189 {
190     while (scope != NULL) {
191         if (scope->size == size) {
192             return scope;
193         }
194         else if (size > scope->size) {
195             scope = scope->right;
196         }
197         else {
198             scope = scope->left;
199         }
200     }
201 
202     return NULL;
203 }
204 
205 lexbor_bst_entry_t *
lexbor_bst_search_close(lexbor_bst_t * bst,lexbor_bst_entry_t * scope,size_t size)206 lexbor_bst_search_close(lexbor_bst_t *bst, lexbor_bst_entry_t *scope,
207                         size_t size)
208 {
209     lexbor_bst_entry_t *max = NULL;
210 
211     while (scope != NULL) {
212         if (scope->size == size) {
213             return scope;
214         }
215         else if (size > scope->size) {
216             scope = scope->right;
217         }
218         else {
219             max = scope;
220             scope = scope->left;
221         }
222     }
223 
224     return max;
225 }
226 
227 void *
lexbor_bst_remove(lexbor_bst_t * bst,lexbor_bst_entry_t ** scope,size_t size)228 lexbor_bst_remove(lexbor_bst_t *bst, lexbor_bst_entry_t **scope, size_t size)
229 {
230     lexbor_bst_entry_t *entry = *scope;
231 
232     while (entry != NULL) {
233         if (entry->size == size) {
234             return lexbor_bst_remove_by_pointer(bst, entry, scope);
235         }
236         else if (size > entry->size) {
237             entry = entry->right;
238         }
239         else {
240             entry = entry->left;
241         }
242     }
243 
244     return NULL;
245 }
246 
247 void *
lexbor_bst_remove_close(lexbor_bst_t * bst,lexbor_bst_entry_t ** scope,size_t size,size_t * found_size)248 lexbor_bst_remove_close(lexbor_bst_t *bst, lexbor_bst_entry_t **scope,
249                         size_t size, size_t *found_size)
250 {
251     lexbor_bst_entry_t *entry = *scope;
252     lexbor_bst_entry_t *max = NULL;
253 
254     while (entry != NULL) {
255         if (entry->size == size) {
256             if (found_size) {
257                 *found_size = entry->size;
258             }
259 
260             return lexbor_bst_remove_by_pointer(bst, entry, scope);
261         }
262         else if (size > entry->size) {
263             entry = entry->right;
264         }
265         else {
266             max = entry;
267             entry = entry->left;
268         }
269     }
270 
271     if (max != NULL) {
272         if (found_size != NULL) {
273             *found_size = max->size;
274         }
275 
276         return lexbor_bst_remove_by_pointer(bst, max, scope);
277     }
278 
279     if (found_size != NULL) {
280         *found_size = 0;
281     }
282 
283     return NULL;
284 }
285 
286 void *
lexbor_bst_remove_by_pointer(lexbor_bst_t * bst,lexbor_bst_entry_t * entry,lexbor_bst_entry_t ** root)287 lexbor_bst_remove_by_pointer(lexbor_bst_t *bst, lexbor_bst_entry_t *entry,
288                              lexbor_bst_entry_t **root)
289 {
290     void *value;
291     lexbor_bst_entry_t *next, *right, *left;
292 
293     bst->tree_length--;
294 
295     if (entry->next != NULL) {
296         next = entry->next;
297         entry->next = entry->next->next;
298 
299         value = next->value;
300 
301         lexbor_dobject_free(bst->dobject, next);
302 
303         return value;
304     }
305 
306     value = entry->value;
307 
308     if (entry->left == NULL && entry->right == NULL) {
309         if (entry->parent != NULL) {
310             if (entry->parent->left == entry)  entry->parent->left  = NULL;
311             if (entry->parent->right == entry) entry->parent->right = NULL;
312         }
313         else {
314             *root = NULL;
315         }
316 
317         lexbor_dobject_free(bst->dobject, entry);
318     }
319     else if (entry->left == NULL) {
320         if (entry->parent == NULL) {
321             entry->right->parent = NULL;
322 
323             *root = entry->right;
324 
325             lexbor_dobject_free(bst->dobject, entry);
326 
327             entry = *root;
328         }
329         else {
330             right = entry->right;
331             right->parent = entry->parent;
332 
333             memcpy(entry, right, sizeof(lexbor_bst_entry_t));
334 
335             lexbor_dobject_free(bst->dobject, right);
336         }
337 
338         if (entry->right != NULL) {
339             entry->right->parent = entry;
340         }
341 
342         if (entry->left != NULL) {
343             entry->left->parent = entry;
344         }
345     }
346     else if (entry->right == NULL) {
347         if (entry->parent == NULL) {
348             entry->left->parent = NULL;
349 
350             *root = entry->left;
351 
352             lexbor_dobject_free(bst->dobject, entry);
353 
354             entry = *root;
355         }
356         else {
357             left = entry->left;
358             left->parent = entry->parent;
359 
360             memcpy(entry, left, sizeof(lexbor_bst_entry_t));
361 
362             lexbor_dobject_free(bst->dobject, left);
363         }
364 
365         if (entry->right != NULL) {
366             entry->right->parent = entry;
367         }
368 
369         if (entry->left != NULL) {
370             entry->left->parent = entry;
371         }
372     }
373     else {
374         left = entry->right;
375 
376         while (left->left != NULL) {
377             left = left->left;
378         }
379 
380         /* Swap */
381         entry->size  = left->size;
382         entry->next  = left->next;
383         entry->value = left->value;
384 
385         /* Change parrent */
386         if (entry->right == left) {
387             entry->right = left->right;
388 
389             if (entry->right != NULL) {
390                 left->right->parent = entry;
391             }
392         }
393         else {
394             left->parent->left = left->right;
395 
396             if (left->right != NULL) {
397                 left->right->parent = left->parent;
398             }
399         }
400 
401         lexbor_dobject_free(bst->dobject, left);
402     }
403 
404     return value;
405 }
406 
407 void
lexbor_bst_serialize(lexbor_bst_t * bst,lexbor_callback_f callback,void * ctx)408 lexbor_bst_serialize(lexbor_bst_t *bst, lexbor_callback_f callback, void *ctx)
409 {
410     lexbor_bst_serialize_entry(bst->root, callback, ctx, 0);
411 }
412 
413 void
lexbor_bst_serialize_entry(lexbor_bst_entry_t * entry,lexbor_callback_f callback,void * ctx,size_t tabs)414 lexbor_bst_serialize_entry(lexbor_bst_entry_t *entry,
415                            lexbor_callback_f callback, void *ctx, size_t tabs)
416 {
417     size_t len;
418     lxb_char_t buff[1024];
419 
420     if (entry == NULL) {
421         return;
422     }
423 
424     /* Left */
425     for (size_t i = 0; i < tabs; i++) {
426         callback((lxb_char_t *) "\t", 1, ctx);
427     }
428     callback((lxb_char_t *) "<left ", 6, ctx);
429 
430     if (entry->left) {
431         len = lexbor_conv_int64_to_data((int64_t) entry->left->size,
432                                         buff, sizeof(buff));
433         callback(buff, len, ctx);
434 
435         callback((lxb_char_t *) ">\n", 2, ctx);
436         lexbor_bst_serialize_entry(entry->left, callback, ctx, (tabs + 1));
437 
438         for (size_t i = 0; i < tabs; i++) {
439             callback((lxb_char_t *) "\t", 1, ctx);
440         }
441     }
442     else {
443         callback((lxb_char_t *) "NULL>", 5, ctx);
444     }
445 
446     callback((lxb_char_t *) "</left>\n", 8, ctx);
447 
448     /* Right */
449     for (size_t i = 0; i < tabs; i++) {
450         callback((lxb_char_t *) "\t", 1, ctx);
451     }
452     callback((lxb_char_t *) "<right ", 7, ctx);
453 
454     if (entry->right) {
455         len = lexbor_conv_int64_to_data((int64_t) entry->right->size,
456                                         buff, sizeof(buff));
457         callback(buff, len, ctx);
458 
459         callback((lxb_char_t *) ">\n", 2, ctx);
460         lexbor_bst_serialize_entry(entry->right, callback, ctx, (tabs + 1));
461 
462         for (size_t i = 0; i < tabs; i++) {
463             callback((lxb_char_t *) "\t", 1, ctx);
464         }
465     }
466     else {
467         callback((lxb_char_t *) "NULL>", 5, ctx);
468     }
469 
470     callback((lxb_char_t *) "</right>\n", 9, ctx);
471 }
472