tavl.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. /* Produced by texiweb from libavl.w on 2002/02/09 at 01:45. */
  2. /* libavl - library for manipulation of binary trees.
  3. Copyright (C) 1998-2002 Free Software Foundation, Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. See the GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.
  16. The author may be contacted at <blp@gnu.org> on the Internet, or
  17. as Ben Pfaff, 12167 Airport Rd, DeWitt MI 48820, USA through more
  18. mundane means.
  19. */
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include "tavl.h"
  24. /* Creates and returns a new table
  25. with comparison function |compare| using parameter |param|
  26. and memory allocator |allocator|.
  27. Returns |NULL| if memory allocation failed. */
  28. struct tavl_table *tavl_create(tavl_comparison_func * compare, void *param,
  29. struct libavl_allocator *allocator)
  30. {
  31. struct tavl_table *tree;
  32. assert(compare != NULL);
  33. if (allocator == NULL)
  34. allocator = &tavl_allocator_default;
  35. tree = allocator->libavl_malloc(allocator, sizeof *tree);
  36. if (tree == NULL)
  37. return NULL;
  38. tree->tavl_root = NULL;
  39. tree->tavl_compare = compare;
  40. tree->tavl_param = param;
  41. tree->tavl_alloc = allocator;
  42. tree->tavl_count = 0;
  43. return tree;
  44. }
  45. /* Search |tree| for an item matching |item|, and return it if found.
  46. Otherwise return |NULL|. */
  47. void *tavl_find(const struct tavl_table *tree, const void *item)
  48. {
  49. const struct tavl_node *p;
  50. assert(tree != NULL && item != NULL);
  51. p = tree->tavl_root;
  52. if (p == NULL)
  53. return NULL;
  54. for (;;) {
  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. return NULL;
  64. }
  65. }
  66. /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
  67. If a duplicate item is found in the tree,
  68. returns a pointer to the duplicate without inserting |item|.
  69. Returns |NULL| in case of memory allocation failure. */
  70. void **tavl_probe(struct tavl_table *tree, void *item)
  71. {
  72. struct tavl_node *y, *z; /* Top node to update balance factor, and parent. */
  73. struct tavl_node *p, *q; /* Iterator, and parent. */
  74. struct tavl_node *n; /* Newly inserted node. */
  75. struct tavl_node *w; /* New root of rebalanced subtree. */
  76. int dir; /* Direction to descend. */
  77. unsigned char da[TAVL_MAX_HEIGHT]; /* Cached comparison results. */
  78. int k = 0; /* Number of cached results. */
  79. assert(tree != NULL && item != NULL);
  80. z = (struct tavl_node *)&tree->tavl_root;
  81. y = tree->tavl_root;
  82. if (y != NULL) {
  83. for (q = z, p = y;; q = p, p = p->tavl_link[dir]) {
  84. int cmp =
  85. tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  86. if (cmp == 0)
  87. return &p->tavl_data;
  88. if (p->tavl_balance != 0)
  89. z = q, y = p, k = 0;
  90. da[k++] = dir = cmp > 0;
  91. if (p->tavl_tag[dir] == TAVL_THREAD)
  92. break;
  93. }
  94. }
  95. else {
  96. p = z;
  97. dir = 0;
  98. }
  99. n = tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *n);
  100. if (n == NULL)
  101. return NULL;
  102. tree->tavl_count++;
  103. n->tavl_data = item;
  104. n->tavl_tag[0] = n->tavl_tag[1] = TAVL_THREAD;
  105. n->tavl_link[dir] = p->tavl_link[dir];
  106. if (tree->tavl_root != NULL) {
  107. p->tavl_tag[dir] = TAVL_CHILD;
  108. n->tavl_link[!dir] = p;
  109. }
  110. else
  111. n->tavl_link[1] = NULL;
  112. p->tavl_link[dir] = n;
  113. n->tavl_balance = 0;
  114. if (tree->tavl_root == n)
  115. return &n->tavl_data;
  116. for (p = y, k = 0; p != n; p = p->tavl_link[da[k]], k++)
  117. if (da[k] == 0)
  118. p->tavl_balance--;
  119. else
  120. p->tavl_balance++;
  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. if (tree->tavl_root == NULL)
  270. return NULL;
  271. p = (struct tavl_node *)&tree->tavl_root;
  272. for (cmp = -1; cmp != 0;
  273. cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param)) {
  274. dir = cmp > 0;
  275. q = p;
  276. if (p->tavl_tag[dir] == TAVL_THREAD)
  277. return NULL;
  278. p = p->tavl_link[dir];
  279. }
  280. item = p->tavl_data;
  281. if (p->tavl_tag[1] == TAVL_THREAD) {
  282. if (p->tavl_tag[0] == TAVL_CHILD) {
  283. struct tavl_node *t = p->tavl_link[0];
  284. while (t->tavl_tag[1] == TAVL_CHILD)
  285. t = t->tavl_link[1];
  286. t->tavl_link[1] = p->tavl_link[1];
  287. q->tavl_link[dir] = p->tavl_link[0];
  288. }
  289. else {
  290. q->tavl_link[dir] = p->tavl_link[dir];
  291. if (q != (struct tavl_node *)&tree->tavl_root)
  292. q->tavl_tag[dir] = TAVL_THREAD;
  293. }
  294. }
  295. else {
  296. struct tavl_node *r = p->tavl_link[1];
  297. if (r->tavl_tag[0] == TAVL_THREAD) {
  298. r->tavl_link[0] = p->tavl_link[0];
  299. r->tavl_tag[0] = p->tavl_tag[0];
  300. if (r->tavl_tag[0] == TAVL_CHILD) {
  301. struct tavl_node *t = r->tavl_link[0];
  302. while (t->tavl_tag[1] == TAVL_CHILD)
  303. t = t->tavl_link[1];
  304. t->tavl_link[1] = r;
  305. }
  306. q->tavl_link[dir] = r;
  307. r->tavl_balance = p->tavl_balance;
  308. q = r;
  309. dir = 1;
  310. }
  311. else {
  312. struct tavl_node *s;
  313. for (;;) {
  314. s = r->tavl_link[0];
  315. if (s->tavl_tag[0] == TAVL_THREAD)
  316. break;
  317. r = s;
  318. }
  319. if (s->tavl_tag[1] == TAVL_CHILD)
  320. r->tavl_link[0] = s->tavl_link[1];
  321. else {
  322. r->tavl_link[0] = s;
  323. r->tavl_tag[0] = TAVL_THREAD;
  324. }
  325. s->tavl_link[0] = p->tavl_link[0];
  326. if (p->tavl_tag[0] == TAVL_CHILD) {
  327. struct tavl_node *t = p->tavl_link[0];
  328. while (t->tavl_tag[1] == TAVL_CHILD)
  329. t = t->tavl_link[1];
  330. t->tavl_link[1] = s;
  331. s->tavl_tag[0] = TAVL_CHILD;
  332. }
  333. s->tavl_link[1] = p->tavl_link[1];
  334. s->tavl_tag[1] = TAVL_CHILD;
  335. q->tavl_link[dir] = s;
  336. s->tavl_balance = p->tavl_balance;
  337. q = r;
  338. dir = 0;
  339. }
  340. }
  341. tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
  342. while (q != (struct tavl_node *)&tree->tavl_root) {
  343. struct tavl_node *y = q;
  344. q = find_parent(tree, y);
  345. if (dir == 0) {
  346. dir = q->tavl_link[0] != y;
  347. y->tavl_balance++;
  348. if (y->tavl_balance == +1)
  349. break;
  350. else if (y->tavl_balance == +2) {
  351. struct tavl_node *x = y->tavl_link[1];
  352. assert(x != NULL);
  353. if (x->tavl_balance == -1) {
  354. struct tavl_node *w;
  355. assert(x->tavl_balance == -1);
  356. w = x->tavl_link[0];
  357. x->tavl_link[0] = w->tavl_link[1];
  358. w->tavl_link[1] = x;
  359. y->tavl_link[1] = w->tavl_link[0];
  360. w->tavl_link[0] = y;
  361. if (w->tavl_balance == +1)
  362. x->tavl_balance = 0, y->tavl_balance = -1;
  363. else if (w->tavl_balance == 0)
  364. x->tavl_balance = y->tavl_balance = 0;
  365. else /* |w->tavl_balance == -1| */
  366. x->tavl_balance = +1, y->tavl_balance = 0;
  367. w->tavl_balance = 0;
  368. if (w->tavl_tag[0] == TAVL_THREAD) {
  369. y->tavl_tag[1] = TAVL_THREAD;
  370. y->tavl_link[1] = w;
  371. w->tavl_tag[0] = TAVL_CHILD;
  372. }
  373. if (w->tavl_tag[1] == TAVL_THREAD) {
  374. x->tavl_tag[0] = TAVL_THREAD;
  375. x->tavl_link[0] = w;
  376. w->tavl_tag[1] = TAVL_CHILD;
  377. }
  378. q->tavl_link[dir] = w;
  379. }
  380. else {
  381. q->tavl_link[dir] = x;
  382. if (x->tavl_balance == 0) {
  383. y->tavl_link[1] = x->tavl_link[0];
  384. x->tavl_link[0] = y;
  385. x->tavl_balance = -1;
  386. y->tavl_balance = +1;
  387. break;
  388. }
  389. else { /* |x->tavl_balance == +1| */
  390. if (x->tavl_tag[0] == TAVL_CHILD)
  391. y->tavl_link[1] = x->tavl_link[0];
  392. else {
  393. y->tavl_tag[1] = TAVL_THREAD;
  394. x->tavl_tag[0] = TAVL_CHILD;
  395. }
  396. x->tavl_link[0] = y;
  397. y->tavl_balance = x->tavl_balance = 0;
  398. }
  399. }
  400. }
  401. }
  402. else {
  403. dir = q->tavl_link[0] != y;
  404. y->tavl_balance--;
  405. if (y->tavl_balance == -1)
  406. break;
  407. else if (y->tavl_balance == -2) {
  408. struct tavl_node *x = y->tavl_link[0];
  409. assert(x != NULL);
  410. if (x->tavl_balance == +1) {
  411. struct tavl_node *w;
  412. assert(x->tavl_balance == +1);
  413. w = x->tavl_link[1];
  414. x->tavl_link[1] = w->tavl_link[0];
  415. w->tavl_link[0] = x;
  416. y->tavl_link[0] = w->tavl_link[1];
  417. w->tavl_link[1] = y;
  418. if (w->tavl_balance == -1)
  419. x->tavl_balance = 0, y->tavl_balance = +1;
  420. else if (w->tavl_balance == 0)
  421. x->tavl_balance = y->tavl_balance = 0;
  422. else /* |w->tavl_balance == +1| */
  423. x->tavl_balance = -1, y->tavl_balance = 0;
  424. w->tavl_balance = 0;
  425. if (w->tavl_tag[0] == TAVL_THREAD) {
  426. x->tavl_tag[1] = TAVL_THREAD;
  427. x->tavl_link[1] = w;
  428. w->tavl_tag[0] = TAVL_CHILD;
  429. }
  430. if (w->tavl_tag[1] == TAVL_THREAD) {
  431. y->tavl_tag[0] = TAVL_THREAD;
  432. y->tavl_link[0] = w;
  433. w->tavl_tag[1] = TAVL_CHILD;
  434. }
  435. q->tavl_link[dir] = w;
  436. }
  437. else {
  438. q->tavl_link[dir] = x;
  439. if (x->tavl_balance == 0) {
  440. y->tavl_link[0] = x->tavl_link[1];
  441. x->tavl_link[1] = y;
  442. x->tavl_balance = +1;
  443. y->tavl_balance = -1;
  444. break;
  445. }
  446. else { /* |x->tavl_balance == -1| */
  447. if (x->tavl_tag[1] == TAVL_CHILD)
  448. y->tavl_link[0] = x->tavl_link[1];
  449. else {
  450. y->tavl_tag[0] = TAVL_THREAD;
  451. x->tavl_tag[1] = TAVL_CHILD;
  452. }
  453. x->tavl_link[1] = y;
  454. y->tavl_balance = x->tavl_balance = 0;
  455. }
  456. }
  457. }
  458. }
  459. }
  460. tree->tavl_count--;
  461. return (void *)item;
  462. }
  463. /* Initializes |trav| for use with |tree|
  464. and selects the null node. */
  465. void tavl_t_init(struct tavl_traverser *trav, struct tavl_table *tree)
  466. {
  467. trav->tavl_table = tree;
  468. trav->tavl_node = NULL;
  469. }
  470. /* Initializes |trav| for |tree|.
  471. Returns data item in |tree| with the least value,
  472. or |NULL| if |tree| is empty. */
  473. void *tavl_t_first(struct tavl_traverser *trav, struct tavl_table *tree)
  474. {
  475. assert(tree != NULL && trav != NULL);
  476. trav->tavl_table = tree;
  477. trav->tavl_node = tree->tavl_root;
  478. if (trav->tavl_node != NULL) {
  479. while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
  480. trav->tavl_node = trav->tavl_node->tavl_link[0];
  481. return trav->tavl_node->tavl_data;
  482. }
  483. else
  484. return NULL;
  485. }
  486. /* Initializes |trav| for |tree|.
  487. Returns data item in |tree| with the greatest value,
  488. or |NULL| if |tree| is empty. */
  489. void *tavl_t_last(struct tavl_traverser *trav, struct tavl_table *tree)
  490. {
  491. assert(tree != NULL && trav != NULL);
  492. trav->tavl_table = tree;
  493. trav->tavl_node = tree->tavl_root;
  494. if (trav->tavl_node != NULL) {
  495. while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
  496. trav->tavl_node = trav->tavl_node->tavl_link[1];
  497. return trav->tavl_node->tavl_data;
  498. }
  499. else
  500. return NULL;
  501. }
  502. /* Searches for |item| in |tree|.
  503. If found, initializes |trav| to the item found and returns the item
  504. as well.
  505. If there is no matching item, initializes |trav| to the null item
  506. and returns |NULL|. */
  507. void *tavl_t_find(struct tavl_traverser *trav, struct tavl_table *tree,
  508. void *item)
  509. {
  510. struct tavl_node *p;
  511. assert(trav != NULL && tree != NULL && item != NULL);
  512. trav->tavl_table = tree;
  513. trav->tavl_node = NULL;
  514. p = tree->tavl_root;
  515. if (p == NULL)
  516. return NULL;
  517. for (;;) {
  518. int cmp, dir;
  519. cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
  520. if (cmp == 0) {
  521. trav->tavl_node = p;
  522. return p->tavl_data;
  523. }
  524. dir = cmp > 0;
  525. if (p->tavl_tag[dir] == TAVL_CHILD)
  526. p = p->tavl_link[dir];
  527. else
  528. return NULL;
  529. }
  530. }
  531. /* Attempts to insert |item| into |tree|.
  532. If |item| is inserted successfully, it is returned and |trav| is
  533. initialized to its location.
  534. If a duplicate is found, it is returned and |trav| is initialized to
  535. its location. No replacement of the item occurs.
  536. If a memory allocation failure occurs, |NULL| is returned and |trav|
  537. is initialized to the null item. */
  538. void *tavl_t_insert(struct tavl_traverser *trav,
  539. struct tavl_table *tree, void *item)
  540. {
  541. void **p;
  542. assert(trav != NULL && tree != NULL && item != NULL);
  543. p = tavl_probe(tree, item);
  544. if (p != NULL) {
  545. trav->tavl_table = tree;
  546. trav->tavl_node = ((struct tavl_node *)
  547. ((char *)p -
  548. offsetof(struct tavl_node, tavl_data)));
  549. return *p;
  550. }
  551. else {
  552. tavl_t_init(trav, tree);
  553. return NULL;
  554. }
  555. }
  556. /* Initializes |trav| to have the same current node as |src|. */
  557. void *tavl_t_copy(struct tavl_traverser *trav,
  558. const struct tavl_traverser *src)
  559. {
  560. assert(trav != NULL && src != NULL);
  561. trav->tavl_table = src->tavl_table;
  562. trav->tavl_node = src->tavl_node;
  563. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  564. }
  565. /* Returns the next data item in inorder
  566. within the tree being traversed with |trav|,
  567. or if there are no more data items returns |NULL|. */
  568. void *tavl_t_next(struct tavl_traverser *trav)
  569. {
  570. assert(trav != NULL);
  571. if (trav->tavl_node == NULL)
  572. return tavl_t_first(trav, trav->tavl_table);
  573. else if (trav->tavl_node->tavl_tag[1] == TAVL_THREAD) {
  574. trav->tavl_node = trav->tavl_node->tavl_link[1];
  575. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  576. }
  577. else {
  578. trav->tavl_node = trav->tavl_node->tavl_link[1];
  579. while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
  580. trav->tavl_node = trav->tavl_node->tavl_link[0];
  581. return trav->tavl_node->tavl_data;
  582. }
  583. }
  584. /* Returns the previous data item in inorder
  585. within the tree being traversed with |trav|,
  586. or if there are no more data items returns |NULL|. */
  587. void *tavl_t_prev(struct tavl_traverser *trav)
  588. {
  589. assert(trav != NULL);
  590. if (trav->tavl_node == NULL)
  591. return tavl_t_last(trav, trav->tavl_table);
  592. else if (trav->tavl_node->tavl_tag[0] == TAVL_THREAD) {
  593. trav->tavl_node = trav->tavl_node->tavl_link[0];
  594. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  595. }
  596. else {
  597. trav->tavl_node = trav->tavl_node->tavl_link[0];
  598. while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
  599. trav->tavl_node = trav->tavl_node->tavl_link[1];
  600. return trav->tavl_node->tavl_data;
  601. }
  602. }
  603. /* Returns |trav|'s current item. */
  604. void *tavl_t_cur(struct tavl_traverser *trav)
  605. {
  606. assert(trav != NULL);
  607. return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
  608. }
  609. /* Replaces the current item in |trav| by |new| and returns the item replaced.
  610. |trav| must not have the null item selected.
  611. The new item must not upset the ordering of the tree. */
  612. void *tavl_t_replace(struct tavl_traverser *trav, void *new)
  613. {
  614. struct tavl_node *old;
  615. assert(trav != NULL && trav->tavl_node != NULL && new != NULL);
  616. old = trav->tavl_node->tavl_data;
  617. trav->tavl_node->tavl_data = new;
  618. return old;
  619. }
  620. /* Creates a new node as a child of |dst| on side |dir|.
  621. Copies data and |tavl_balance| from |src| into the new node,
  622. applying |copy()|, if non-null.
  623. Returns nonzero only if fully successful.
  624. Regardless of success, integrity of the tree structure is assured,
  625. though failure may leave a null pointer in a |tavl_data| member. */
  626. static int
  627. copy_node(struct tavl_table *tree,
  628. struct tavl_node *dst, int dir,
  629. const struct tavl_node *src, tavl_copy_func * copy)
  630. {
  631. struct tavl_node *new =
  632. tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *new);
  633. if (new == NULL)
  634. return 0;
  635. new->tavl_link[dir] = dst->tavl_link[dir];
  636. new->tavl_tag[dir] = TAVL_THREAD;
  637. new->tavl_link[!dir] = dst;
  638. new->tavl_tag[!dir] = TAVL_THREAD;
  639. dst->tavl_link[dir] = new;
  640. dst->tavl_tag[dir] = TAVL_CHILD;
  641. new->tavl_balance = src->tavl_balance;
  642. if (copy == NULL)
  643. new->tavl_data = src->tavl_data;
  644. else {
  645. new->tavl_data = copy(src->tavl_data, tree->tavl_param);
  646. if (new->tavl_data == NULL)
  647. return 0;
  648. }
  649. return 1;
  650. }
  651. static void
  652. copy_error_recovery(struct tavl_node *p,
  653. struct tavl_table *new, tavl_item_func * destroy)
  654. {
  655. new->tavl_root = p;
  656. if (p != NULL) {
  657. while (p->tavl_tag[1] == TAVL_CHILD)
  658. p = p->tavl_link[1];
  659. p->tavl_link[1] = NULL;
  660. }
  661. tavl_destroy(new, destroy);
  662. }
  663. /* Copies |org| to a newly created tree, which is returned.
  664. If |copy != NULL|, each data item in |org| is first passed to |copy|,
  665. and the return values are inserted into the tree,
  666. with |NULL| return values taken as indications of failure.
  667. On failure, destroys the partially created new tree,
  668. applying |destroy|, if non-null, to each item in the new tree so far,
  669. and returns |NULL|.
  670. If |allocator != NULL|, it is used for allocation in the new tree.
  671. Otherwise, the same allocator used for |org| is used. */
  672. struct tavl_table *tavl_copy(const struct tavl_table *org,
  673. tavl_copy_func * copy, tavl_item_func * destroy,
  674. struct libavl_allocator *allocator)
  675. {
  676. struct tavl_table *new;
  677. const struct tavl_node *p;
  678. struct tavl_node *q;
  679. struct tavl_node rp, rq;
  680. assert(org != NULL);
  681. new = tavl_create(org->tavl_compare, org->tavl_param,
  682. allocator != NULL ? allocator : org->tavl_alloc);
  683. if (new == NULL)
  684. return NULL;
  685. new->tavl_count = org->tavl_count;
  686. if (new->tavl_count == 0)
  687. return new;
  688. p = &rp;
  689. rp.tavl_link[0] = org->tavl_root;
  690. rp.tavl_tag[0] = TAVL_CHILD;
  691. q = &rq;
  692. rq.tavl_link[0] = NULL;
  693. rq.tavl_tag[0] = TAVL_THREAD;
  694. for (;;) {
  695. if (p->tavl_tag[0] == TAVL_CHILD) {
  696. if (!copy_node(new, q, 0, p->tavl_link[0], copy)) {
  697. copy_error_recovery(rq.tavl_link[0], new, destroy);
  698. return NULL;
  699. }
  700. p = p->tavl_link[0];
  701. q = q->tavl_link[0];
  702. }
  703. else {
  704. while (p->tavl_tag[1] == TAVL_THREAD) {
  705. p = p->tavl_link[1];
  706. if (p == NULL) {
  707. q->tavl_link[1] = NULL;
  708. new->tavl_root = rq.tavl_link[0];
  709. return new;
  710. }
  711. q = q->tavl_link[1];
  712. }
  713. p = p->tavl_link[1];
  714. q = q->tavl_link[1];
  715. }
  716. if (p->tavl_tag[1] == TAVL_CHILD)
  717. if (!copy_node(new, q, 1, p->tavl_link[1], copy)) {
  718. copy_error_recovery(rq.tavl_link[0], new, destroy);
  719. return NULL;
  720. }
  721. }
  722. }
  723. /* Frees storage allocated for |tree|.
  724. If |destroy != NULL|, applies it to each data item in inorder. */
  725. void tavl_destroy(struct tavl_table *tree, tavl_item_func * destroy)
  726. {
  727. struct tavl_node *p; /* Current node. */
  728. struct tavl_node *n; /* Next node. */
  729. p = tree->tavl_root;
  730. if (p != NULL)
  731. while (p->tavl_tag[0] == TAVL_CHILD)
  732. p = p->tavl_link[0];
  733. while (p != NULL) {
  734. n = p->tavl_link[1];
  735. if (p->tavl_tag[1] == TAVL_CHILD)
  736. while (n->tavl_tag[0] == TAVL_CHILD)
  737. n = n->tavl_link[0];
  738. if (destroy != NULL && p->tavl_data != NULL)
  739. destroy(p->tavl_data, tree->tavl_param);
  740. tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
  741. p = n;
  742. }
  743. tree->tavl_alloc->libavl_free(tree->tavl_alloc, tree);
  744. }
  745. /* Allocates |size| bytes of space using |malloc()|.
  746. Returns a null pointer if allocation fails. */
  747. void *tavl_malloc(struct libavl_allocator *allocator, size_t size)
  748. {
  749. assert(allocator != NULL && size > 0);
  750. return malloc(size);
  751. }
  752. /* Frees |block|. */
  753. void tavl_free(struct libavl_allocator *allocator, void *block)
  754. {
  755. assert(allocator != NULL && block != NULL);
  756. free(block);
  757. }
  758. /* Default memory allocator that uses |malloc()| and |free()|. */
  759. struct libavl_allocator tavl_allocator_default = {
  760. tavl_malloc,
  761. tavl_free
  762. };
  763. /* Asserts that |tavl_insert()| succeeds at inserting |item| into |table|. */
  764. void (tavl_assert_insert) (struct tavl_table * table, void *item)
  765. {
  766. void **p = tavl_probe(table, item);
  767. assert(p != NULL && *p == item);
  768. }
  769. /* Asserts that |tavl_delete()| really removes |item| from |table|,
  770. and returns the removed item. */
  771. void *(tavl_assert_delete) (struct tavl_table * table, void *item)
  772. {
  773. void *p = tavl_delete(table, item);
  774. assert(p != NULL);
  775. return p;
  776. }