tavl.c 24 KB

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