tavl.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  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 "tavl.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 tavl_table *tavl_create(tavl_comparison_func * compare, void *param,
  31. struct libavl_allocator *allocator)
  32. {
  33. struct tavl_table *tree;
  34. assert(compare != NULL);
  35. if (allocator == NULL)
  36. allocator = &tavl_allocator_default;
  37. tree = allocator->libavl_malloc(allocator, sizeof *tree);
  38. if (tree == NULL)
  39. return NULL;
  40. tree->tavl_root = NULL;
  41. tree->tavl_compare = compare;
  42. tree->tavl_param = param;
  43. tree->tavl_alloc = allocator;
  44. tree->tavl_count = 0;
  45. return tree;
  46. }
  47. /* Search |tree| for an item matching |item|, and return it if found.
  48. Otherwise return |NULL|. */
  49. void *tavl_find(const struct tavl_table *tree, const void *item)
  50. {
  51. const struct tavl_node *p;
  52. assert(tree != NULL && item != NULL);
  53. p = tree->tavl_root;
  54. while (p != NULL) {
  55. int cmp, dir;
  56. cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  57. if (cmp == 0)
  58. return p->tavl_data;
  59. dir = cmp > 0;
  60. if (p->tavl_tag[dir] == TAVL_CHILD)
  61. p = p->tavl_link[dir];
  62. else
  63. p = NULL;
  64. }
  65. return NULL;
  66. }
  67. /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
  68. If a duplicate item is found in the tree,
  69. returns a pointer to the duplicate without inserting |item|.
  70. Returns |NULL| in case of memory allocation failure. */
  71. void **tavl_probe(struct tavl_table *tree, void *item)
  72. {
  73. struct tavl_node *y, *z; /* Top node to update balance factor, and parent. */
  74. struct tavl_node *p, *q; /* Iterator, and parent. */
  75. struct tavl_node *n; /* Newly inserted node. */
  76. struct tavl_node *w; /* New root of rebalanced subtree. */
  77. int dir; /* Direction to descend. */
  78. unsigned char da[TAVL_MAX_HEIGHT]; /* Cached comparison results. */
  79. int k = 0; /* Number of cached results. */
  80. assert(tree != NULL && item != NULL);
  81. z = (struct tavl_node *)&tree->tavl_root;
  82. y = tree->tavl_root;
  83. dir = 0;
  84. q = z, p = y;
  85. while (p != NULL) {
  86. int cmp =
  87. tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  88. if (cmp == 0)
  89. return &p->tavl_data;
  90. if (p->tavl_balance != 0)
  91. z = q, y = p, k = 0;
  92. da[k++] = dir = cmp > 0;
  93. if (p->tavl_tag[dir] == TAVL_THREAD)
  94. break;
  95. q = p, p = p->tavl_link[dir];
  96. }
  97. n = tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *n);
  98. if (n == NULL)
  99. return NULL;
  100. tree->tavl_count++;
  101. n->tavl_data = item;
  102. n->tavl_tag[0] = n->tavl_tag[1] = TAVL_THREAD;
  103. n->tavl_balance = 0;
  104. if (y == NULL) {
  105. n->tavl_link[0] = n->tavl_link[1] = NULL;
  106. tree->tavl_root = n;
  107. return &n->tavl_data;
  108. }
  109. n->tavl_link[dir] = p->tavl_link[dir];
  110. n->tavl_link[!dir] = p;
  111. p->tavl_tag[dir] = TAVL_CHILD;
  112. p->tavl_link[dir] = n;
  113. p = y, k = 0;
  114. while (p != n) {
  115. if (da[k] == 0)
  116. p->tavl_balance--;
  117. else
  118. p->tavl_balance++;
  119. p = p->tavl_link[da[k]], k++;
  120. }
  121. if (y->tavl_balance == -2) {
  122. struct tavl_node *x = y->tavl_link[0];
  123. if (x->tavl_balance == -1) {
  124. w = x;
  125. if (x->tavl_tag[1] == TAVL_THREAD) {
  126. x->tavl_tag[1] = TAVL_CHILD;
  127. y->tavl_tag[0] = TAVL_THREAD;
  128. y->tavl_link[0] = x;
  129. }
  130. else
  131. y->tavl_link[0] = x->tavl_link[1];
  132. x->tavl_link[1] = y;
  133. x->tavl_balance = y->tavl_balance = 0;
  134. }
  135. else {
  136. assert(x->tavl_balance == +1);
  137. w = x->tavl_link[1];
  138. x->tavl_link[1] = w->tavl_link[0];
  139. w->tavl_link[0] = x;
  140. y->tavl_link[0] = w->tavl_link[1];
  141. w->tavl_link[1] = y;
  142. if (w->tavl_balance == -1)
  143. x->tavl_balance = 0, y->tavl_balance = +1;
  144. else if (w->tavl_balance == 0)
  145. x->tavl_balance = y->tavl_balance = 0;
  146. else /* |w->tavl_balance == +1| */
  147. x->tavl_balance = -1, y->tavl_balance = 0;
  148. w->tavl_balance = 0;
  149. if (w->tavl_tag[0] == TAVL_THREAD) {
  150. x->tavl_tag[1] = TAVL_THREAD;
  151. x->tavl_link[1] = w;
  152. w->tavl_tag[0] = TAVL_CHILD;
  153. }
  154. if (w->tavl_tag[1] == TAVL_THREAD) {
  155. y->tavl_tag[0] = TAVL_THREAD;
  156. y->tavl_link[0] = w;
  157. w->tavl_tag[1] = TAVL_CHILD;
  158. }
  159. }
  160. }
  161. else if (y->tavl_balance == +2) {
  162. struct tavl_node *x = y->tavl_link[1];
  163. if (x->tavl_balance == +1) {
  164. w = x;
  165. if (x->tavl_tag[0] == TAVL_THREAD) {
  166. x->tavl_tag[0] = TAVL_CHILD;
  167. y->tavl_tag[1] = TAVL_THREAD;
  168. y->tavl_link[1] = x;
  169. }
  170. else
  171. y->tavl_link[1] = x->tavl_link[0];
  172. x->tavl_link[0] = y;
  173. x->tavl_balance = y->tavl_balance = 0;
  174. }
  175. else {
  176. assert(x->tavl_balance == -1);
  177. w = x->tavl_link[0];
  178. x->tavl_link[0] = w->tavl_link[1];
  179. w->tavl_link[1] = x;
  180. y->tavl_link[1] = w->tavl_link[0];
  181. w->tavl_link[0] = y;
  182. if (w->tavl_balance == +1)
  183. x->tavl_balance = 0, y->tavl_balance = -1;
  184. else if (w->tavl_balance == 0)
  185. x->tavl_balance = y->tavl_balance = 0;
  186. else /* |w->tavl_balance == -1| */
  187. x->tavl_balance = +1, y->tavl_balance = 0;
  188. w->tavl_balance = 0;
  189. if (w->tavl_tag[0] == TAVL_THREAD) {
  190. y->tavl_tag[1] = TAVL_THREAD;
  191. y->tavl_link[1] = w;
  192. w->tavl_tag[0] = TAVL_CHILD;
  193. }
  194. if (w->tavl_tag[1] == TAVL_THREAD) {
  195. x->tavl_tag[0] = TAVL_THREAD;
  196. x->tavl_link[0] = w;
  197. w->tavl_tag[1] = TAVL_CHILD;
  198. }
  199. }
  200. }
  201. else
  202. return &n->tavl_data;
  203. z->tavl_link[y != z->tavl_link[0]] = w;
  204. return &n->tavl_data;
  205. }
  206. /* Inserts |item| into |table|.
  207. Returns |NULL| if |item| was successfully inserted
  208. or if a memory allocation error occurred.
  209. Otherwise, returns the duplicate item. */
  210. void *tavl_insert(struct tavl_table *table, void *item)
  211. {
  212. void **p = tavl_probe(table, item);
  213. return p == NULL || *p == item ? NULL : *p;
  214. }
  215. /* Inserts |item| into |table|, replacing any duplicate item.
  216. Returns |NULL| if |item| was inserted without replacing a duplicate,
  217. or if a memory allocation error occurred.
  218. Otherwise, returns the item that was replaced. */
  219. void *tavl_replace(struct tavl_table *table, void *item)
  220. {
  221. void **p = tavl_probe(table, item);
  222. if (p == NULL || *p == item)
  223. return NULL;
  224. else {
  225. void *r = *p;
  226. *p = item;
  227. return r;
  228. }
  229. }
  230. /* Returns the parent of |node| within |tree|,
  231. or a pointer to |tavl_root| if |s| is the root of the tree. */
  232. static struct tavl_node *find_parent(struct tavl_table *tree,
  233. struct tavl_node *node)
  234. {
  235. if (node != tree->tavl_root) {
  236. struct tavl_node *x, *y;
  237. for (x = y = node;; x = x->tavl_link[0], y = y->tavl_link[1])
  238. if (y->tavl_tag[1] == TAVL_THREAD) {
  239. struct tavl_node *p = y->tavl_link[1];
  240. if (p == NULL || p->tavl_link[0] != node) {
  241. while (x->tavl_tag[0] == TAVL_CHILD)
  242. x = x->tavl_link[0];
  243. p = x->tavl_link[0];
  244. }
  245. return p;
  246. }
  247. else if (x->tavl_tag[0] == TAVL_THREAD) {
  248. struct tavl_node *p = x->tavl_link[0];
  249. if (p == NULL || p->tavl_link[1] != node) {
  250. while (y->tavl_tag[1] == TAVL_CHILD)
  251. y = y->tavl_link[1];
  252. p = y->tavl_link[1];
  253. }
  254. return p;
  255. }
  256. }
  257. else
  258. return (struct tavl_node *)&tree->tavl_root;
  259. }
  260. /* Deletes from |tree| and returns an item matching |item|.
  261. Returns a null pointer if no matching item found. */
  262. void *tavl_delete(struct tavl_table *tree, const void *item)
  263. {
  264. struct tavl_node *p; /* Traverses tree to find node to delete. */
  265. struct tavl_node *q; /* Parent of |p|. */
  266. int dir; /* Index into |q->tavl_link[]| to get |p|. */
  267. int cmp; /* Result of comparison between |item| and |p|. */
  268. assert(tree != NULL && item != NULL);
  269. q = (struct tavl_node *)&tree->tavl_root;
  270. p = tree->tavl_root;
  271. dir = 0;
  272. while (p != NULL) {
  273. cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  274. if (cmp == 0)
  275. break;
  276. dir = cmp > 0;
  277. q = p;
  278. if (p->tavl_tag[dir] == TAVL_CHILD)
  279. p = p->tavl_link[dir];
  280. else
  281. p = NULL;
  282. }
  283. if (p == NULL)
  284. return NULL;
  285. item = p->tavl_data;
  286. if (p->tavl_tag[1] == TAVL_THREAD) {
  287. if (p->tavl_tag[0] == TAVL_CHILD) {
  288. struct tavl_node *t = p->tavl_link[0];
  289. while (t->tavl_tag[1] == TAVL_CHILD)
  290. t = t->tavl_link[1];
  291. t->tavl_link[1] = p->tavl_link[1];
  292. q->tavl_link[dir] = p->tavl_link[0];
  293. }
  294. else {
  295. q->tavl_link[dir] = p->tavl_link[dir];
  296. if (q != (struct tavl_node *)&tree->tavl_root)
  297. q->tavl_tag[dir] = TAVL_THREAD;
  298. }
  299. }
  300. else {
  301. struct tavl_node *r = p->tavl_link[1];
  302. if (r->tavl_tag[0] == TAVL_THREAD) {
  303. r->tavl_link[0] = p->tavl_link[0];
  304. r->tavl_tag[0] = p->tavl_tag[0];
  305. if (r->tavl_tag[0] == TAVL_CHILD) {
  306. struct tavl_node *t = r->tavl_link[0];
  307. while (t->tavl_tag[1] == TAVL_CHILD)
  308. t = t->tavl_link[1];
  309. t->tavl_link[1] = r;
  310. }
  311. q->tavl_link[dir] = r;
  312. r->tavl_balance = p->tavl_balance;
  313. q = r;
  314. dir = 1;
  315. }
  316. else {
  317. struct tavl_node *s;
  318. while (r != NULL) {
  319. s = r->tavl_link[0];
  320. if (s->tavl_tag[0] == TAVL_THREAD)
  321. break;
  322. r = s;
  323. }
  324. if (s->tavl_tag[1] == TAVL_CHILD)
  325. r->tavl_link[0] = s->tavl_link[1];
  326. else {
  327. r->tavl_link[0] = s;
  328. r->tavl_tag[0] = TAVL_THREAD;
  329. }
  330. s->tavl_link[0] = p->tavl_link[0];
  331. if (p->tavl_tag[0] == TAVL_CHILD) {
  332. struct tavl_node *t = p->tavl_link[0];
  333. while (t->tavl_tag[1] == TAVL_CHILD)
  334. t = t->tavl_link[1];
  335. t->tavl_link[1] = s;
  336. s->tavl_tag[0] = TAVL_CHILD;
  337. }
  338. s->tavl_link[1] = p->tavl_link[1];
  339. s->tavl_tag[1] = TAVL_CHILD;
  340. q->tavl_link[dir] = s;
  341. s->tavl_balance = p->tavl_balance;
  342. q = r;
  343. dir = 0;
  344. }
  345. }
  346. tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
  347. while (q != (struct tavl_node *)&tree->tavl_root) {
  348. struct tavl_node *y = q;
  349. q = find_parent(tree, y);
  350. if (dir == 0) {
  351. dir = q->tavl_link[0] != y;
  352. y->tavl_balance++;
  353. if (y->tavl_balance == +1)
  354. break;
  355. else if (y->tavl_balance == +2) {
  356. struct tavl_node *x = y->tavl_link[1];
  357. assert(x != NULL);
  358. if (x->tavl_balance == -1) {
  359. struct tavl_node *w;
  360. assert(x->tavl_balance == -1);
  361. w = x->tavl_link[0];
  362. x->tavl_link[0] = w->tavl_link[1];
  363. w->tavl_link[1] = x;
  364. y->tavl_link[1] = w->tavl_link[0];
  365. w->tavl_link[0] = y;
  366. if (w->tavl_balance == +1)
  367. x->tavl_balance = 0, y->tavl_balance = -1;
  368. else if (w->tavl_balance == 0)
  369. x->tavl_balance = y->tavl_balance = 0;
  370. else /* |w->tavl_balance == -1| */
  371. x->tavl_balance = +1, y->tavl_balance = 0;
  372. w->tavl_balance = 0;
  373. if (w->tavl_tag[0] == TAVL_THREAD) {
  374. y->tavl_tag[1] = TAVL_THREAD;
  375. y->tavl_link[1] = w;
  376. w->tavl_tag[0] = TAVL_CHILD;
  377. }
  378. if (w->tavl_tag[1] == TAVL_THREAD) {
  379. x->tavl_tag[0] = TAVL_THREAD;
  380. x->tavl_link[0] = w;
  381. w->tavl_tag[1] = TAVL_CHILD;
  382. }
  383. q->tavl_link[dir] = w;
  384. }
  385. else {
  386. q->tavl_link[dir] = x;
  387. if (x->tavl_balance == 0) {
  388. y->tavl_link[1] = x->tavl_link[0];
  389. x->tavl_link[0] = y;
  390. x->tavl_balance = -1;
  391. y->tavl_balance = +1;
  392. break;
  393. }
  394. else { /* |x->tavl_balance == +1| */
  395. if (x->tavl_tag[0] == TAVL_CHILD)
  396. y->tavl_link[1] = x->tavl_link[0];
  397. else {
  398. y->tavl_tag[1] = TAVL_THREAD;
  399. x->tavl_tag[0] = TAVL_CHILD;
  400. }
  401. x->tavl_link[0] = y;
  402. y->tavl_balance = x->tavl_balance = 0;
  403. }
  404. }
  405. }
  406. }
  407. else {
  408. dir = q->tavl_link[0] != y;
  409. y->tavl_balance--;
  410. if (y->tavl_balance == -1)
  411. break;
  412. else if (y->tavl_balance == -2) {
  413. struct tavl_node *x = y->tavl_link[0];
  414. assert(x != NULL);
  415. if (x->tavl_balance == +1) {
  416. struct tavl_node *w;
  417. assert(x->tavl_balance == +1);
  418. w = x->tavl_link[1];
  419. x->tavl_link[1] = w->tavl_link[0];
  420. w->tavl_link[0] = x;
  421. y->tavl_link[0] = w->tavl_link[1];
  422. w->tavl_link[1] = y;
  423. if (w->tavl_balance == -1)
  424. x->tavl_balance = 0, y->tavl_balance = +1;
  425. else if (w->tavl_balance == 0)
  426. x->tavl_balance = y->tavl_balance = 0;
  427. else /* |w->tavl_balance == +1| */
  428. x->tavl_balance = -1, y->tavl_balance = 0;
  429. w->tavl_balance = 0;
  430. if (w->tavl_tag[0] == TAVL_THREAD) {
  431. x->tavl_tag[1] = TAVL_THREAD;
  432. x->tavl_link[1] = w;
  433. w->tavl_tag[0] = TAVL_CHILD;
  434. }
  435. if (w->tavl_tag[1] == TAVL_THREAD) {
  436. y->tavl_tag[0] = TAVL_THREAD;
  437. y->tavl_link[0] = w;
  438. w->tavl_tag[1] = TAVL_CHILD;
  439. }
  440. q->tavl_link[dir] = w;
  441. }
  442. else {
  443. q->tavl_link[dir] = x;
  444. if (x->tavl_balance == 0) {
  445. y->tavl_link[0] = x->tavl_link[1];
  446. x->tavl_link[1] = y;
  447. x->tavl_balance = +1;
  448. y->tavl_balance = -1;
  449. break;
  450. }
  451. else { /* |x->tavl_balance == -1| */
  452. if (x->tavl_tag[1] == TAVL_CHILD)
  453. y->tavl_link[0] = x->tavl_link[1];
  454. else {
  455. y->tavl_tag[0] = TAVL_THREAD;
  456. x->tavl_tag[1] = TAVL_CHILD;
  457. }
  458. x->tavl_link[1] = y;
  459. y->tavl_balance = x->tavl_balance = 0;
  460. }
  461. }
  462. }
  463. }
  464. }
  465. tree->tavl_count--;
  466. return (void *)item;
  467. }
  468. /* Initializes |trav| for use with |tree|
  469. and selects the null node. */
  470. void tavl_t_init(struct tavl_traverser *trav, struct tavl_table *tree)
  471. {
  472. trav->tavl_table = tree;
  473. trav->tavl_node = NULL;
  474. }
  475. /* Initializes |trav| for |tree|.
  476. Returns data item in |tree| with the least value,
  477. or |NULL| if |tree| is empty. */
  478. void *tavl_t_first(struct tavl_traverser *trav, struct tavl_table *tree)
  479. {
  480. assert(tree != NULL && trav != NULL);
  481. trav->tavl_table = tree;
  482. trav->tavl_node = tree->tavl_root;
  483. if (trav->tavl_node != NULL) {
  484. while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
  485. trav->tavl_node = trav->tavl_node->tavl_link[0];
  486. return trav->tavl_node->tavl_data;
  487. }
  488. else
  489. return NULL;
  490. }
  491. /* Initializes |trav| for |tree|.
  492. Returns data item in |tree| with the greatest value,
  493. or |NULL| if |tree| is empty. */
  494. void *tavl_t_last(struct tavl_traverser *trav, struct tavl_table *tree)
  495. {
  496. assert(tree != NULL && trav != NULL);
  497. trav->tavl_table = tree;
  498. trav->tavl_node = tree->tavl_root;
  499. if (trav->tavl_node != NULL) {
  500. while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
  501. trav->tavl_node = trav->tavl_node->tavl_link[1];
  502. return trav->tavl_node->tavl_data;
  503. }
  504. else
  505. return NULL;
  506. }
  507. /* Searches for |item| in |tree|.
  508. If found, initializes |trav| to the item found and returns the item
  509. as well.
  510. If there is no matching item, initializes |trav| to the null item
  511. and returns |NULL|. */
  512. void *tavl_t_find(struct tavl_traverser *trav, struct tavl_table *tree,
  513. void *item)
  514. {
  515. struct tavl_node *p;
  516. assert(trav != NULL && tree != NULL && item != NULL);
  517. trav->tavl_table = tree;
  518. trav->tavl_node = NULL;
  519. p = tree->tavl_root;
  520. while (p != NULL) {
  521. int cmp, dir;
  522. cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  523. if (cmp == 0) {
  524. trav->tavl_node = p;
  525. return p->tavl_data;
  526. }
  527. dir = cmp > 0;
  528. if (p->tavl_tag[dir] == TAVL_CHILD)
  529. p = p->tavl_link[dir];
  530. else
  531. p = NULL;
  532. }
  533. trav->tavl_node = NULL;
  534. return NULL;
  535. }
  536. /* Attempts to insert |item| into |tree|.
  537. If |item| is inserted successfully, it is returned and |trav| is
  538. initialized to its location.
  539. If a duplicate is found, it is returned and |trav| is initialized to
  540. its location. No replacement of the item occurs.
  541. If a memory allocation failure occurs, |NULL| is returned and |trav|
  542. is initialized to the null item. */
  543. void *tavl_t_insert(struct tavl_traverser *trav,
  544. struct tavl_table *tree, void *item)
  545. {
  546. void **p;
  547. assert(trav != NULL && tree != NULL && item != NULL);
  548. p = tavl_probe(tree, item);
  549. if (p != NULL) {
  550. trav->tavl_table = tree;
  551. trav->tavl_node = ((struct tavl_node *)
  552. ((char *)p -
  553. offsetof(struct tavl_node, tavl_data)));
  554. return *p;
  555. }
  556. else {
  557. tavl_t_init(trav, tree);
  558. return NULL;
  559. }
  560. }
  561. /* Initializes |trav| to have the same current node as |src|. */
  562. void *tavl_t_copy(struct tavl_traverser *trav,
  563. const struct tavl_traverser *src)
  564. {
  565. assert(trav != NULL && src != NULL);
  566. trav->tavl_table = src->tavl_table;
  567. trav->tavl_node = src->tavl_node;
  568. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  569. }
  570. /* Returns the next data item in inorder
  571. within the tree being traversed with |trav|,
  572. or if there are no more data items returns |NULL|. */
  573. void *tavl_t_next(struct tavl_traverser *trav)
  574. {
  575. assert(trav != NULL);
  576. if (trav->tavl_node == NULL)
  577. return tavl_t_first(trav, trav->tavl_table);
  578. else if (trav->tavl_node->tavl_tag[1] == TAVL_THREAD) {
  579. trav->tavl_node = trav->tavl_node->tavl_link[1];
  580. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  581. }
  582. else {
  583. trav->tavl_node = trav->tavl_node->tavl_link[1];
  584. while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
  585. trav->tavl_node = trav->tavl_node->tavl_link[0];
  586. return trav->tavl_node->tavl_data;
  587. }
  588. }
  589. /* Returns the previous data item in inorder
  590. within the tree being traversed with |trav|,
  591. or if there are no more data items returns |NULL|. */
  592. void *tavl_t_prev(struct tavl_traverser *trav)
  593. {
  594. assert(trav != NULL);
  595. if (trav->tavl_node == NULL)
  596. return tavl_t_last(trav, trav->tavl_table);
  597. else if (trav->tavl_node->tavl_tag[0] == TAVL_THREAD) {
  598. trav->tavl_node = trav->tavl_node->tavl_link[0];
  599. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  600. }
  601. else {
  602. trav->tavl_node = trav->tavl_node->tavl_link[0];
  603. while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
  604. trav->tavl_node = trav->tavl_node->tavl_link[1];
  605. return trav->tavl_node->tavl_data;
  606. }
  607. }
  608. /* Returns |trav|'s current item. */
  609. void *tavl_t_cur(struct tavl_traverser *trav)
  610. {
  611. assert(trav != NULL);
  612. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  613. }
  614. /* Replaces the current item in |trav| by |new| and returns the item replaced.
  615. |trav| must not have the null item selected.
  616. The new item must not upset the ordering of the tree. */
  617. void *tavl_t_replace(struct tavl_traverser *trav, void *new)
  618. {
  619. void *old;
  620. assert(trav != NULL && trav->tavl_node != NULL && new != NULL);
  621. old = trav->tavl_node->tavl_data;
  622. trav->tavl_node->tavl_data = new;
  623. return old;
  624. }
  625. /* Creates a new node as a child of |dst| on side |dir|.
  626. Copies data and |tavl_balance| from |src| into the new node,
  627. applying |copy()|, if non-null.
  628. Returns nonzero only if fully successful.
  629. Regardless of success, integrity of the tree structure is assured,
  630. though failure may leave a null pointer in a |tavl_data| member. */
  631. static int
  632. copy_node(struct tavl_table *tree,
  633. struct tavl_node *dst, int dir,
  634. const struct tavl_node *src, tavl_copy_func * copy)
  635. {
  636. struct tavl_node *new =
  637. tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *new);
  638. if (new == NULL)
  639. return 0;
  640. new->tavl_link[dir] = dst->tavl_link[dir];
  641. new->tavl_tag[dir] = TAVL_THREAD;
  642. new->tavl_link[!dir] = dst;
  643. new->tavl_tag[!dir] = TAVL_THREAD;
  644. dst->tavl_link[dir] = new;
  645. dst->tavl_tag[dir] = TAVL_CHILD;
  646. new->tavl_balance = src->tavl_balance;
  647. if (copy == NULL)
  648. new->tavl_data = src->tavl_data;
  649. else {
  650. new->tavl_data = copy(src->tavl_data, tree->tavl_param);
  651. if (new->tavl_data == NULL)
  652. return 0;
  653. }
  654. return 1;
  655. }
  656. /* Destroys |new| with |tavl_destroy (new, destroy)|,
  657. first initializing the right link in |new| that has
  658. not yet been initialized. */
  659. static void
  660. copy_error_recovery(struct tavl_node *p,
  661. struct tavl_table *new, tavl_item_func * destroy)
  662. {
  663. new->tavl_root = p;
  664. if (p != NULL) {
  665. while (p->tavl_tag[1] == TAVL_CHILD)
  666. p = p->tavl_link[1];
  667. p->tavl_link[1] = NULL;
  668. }
  669. tavl_destroy(new, destroy);
  670. }
  671. /* Copies |org| to a newly created tree, which is returned.
  672. If |copy != NULL|, each data item in |org| is first passed to |copy|,
  673. and the return values are inserted into the tree,
  674. with |NULL| return values taken as indications of failure.
  675. On failure, destroys the partially created new tree,
  676. applying |destroy|, if non-null, to each item in the new tree so far,
  677. and returns |NULL|.
  678. If |allocator != NULL|, it is used for allocation in the new tree.
  679. Otherwise, the same allocator used for |org| is used. */
  680. struct tavl_table *tavl_copy(const struct tavl_table *org,
  681. tavl_copy_func * copy, tavl_item_func * destroy,
  682. struct libavl_allocator *allocator)
  683. {
  684. struct tavl_table *new;
  685. const struct tavl_node *p;
  686. struct tavl_node *q;
  687. struct tavl_node rp, rq;
  688. assert(org != NULL);
  689. new = tavl_create(org->tavl_compare, org->tavl_param,
  690. allocator != NULL ? allocator : org->tavl_alloc);
  691. if (new == NULL)
  692. return NULL;
  693. new->tavl_count = org->tavl_count;
  694. if (new->tavl_count == 0)
  695. return new;
  696. p = &rp;
  697. rp.tavl_link[0] = org->tavl_root;
  698. rp.tavl_tag[0] = TAVL_CHILD;
  699. q = &rq;
  700. rq.tavl_link[0] = NULL;
  701. rq.tavl_tag[0] = TAVL_THREAD;
  702. while (p != NULL) {
  703. if (p->tavl_tag[0] == TAVL_CHILD) {
  704. if (!copy_node(new, q, 0, p->tavl_link[0], copy)) {
  705. copy_error_recovery(rq.tavl_link[0], new, destroy);
  706. return NULL;
  707. }
  708. p = p->tavl_link[0];
  709. q = q->tavl_link[0];
  710. }
  711. else {
  712. while (p->tavl_tag[1] == TAVL_THREAD) {
  713. p = p->tavl_link[1];
  714. if (p == NULL) {
  715. q->tavl_link[1] = NULL;
  716. new->tavl_root = rq.tavl_link[0];
  717. return new;
  718. }
  719. q = q->tavl_link[1];
  720. }
  721. p = p->tavl_link[1];
  722. q = q->tavl_link[1];
  723. }
  724. if (p->tavl_tag[1] == TAVL_CHILD)
  725. if (!copy_node(new, q, 1, p->tavl_link[1], copy)) {
  726. copy_error_recovery(rq.tavl_link[0], new, destroy);
  727. return NULL;
  728. }
  729. }
  730. return new;
  731. }
  732. /* Frees storage allocated for |tree|.
  733. If |destroy != NULL|, applies it to each data item in inorder. */
  734. void tavl_destroy(struct tavl_table *tree, tavl_item_func * destroy)
  735. {
  736. struct tavl_node *p; /* Current node. */
  737. struct tavl_node *n; /* Next node. */
  738. p = tree->tavl_root;
  739. if (p != NULL) {
  740. while (p->tavl_tag[0] == TAVL_CHILD)
  741. p = p->tavl_link[0];
  742. }
  743. while (p != NULL) {
  744. n = p->tavl_link[1];
  745. if (p->tavl_tag[1] == TAVL_CHILD)
  746. while (n->tavl_tag[0] == TAVL_CHILD)
  747. n = n->tavl_link[0];
  748. if (destroy != NULL && p->tavl_data != NULL)
  749. destroy(p->tavl_data, tree->tavl_param);
  750. tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
  751. p = n;
  752. }
  753. tree->tavl_alloc->libavl_free(tree->tavl_alloc, tree);
  754. }
  755. /* Allocates |size| bytes of space using |malloc()|.
  756. Returns a null pointer if allocation fails. */
  757. void *tavl_malloc(struct libavl_allocator *allocator, size_t size)
  758. {
  759. assert(allocator != NULL && size > 0);
  760. return malloc(size);
  761. }
  762. /* Frees |block|. */
  763. void tavl_free(struct libavl_allocator *allocator, void *block)
  764. {
  765. assert(allocator != NULL && block != NULL);
  766. free(block);
  767. }
  768. /* Default memory allocator that uses |malloc()| and |free()|. */
  769. struct libavl_allocator tavl_allocator_default = {
  770. tavl_malloc,
  771. tavl_free
  772. };
  773. #undef NDEBUG
  774. #include <assert.h>
  775. /* Asserts that |tavl_insert()| succeeds at inserting |item| into |table|. */
  776. void (tavl_assert_insert) (struct tavl_table * table, void *item)
  777. {
  778. void **p = tavl_probe(table, item);
  779. assert(p != NULL && *p == item);
  780. }
  781. /* Asserts that |tavl_delete()| really removes |item| from |table|,
  782. and returns the removed item. */
  783. void *(tavl_assert_delete) (struct tavl_table * table, void *item)
  784. {
  785. void *p = tavl_delete(table, item);
  786. assert(p != NULL);
  787. return p;
  788. }