pavl.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /* Produced by texiweb from libavl.w. */
  2. /* libavl - library for manipulation of binary trees.
  3. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
  4. Foundation, Inc.
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 3 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. */
  18. /* Nov 2016, Markus Metz
  19. * from libavl-2.0.3
  20. * added safety checks and speed optimizations
  21. */
  22. #include <assert.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include "pavl.h"
  26. /* Creates and returns a new table
  27. with comparison function |compare| using parameter |param|
  28. and memory allocator |allocator|.
  29. Returns |NULL| if memory allocation failed. */
  30. struct pavl_table *pavl_create(pavl_comparison_func * compare,
  31. struct libavl_allocator *allocator)
  32. {
  33. struct pavl_table *tree;
  34. assert(compare != NULL);
  35. if (allocator == NULL)
  36. allocator = &pavl_allocator_default;
  37. tree = allocator->libavl_malloc(sizeof *tree);
  38. if (tree == NULL)
  39. return NULL;
  40. tree->pavl_root = NULL;
  41. tree->pavl_compare = compare;
  42. tree->pavl_alloc = allocator;
  43. tree->pavl_count = 0;
  44. return tree;
  45. }
  46. /* Search |tree| for an item matching |item|, and return it if found.
  47. Otherwise return |NULL|. */
  48. void *pavl_find(const struct pavl_table *tree, const void *item)
  49. {
  50. const struct pavl_node *p;
  51. assert(tree != NULL && item != NULL);
  52. p = tree->pavl_root;
  53. while (p != NULL) {
  54. int cmp = tree->pavl_compare(item, p->pavl_data);
  55. if (cmp == 0)
  56. return p->pavl_data;
  57. p = p->pavl_link[cmp > 0];
  58. }
  59. return NULL;
  60. }
  61. /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
  62. If a duplicate item is found in the tree,
  63. returns a pointer to the duplicate without inserting |item|.
  64. Returns |NULL| in case of memory allocation failure. */
  65. void **pavl_probe(struct pavl_table *tree, void *item)
  66. {
  67. struct pavl_node *y; /* Top node to update balance factor, and parent. */
  68. struct pavl_node *p, *q; /* Iterator, and parent. */
  69. struct pavl_node *n; /* Newly inserted node. */
  70. struct pavl_node *w; /* New root of rebalanced subtree. */
  71. int dir; /* Direction to descend. */
  72. assert(tree != NULL && item != NULL);
  73. y = p = tree->pavl_root;
  74. q = NULL;
  75. dir = 0;
  76. while (p != NULL) {
  77. int cmp = tree->pavl_compare(item, p->pavl_data);
  78. if (cmp == 0)
  79. return &p->pavl_data;
  80. dir = cmp > 0;
  81. if (p->pavl_balance != 0)
  82. y = p;
  83. q = p, p = p->pavl_link[dir];
  84. }
  85. n = tree->pavl_alloc->libavl_malloc(sizeof *p);
  86. if (n == NULL)
  87. return NULL;
  88. tree->pavl_count++;
  89. n->pavl_link[0] = n->pavl_link[1] = NULL;
  90. n->pavl_parent = q;
  91. n->pavl_data = item;
  92. n->pavl_balance = 0;
  93. if (q == NULL) {
  94. tree->pavl_root = n;
  95. return &n->pavl_data;
  96. }
  97. q->pavl_link[dir] = n;
  98. p = n;
  99. while (p != y) {
  100. q = p->pavl_parent;
  101. /*
  102. dir = q->pavl_link[0] != p;
  103. if (dir == 0)
  104. q->pavl_balance--;
  105. else
  106. q->pavl_balance++;
  107. */
  108. if (q->pavl_link[0] != p)
  109. q->pavl_balance++;
  110. else
  111. q->pavl_balance--;
  112. p = q;
  113. }
  114. if (y->pavl_balance == -2) {
  115. struct pavl_node *x = y->pavl_link[0];
  116. if (x->pavl_balance == -1) {
  117. w = x;
  118. y->pavl_link[0] = x->pavl_link[1];
  119. x->pavl_link[1] = y;
  120. x->pavl_balance = y->pavl_balance = 0;
  121. x->pavl_parent = y->pavl_parent;
  122. y->pavl_parent = x;
  123. if (y->pavl_link[0] != NULL)
  124. y->pavl_link[0]->pavl_parent = y;
  125. }
  126. else {
  127. assert(x->pavl_balance == +1);
  128. w = x->pavl_link[1];
  129. x->pavl_link[1] = w->pavl_link[0];
  130. w->pavl_link[0] = x;
  131. y->pavl_link[0] = w->pavl_link[1];
  132. w->pavl_link[1] = y;
  133. if (w->pavl_balance == -1)
  134. x->pavl_balance = 0, y->pavl_balance = +1;
  135. else if (w->pavl_balance == 0)
  136. x->pavl_balance = y->pavl_balance = 0;
  137. else /* |w->pavl_balance == +1| */
  138. x->pavl_balance = -1, y->pavl_balance = 0;
  139. w->pavl_balance = 0;
  140. w->pavl_parent = y->pavl_parent;
  141. x->pavl_parent = y->pavl_parent = w;
  142. if (x->pavl_link[1] != NULL)
  143. x->pavl_link[1]->pavl_parent = x;
  144. if (y->pavl_link[0] != NULL)
  145. y->pavl_link[0]->pavl_parent = y;
  146. }
  147. }
  148. else if (y->pavl_balance == +2) {
  149. struct pavl_node *x = y->pavl_link[1];
  150. if (x->pavl_balance == +1) {
  151. w = x;
  152. y->pavl_link[1] = x->pavl_link[0];
  153. x->pavl_link[0] = y;
  154. x->pavl_balance = y->pavl_balance = 0;
  155. x->pavl_parent = y->pavl_parent;
  156. y->pavl_parent = x;
  157. if (y->pavl_link[1] != NULL)
  158. y->pavl_link[1]->pavl_parent = y;
  159. }
  160. else {
  161. assert(x->pavl_balance == -1);
  162. w = x->pavl_link[0];
  163. x->pavl_link[0] = w->pavl_link[1];
  164. w->pavl_link[1] = x;
  165. y->pavl_link[1] = w->pavl_link[0];
  166. w->pavl_link[0] = y;
  167. if (w->pavl_balance == +1)
  168. x->pavl_balance = 0, y->pavl_balance = -1;
  169. else if (w->pavl_balance == 0)
  170. x->pavl_balance = y->pavl_balance = 0;
  171. else /* |w->pavl_balance == -1| */
  172. x->pavl_balance = +1, y->pavl_balance = 0;
  173. w->pavl_balance = 0;
  174. w->pavl_parent = y->pavl_parent;
  175. x->pavl_parent = y->pavl_parent = w;
  176. if (x->pavl_link[0] != NULL)
  177. x->pavl_link[0]->pavl_parent = x;
  178. if (y->pavl_link[1] != NULL)
  179. y->pavl_link[1]->pavl_parent = y;
  180. }
  181. }
  182. else
  183. return &n->pavl_data;
  184. if (w->pavl_parent != NULL)
  185. w->pavl_parent->pavl_link[y != w->pavl_parent->pavl_link[0]] = w;
  186. else
  187. tree->pavl_root = w;
  188. return &n->pavl_data;
  189. }
  190. /* Inserts |item| into |table|.
  191. Returns |NULL| if |item| was successfully inserted
  192. or if a memory allocation error occurred.
  193. Otherwise, returns the duplicate item. */
  194. void *pavl_insert(struct pavl_table *table, void *item)
  195. {
  196. void **p = pavl_probe(table, item);
  197. return p == NULL || *p == item ? NULL : *p;
  198. }
  199. /* Inserts |item| into |table|, replacing any duplicate item.
  200. Returns |NULL| if |item| was inserted without replacing a duplicate,
  201. or if a memory allocation error occurred.
  202. Otherwise, returns the item that was replaced. */
  203. void *pavl_replace(struct pavl_table *table, void *item)
  204. {
  205. void **p = pavl_probe(table, item);
  206. if (p == NULL || *p == item)
  207. return NULL;
  208. else {
  209. void *r = *p;
  210. *p = item;
  211. return r;
  212. }
  213. }
  214. /* Deletes from |tree| and returns an item matching |item|.
  215. Returns a null pointer if no matching item found. */
  216. void *pavl_delete(struct pavl_table *tree, const void *item)
  217. {
  218. struct pavl_node *p; /* Traverses tree to find node to delete. */
  219. struct pavl_node *q; /* Parent of |p|. */
  220. int dir; /* Side of |q| on which |p| is linked. */
  221. int cmp; /* Result of comparison between |item| and |p|. */
  222. assert(tree != NULL && item != NULL);
  223. p = tree->pavl_root;
  224. dir = 0;
  225. while (p != NULL) {
  226. cmp = tree->pavl_compare(item, p->pavl_data);
  227. if (cmp == 0)
  228. break;
  229. dir = cmp > 0;
  230. p = p->pavl_link[dir];
  231. }
  232. if (p == NULL)
  233. return NULL;
  234. item = p->pavl_data;
  235. q = p->pavl_parent;
  236. if (q == NULL) {
  237. q = (struct pavl_node *)&tree->pavl_root;
  238. dir = 0;
  239. }
  240. if (p->pavl_link[1] == NULL) {
  241. q->pavl_link[dir] = p->pavl_link[0];
  242. if (q->pavl_link[dir] != NULL)
  243. q->pavl_link[dir]->pavl_parent = p->pavl_parent;
  244. }
  245. else {
  246. struct pavl_node *r = p->pavl_link[1];
  247. if (r->pavl_link[0] == NULL) {
  248. r->pavl_link[0] = p->pavl_link[0];
  249. q->pavl_link[dir] = r;
  250. r->pavl_parent = p->pavl_parent;
  251. if (r->pavl_link[0] != NULL)
  252. r->pavl_link[0]->pavl_parent = r;
  253. r->pavl_balance = p->pavl_balance;
  254. q = r;
  255. dir = 1;
  256. }
  257. else {
  258. struct pavl_node *s = r->pavl_link[0];
  259. while (s->pavl_link[0] != NULL)
  260. s = s->pavl_link[0];
  261. r = s->pavl_parent;
  262. r->pavl_link[0] = s->pavl_link[1];
  263. s->pavl_link[0] = p->pavl_link[0];
  264. s->pavl_link[1] = p->pavl_link[1];
  265. q->pavl_link[dir] = s;
  266. if (s->pavl_link[0] != NULL)
  267. s->pavl_link[0]->pavl_parent = s;
  268. s->pavl_link[1]->pavl_parent = s;
  269. s->pavl_parent = p->pavl_parent;
  270. if (r->pavl_link[0] != NULL)
  271. r->pavl_link[0]->pavl_parent = r;
  272. s->pavl_balance = p->pavl_balance;
  273. q = r;
  274. dir = 0;
  275. }
  276. }
  277. tree->pavl_alloc->libavl_free(p);
  278. while (q != (struct pavl_node *)&tree->pavl_root) {
  279. struct pavl_node *y = q;
  280. if (y->pavl_parent != NULL)
  281. q = y->pavl_parent;
  282. else
  283. q = (struct pavl_node *)&tree->pavl_root;
  284. if (dir == 0) {
  285. dir = q->pavl_link[0] != y;
  286. y->pavl_balance++;
  287. if (y->pavl_balance == +1)
  288. break;
  289. else if (y->pavl_balance == +2) {
  290. struct pavl_node *x = y->pavl_link[1];
  291. if (x->pavl_balance == -1) {
  292. struct pavl_node *w;
  293. assert(x->pavl_balance == -1);
  294. w = x->pavl_link[0];
  295. x->pavl_link[0] = w->pavl_link[1];
  296. w->pavl_link[1] = x;
  297. y->pavl_link[1] = w->pavl_link[0];
  298. w->pavl_link[0] = y;
  299. if (w->pavl_balance == +1)
  300. x->pavl_balance = 0, y->pavl_balance = -1;
  301. else if (w->pavl_balance == 0)
  302. x->pavl_balance = y->pavl_balance = 0;
  303. else /* |w->pavl_balance == -1| */
  304. x->pavl_balance = +1, y->pavl_balance = 0;
  305. w->pavl_balance = 0;
  306. w->pavl_parent = y->pavl_parent;
  307. x->pavl_parent = y->pavl_parent = w;
  308. if (x->pavl_link[0] != NULL)
  309. x->pavl_link[0]->pavl_parent = x;
  310. if (y->pavl_link[1] != NULL)
  311. y->pavl_link[1]->pavl_parent = y;
  312. q->pavl_link[dir] = w;
  313. }
  314. else {
  315. y->pavl_link[1] = x->pavl_link[0];
  316. x->pavl_link[0] = y;
  317. x->pavl_parent = y->pavl_parent;
  318. y->pavl_parent = x;
  319. if (y->pavl_link[1] != NULL)
  320. y->pavl_link[1]->pavl_parent = y;
  321. q->pavl_link[dir] = x;
  322. if (x->pavl_balance == 0) {
  323. x->pavl_balance = -1;
  324. y->pavl_balance = +1;
  325. break;
  326. }
  327. else {
  328. x->pavl_balance = y->pavl_balance = 0;
  329. y = x;
  330. }
  331. }
  332. }
  333. }
  334. else {
  335. dir = q->pavl_link[0] != y;
  336. y->pavl_balance--;
  337. if (y->pavl_balance == -1)
  338. break;
  339. else if (y->pavl_balance == -2) {
  340. struct pavl_node *x = y->pavl_link[0];
  341. if (x->pavl_balance == +1) {
  342. struct pavl_node *w;
  343. assert(x->pavl_balance == +1);
  344. w = x->pavl_link[1];
  345. x->pavl_link[1] = w->pavl_link[0];
  346. w->pavl_link[0] = x;
  347. y->pavl_link[0] = w->pavl_link[1];
  348. w->pavl_link[1] = y;
  349. if (w->pavl_balance == -1)
  350. x->pavl_balance = 0, y->pavl_balance = +1;
  351. else if (w->pavl_balance == 0)
  352. x->pavl_balance = y->pavl_balance = 0;
  353. else /* |w->pavl_balance == +1| */
  354. x->pavl_balance = -1, y->pavl_balance = 0;
  355. w->pavl_balance = 0;
  356. w->pavl_parent = y->pavl_parent;
  357. x->pavl_parent = y->pavl_parent = w;
  358. if (x->pavl_link[1] != NULL)
  359. x->pavl_link[1]->pavl_parent = x;
  360. if (y->pavl_link[0] != NULL)
  361. y->pavl_link[0]->pavl_parent = y;
  362. q->pavl_link[dir] = w;
  363. }
  364. else {
  365. y->pavl_link[0] = x->pavl_link[1];
  366. x->pavl_link[1] = y;
  367. x->pavl_parent = y->pavl_parent;
  368. y->pavl_parent = x;
  369. if (y->pavl_link[0] != NULL)
  370. y->pavl_link[0]->pavl_parent = y;
  371. q->pavl_link[dir] = x;
  372. if (x->pavl_balance == 0) {
  373. x->pavl_balance = +1;
  374. y->pavl_balance = -1;
  375. break;
  376. }
  377. else {
  378. x->pavl_balance = y->pavl_balance = 0;
  379. y = x;
  380. }
  381. }
  382. }
  383. }
  384. }
  385. tree->pavl_count--;
  386. return (void *)item;
  387. }
  388. /* Initializes |trav| for use with |tree|
  389. and selects the null node. */
  390. void pavl_t_init(struct pavl_traverser *trav, struct pavl_table *tree)
  391. {
  392. trav->pavl_table = tree;
  393. trav->pavl_node = NULL;
  394. }
  395. /* Initializes |trav| for |tree|.
  396. Returns data item in |tree| with the least value,
  397. or |NULL| if |tree| is empty. */
  398. void *pavl_t_first(struct pavl_traverser *trav, struct pavl_table *tree)
  399. {
  400. assert(tree != NULL && trav != NULL);
  401. trav->pavl_table = tree;
  402. trav->pavl_node = tree->pavl_root;
  403. if (trav->pavl_node != NULL) {
  404. while (trav->pavl_node->pavl_link[0] != NULL)
  405. trav->pavl_node = trav->pavl_node->pavl_link[0];
  406. return trav->pavl_node->pavl_data;
  407. }
  408. else
  409. return NULL;
  410. }
  411. /* Initializes |trav| for |tree|.
  412. Returns data item in |tree| with the greatest value,
  413. or |NULL| if |tree| is empty. */
  414. void *pavl_t_last(struct pavl_traverser *trav, struct pavl_table *tree)
  415. {
  416. assert(tree != NULL && trav != NULL);
  417. trav->pavl_table = tree;
  418. trav->pavl_node = tree->pavl_root;
  419. if (trav->pavl_node != NULL) {
  420. while (trav->pavl_node->pavl_link[1] != NULL)
  421. trav->pavl_node = trav->pavl_node->pavl_link[1];
  422. return trav->pavl_node->pavl_data;
  423. }
  424. else
  425. return NULL;
  426. }
  427. /* Searches for |item| in |tree|.
  428. If found, initializes |trav| to the item found and returns the item
  429. as well.
  430. If there is no matching item, initializes |trav| to the null item
  431. and returns |NULL|. */
  432. void *pavl_t_find(struct pavl_traverser *trav, struct pavl_table *tree,
  433. void *item)
  434. {
  435. struct pavl_node *p;
  436. assert(trav != NULL && tree != NULL && item != NULL);
  437. trav->pavl_table = tree;
  438. p = tree->pavl_root;
  439. while (p != NULL) {
  440. int cmp = tree->pavl_compare(item, p->pavl_data);
  441. if (cmp == 0) {
  442. trav->pavl_node = p;
  443. return p->pavl_data;
  444. }
  445. p = p->pavl_link[cmp > 0];
  446. }
  447. trav->pavl_node = NULL;
  448. return NULL;
  449. }
  450. /* Attempts to insert |item| into |tree|.
  451. If |item| is inserted successfully, it is returned and |trav| is
  452. initialized to its location.
  453. If a duplicate is found, it is returned and |trav| is initialized to
  454. its location. No replacement of the item occurs.
  455. If a memory allocation failure occurs, |NULL| is returned and |trav|
  456. is initialized to the null item. */
  457. void *pavl_t_insert(struct pavl_traverser *trav,
  458. struct pavl_table *tree, void *item)
  459. {
  460. void **p;
  461. assert(trav != NULL && tree != NULL && item != NULL);
  462. p = pavl_probe(tree, item);
  463. if (p != NULL) {
  464. trav->pavl_table = tree;
  465. trav->pavl_node = ((struct pavl_node *)((char *)p -
  466. offsetof(struct pavl_node,
  467. pavl_data)));
  468. return *p;
  469. }
  470. else {
  471. pavl_t_init(trav, tree);
  472. return NULL;
  473. }
  474. }
  475. /* Initializes |trav| to have the same current node as |src|. */
  476. void *pavl_t_copy(struct pavl_traverser *trav,
  477. const struct pavl_traverser *src)
  478. {
  479. assert(trav != NULL && src != NULL);
  480. trav->pavl_table = src->pavl_table;
  481. trav->pavl_node = src->pavl_node;
  482. return trav->pavl_node != NULL ? trav->pavl_node->pavl_data : NULL;
  483. }
  484. /* Returns the next data item in inorder
  485. within the tree being traversed with |trav|,
  486. or if there are no more data items returns |NULL|. */
  487. void *pavl_t_next(struct pavl_traverser *trav)
  488. {
  489. assert(trav != NULL);
  490. if (trav->pavl_node == NULL)
  491. return pavl_t_first(trav, trav->pavl_table);
  492. else if (trav->pavl_node->pavl_link[1] == NULL) {
  493. struct pavl_node *q, *p; /* Current node and its child. */
  494. for (p = trav->pavl_node, q = p->pavl_parent;;
  495. p = q, q = q->pavl_parent)
  496. if (q == NULL || p == q->pavl_link[0]) {
  497. trav->pavl_node = q;
  498. return trav->pavl_node != NULL ?
  499. trav->pavl_node->pavl_data : NULL;
  500. }
  501. }
  502. else {
  503. trav->pavl_node = trav->pavl_node->pavl_link[1];
  504. while (trav->pavl_node->pavl_link[0] != NULL)
  505. trav->pavl_node = trav->pavl_node->pavl_link[0];
  506. return trav->pavl_node->pavl_data;
  507. }
  508. }
  509. /* Returns the previous data item in inorder
  510. within the tree being traversed with |trav|,
  511. or if there are no more data items returns |NULL|. */
  512. void *pavl_t_prev(struct pavl_traverser *trav)
  513. {
  514. assert(trav != NULL);
  515. if (trav->pavl_node == NULL)
  516. return pavl_t_last(trav, trav->pavl_table);
  517. else if (trav->pavl_node->pavl_link[0] == NULL) {
  518. struct pavl_node *q, *p; /* Current node and its child. */
  519. for (p = trav->pavl_node, q = p->pavl_parent;;
  520. p = q, q = q->pavl_parent)
  521. if (q == NULL || p == q->pavl_link[1]) {
  522. trav->pavl_node = q;
  523. return trav->pavl_node != NULL ?
  524. trav->pavl_node->pavl_data : NULL;
  525. }
  526. }
  527. else {
  528. trav->pavl_node = trav->pavl_node->pavl_link[0];
  529. while (trav->pavl_node->pavl_link[1] != NULL)
  530. trav->pavl_node = trav->pavl_node->pavl_link[1];
  531. return trav->pavl_node->pavl_data;
  532. }
  533. }
  534. /* Returns |trav|'s current item. */
  535. void *pavl_t_cur(struct pavl_traverser *trav)
  536. {
  537. assert(trav != NULL);
  538. return trav->pavl_node != NULL ? trav->pavl_node->pavl_data : NULL;
  539. }
  540. /* Replaces the current item in |trav| by |new| and returns the item replaced.
  541. |trav| must not have the null item selected.
  542. The new item must not upset the ordering of the tree. */
  543. void *pavl_t_replace(struct pavl_traverser *trav, void *new)
  544. {
  545. void *old;
  546. assert(trav != NULL && trav->pavl_node != NULL && new != NULL);
  547. old = trav->pavl_node->pavl_data;
  548. trav->pavl_node->pavl_data = new;
  549. return old;
  550. }
  551. /* Destroys |new| with |pavl_destroy (new, destroy)|,
  552. first initializing right links in |new| that have
  553. not yet been initialized at time of call. */
  554. static void
  555. copy_error_recovery(struct pavl_node *q,
  556. struct pavl_table *new, pavl_item_func * destroy)
  557. {
  558. assert(q != NULL && new != NULL);
  559. for (;;) {
  560. struct pavl_node *p = q;
  561. q = q->pavl_parent;
  562. if (q == NULL)
  563. break;
  564. if (p == q->pavl_link[0])
  565. q->pavl_link[1] = NULL;
  566. }
  567. pavl_destroy(new, destroy);
  568. }
  569. /* Copies |org| to a newly created tree, which is returned.
  570. If |copy != NULL|, each data item in |org| is first passed to |copy|,
  571. and the return values are inserted into the tree;
  572. |NULL| return values are taken as indications of failure.
  573. On failure, destroys the partially created new tree,
  574. applying |destroy|, if non-null, to each item in the new tree so far,
  575. and returns |NULL|.
  576. If |allocator != NULL|, it is used for allocation in the new tree.
  577. Otherwise, the same allocator used for |org| is used. */
  578. struct pavl_table *pavl_copy(const struct pavl_table *org,
  579. pavl_copy_func * copy, pavl_item_func * destroy,
  580. struct libavl_allocator *allocator)
  581. {
  582. struct pavl_table *new;
  583. const struct pavl_node *x;
  584. struct pavl_node *y;
  585. assert(org != NULL);
  586. new = pavl_create(org->pavl_compare,
  587. allocator != NULL ? allocator : org->pavl_alloc);
  588. if (new == NULL)
  589. return NULL;
  590. new->pavl_count = org->pavl_count;
  591. if (new->pavl_count == 0)
  592. return new;
  593. x = (const struct pavl_node *)&org->pavl_root;
  594. y = (struct pavl_node *)&new->pavl_root;
  595. while (x != NULL) {
  596. while (x->pavl_link[0] != NULL) {
  597. y->pavl_link[0] =
  598. new->pavl_alloc->libavl_malloc(sizeof *y->pavl_link[0]);
  599. if (y->pavl_link[0] == NULL) {
  600. if (y != (struct pavl_node *)&new->pavl_root) {
  601. y->pavl_data = NULL;
  602. y->pavl_link[1] = NULL;
  603. }
  604. copy_error_recovery(y, new, destroy);
  605. return NULL;
  606. }
  607. y->pavl_link[0]->pavl_parent = y;
  608. x = x->pavl_link[0];
  609. y = y->pavl_link[0];
  610. }
  611. y->pavl_link[0] = NULL;
  612. for (;;) {
  613. y->pavl_balance = x->pavl_balance;
  614. if (copy == NULL)
  615. y->pavl_data = x->pavl_data;
  616. else {
  617. y->pavl_data = copy(x->pavl_data);
  618. if (y->pavl_data == NULL) {
  619. y->pavl_link[1] = NULL;
  620. copy_error_recovery(y, new, destroy);
  621. return NULL;
  622. }
  623. }
  624. if (x->pavl_link[1] != NULL) {
  625. y->pavl_link[1] =
  626. new->pavl_alloc->libavl_malloc(sizeof *y->pavl_link[1]);
  627. if (y->pavl_link[1] == NULL) {
  628. copy_error_recovery(y, new, destroy);
  629. return NULL;
  630. }
  631. y->pavl_link[1]->pavl_parent = y;
  632. x = x->pavl_link[1];
  633. y = y->pavl_link[1];
  634. break;
  635. }
  636. else
  637. y->pavl_link[1] = NULL;
  638. for (;;) {
  639. const struct pavl_node *w = x;
  640. x = x->pavl_parent;
  641. if (x == NULL) {
  642. new->pavl_root->pavl_parent = NULL;
  643. return new;
  644. }
  645. y = y->pavl_parent;
  646. if (w == x->pavl_link[0])
  647. break;
  648. }
  649. }
  650. }
  651. return new;
  652. }
  653. /* Frees storage allocated for |tree|.
  654. If |destroy != NULL|, applies it to each data item in inorder. */
  655. void pavl_destroy(struct pavl_table *tree, pavl_item_func * destroy)
  656. {
  657. struct pavl_node *p, *q;
  658. assert(tree != NULL);
  659. p = tree->pavl_root;
  660. while (p != NULL) {
  661. if (p->pavl_link[0] == NULL) {
  662. q = p->pavl_link[1];
  663. if (destroy != NULL && p->pavl_data != NULL)
  664. destroy(p->pavl_data);
  665. tree->pavl_alloc->libavl_free(p);
  666. }
  667. else {
  668. q = p->pavl_link[0];
  669. p->pavl_link[0] = q->pavl_link[1];
  670. q->pavl_link[1] = p;
  671. }
  672. p = q;
  673. }
  674. tree->pavl_alloc->libavl_free(tree);
  675. }
  676. /* Allocates |size| bytes of space using |malloc()|.
  677. Returns a null pointer if allocation fails. */
  678. void *pavl_malloc(size_t size)
  679. {
  680. if (size > 0)
  681. return malloc(size);
  682. return NULL;
  683. }
  684. /* Frees |block|. */
  685. void pavl_free(void *block)
  686. {
  687. if (block)
  688. free(block);
  689. }
  690. /* Default memory allocator that uses |malloc()| and |free()|. */
  691. struct libavl_allocator pavl_allocator_default = {
  692. pavl_malloc,
  693. pavl_free
  694. };
  695. #undef NDEBUG
  696. #include <assert.h>
  697. /* Asserts that |pavl_insert()| succeeds at inserting |item| into |table|. */
  698. void (pavl_assert_insert) (struct pavl_table * table, void *item)
  699. {
  700. void **p = pavl_probe(table, item);
  701. assert(p != NULL && *p == item);
  702. }
  703. /* Asserts that |pavl_delete()| really removes |item| from |table|,
  704. and returns the removed item. */
  705. void *(pavl_assert_delete) (struct pavl_table * table, void *item)
  706. {
  707. void *p = pavl_delete(table, item);
  708. assert(p != NULL);
  709. return p;
  710. }