/xine-ui-0.99.6/src/xitk/oxine/list.c

# · C · 904 lines · 683 code · 182 blank · 39 comment · 123 complexity · 407416ea1baa26a29d2973250f6b7119 MD5 · raw file

  1. /*
  2. * Copyright (C) 2003 the oxine project
  3. *
  4. * xine is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * xine 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
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. * doubly linked lists with builtin iterator,
  19. * based upon xine_list functions of the xine project
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <sys/types.h>
  24. #include <inttypes.h>
  25. #ifdef DEBUG
  26. #include <string.h>
  27. #endif
  28. #include "list.h"
  29. #include "utils.h"
  30. /*
  31. * private data structures
  32. */
  33. typedef struct node_s {
  34. struct node_s *next, *prev;
  35. void *content;
  36. int priority;
  37. } node_t;
  38. struct list_s {
  39. node_t *first, *last, *cur;
  40. #ifdef DEBUG
  41. #define TAG_SIZE 256
  42. char tag[TAG_SIZE];
  43. #endif
  44. };
  45. /*
  46. * create a new, empty list
  47. */
  48. #ifdef DEBUG
  49. list_t *_list_new_tagged(char *file, int line) {
  50. char tag[TAG_SIZE];
  51. list_t *list;
  52. snprintf(tag, TAG_SIZE, "list @ %s:%i", file, line);
  53. list = ho_new_tagged(list_t, tag);
  54. strcpy(list->tag, tag);
  55. list->first=NULL;
  56. list->last =NULL;
  57. list->cur =NULL;
  58. return list;
  59. }
  60. #else
  61. list_t *list_new (void) {
  62. list_t *list;
  63. list = ho_new(list_t);
  64. list->first=NULL;
  65. list->last =NULL;
  66. list->cur =NULL;
  67. return list;
  68. }
  69. #endif
  70. /*
  71. * dispose a list (and only the list, contents have to be managed separately)
  72. */
  73. void list_free(list_t *l) {
  74. node_t *node;
  75. if (!l) {
  76. printf ("list: tried to free empty list\n");
  77. abort();
  78. }
  79. if (!l->first) {
  80. ho_free(l);
  81. return;
  82. }
  83. node = l->first;
  84. while(node) {
  85. node_t *n = node;
  86. node = n->next;
  87. ho_free(n);
  88. }
  89. ho_free(l);
  90. }
  91. void *list_first_content (list_t *l) {
  92. l->cur = l->first;
  93. if (l->first)
  94. return l->first->content;
  95. else
  96. return NULL;
  97. }
  98. void *list_next_content (list_t *l) {
  99. if (l->cur) {
  100. if (l->cur->next) {
  101. l->cur = l->cur->next;
  102. return l->cur->content;
  103. }
  104. else
  105. return NULL;
  106. } else {
  107. printf ("list: next_content - passed end of list\n");
  108. abort ();
  109. }
  110. }
  111. void *list_current_content (list_t *l) {
  112. if (l->cur) {
  113. return l->cur->content;
  114. } else {
  115. printf ("list: next_content - passed end of list\n");
  116. abort ();
  117. }
  118. }
  119. int list_is_empty (list_t *l) {
  120. if (l == NULL){
  121. printf ("list: list_is_empty : list is NULL\n");
  122. abort();
  123. }
  124. return (l->first != NULL);
  125. }
  126. void *list_last_content (list_t *l) {
  127. if (l->last) {
  128. l->cur = l->last;
  129. return l->last->content;
  130. } else
  131. return NULL;
  132. }
  133. void *list_prev_content (list_t *l) {
  134. if (l->cur) {
  135. if (l->cur->prev) {
  136. l->cur = l->cur->prev;
  137. return l->cur->content;
  138. }
  139. else
  140. return NULL;
  141. } else {
  142. printf ("list: passed begin of list\n");
  143. abort ();
  144. }
  145. }
  146. void list_append_priority_content (list_t *l, void *content, int priority) {
  147. node_t *node;
  148. #ifdef DEBUG
  149. char tag[TAG_SIZE];
  150. snprintf(tag, TAG_SIZE, "pri node in %s", l->tag);
  151. node = ho_new_tagged(node_t, tag);
  152. #else
  153. node = ho_new(node_t);
  154. #endif
  155. node->content = content;
  156. node->priority = priority;
  157. if (l->first) {
  158. node_t *cur;
  159. cur = l->first;
  160. while(1) {
  161. if( priority >= cur->priority ) {
  162. node->next = cur;
  163. node->prev = cur->prev;
  164. if( node->prev )
  165. node->prev->next = node;
  166. else
  167. l->first = node;
  168. cur->prev = node;
  169. l->cur = node;
  170. break;
  171. }
  172. if( !cur->next ) {
  173. node->next = NULL;
  174. node->prev = cur;
  175. cur->next = node;
  176. l->cur = node;
  177. l->last = node;
  178. break;
  179. }
  180. cur = cur->next;
  181. }
  182. }
  183. else {
  184. l->first = l->last = l->cur = node;
  185. node->prev = node->next = NULL;
  186. }
  187. }
  188. #ifdef DEBUG
  189. void _list_append_content(list_t *l, void *content, char *file, int line) {
  190. node_t *node;
  191. char tag[TAG_SIZE];
  192. snprintf(tag, TAG_SIZE, "app node @ %s:%i", file, line);
  193. node = ho_new_tagged(node_t, tag);
  194. #else
  195. void list_append_content (list_t *l, void *content) {
  196. node_t *node;
  197. node = ho_new(node_t);
  198. #endif
  199. node->content = content;
  200. if (l->last) {
  201. node->next = NULL;
  202. node->prev = l->last;
  203. l->last->next = node;
  204. l->last = node;
  205. l->cur = node;
  206. }
  207. else {
  208. l->first = l->last = l->cur = node;
  209. node->prev = node->next = NULL;
  210. }
  211. }
  212. void list_insert_content (list_t *l, void *content) {
  213. node_t *nodecur, *nodenew, *nodeprev;
  214. #ifdef DEBUG
  215. char tag[TAG_SIZE];
  216. snprintf(tag, TAG_SIZE, "ins node in %s", l->tag);
  217. nodenew = ho_new_tagged(node_t, tag);
  218. #else
  219. nodenew = ho_new(node_t);
  220. #endif
  221. nodenew->content = content;
  222. nodecur = l->cur;
  223. if(!nodecur) {
  224. list_append_content(l, content);
  225. return;
  226. }
  227. nodeprev = nodecur->prev;
  228. nodecur->prev = nodenew;
  229. nodenew->next = nodecur;
  230. nodenew->prev = nodeprev;
  231. if(nodecur != l->first) {
  232. nodeprev->next = nodenew;
  233. } else {
  234. l->first = nodenew;
  235. }
  236. l->cur = nodenew;
  237. }
  238. void list_delete_current (list_t *l) {
  239. node_t *node_cur;
  240. node_cur = l->cur;
  241. if(node_cur->prev) {
  242. node_cur->prev->next = node_cur->next;
  243. }
  244. else { /* First entry */
  245. l->first = node_cur->next;
  246. }
  247. if(node_cur->next) {
  248. node_cur->next->prev = node_cur->prev;
  249. l->cur = node_cur->next;
  250. }
  251. else { /* last entry in the list */
  252. l->last = node_cur->prev;
  253. l->cur = node_cur->prev;
  254. }
  255. ho_free(node_cur);
  256. }
  257. /*
  258. * glib's implementation of lists
  259. */
  260. #define _g_list_new g_list_new
  261. g_list_t* g_list_new (void) {
  262. g_list_t *list;
  263. list = ho_new(g_list_t);
  264. return list;
  265. }
  266. void g_list_free (g_list_t *list) {
  267. g_list_t *last;
  268. while (list)
  269. {
  270. last = list;
  271. list = list->next;
  272. ho_free (last);
  273. }
  274. }
  275. #define _g_list_free_1 g_list_free_1
  276. void g_list_free_1 (g_list_t *list) {
  277. ho_free (list);
  278. }
  279. g_list_t* g_list_append (g_list_t *list, void* data) {
  280. g_list_t *new_list;
  281. g_list_t *last;
  282. new_list = _g_list_new ();
  283. new_list->data = data;
  284. if (list)
  285. {
  286. last = g_list_last (list);
  287. last->next = new_list;
  288. new_list->prev = last;
  289. return list;
  290. }
  291. else
  292. return new_list;
  293. }
  294. g_list_t* g_list_prepend (g_list_t *list, void* data) {
  295. g_list_t *new_list;
  296. new_list = _g_list_new ();
  297. new_list->data = data;
  298. if (list)
  299. {
  300. if (list->prev)
  301. {
  302. list->prev->next = new_list;
  303. new_list->prev = list->prev;
  304. }
  305. list->prev = new_list;
  306. new_list->next = list;
  307. }
  308. return new_list;
  309. }
  310. g_list_t* g_list_insert (g_list_t *list, void* data, int position) {
  311. g_list_t *new_list;
  312. g_list_t *tmp_list;
  313. if (position < 0)
  314. return g_list_append (list, data);
  315. else if (position == 0)
  316. return g_list_prepend (list, data);
  317. tmp_list = g_list_nth (list, position);
  318. if (!tmp_list)
  319. return g_list_append (list, data);
  320. new_list = _g_list_new ();
  321. new_list->data = data;
  322. if (tmp_list->prev)
  323. {
  324. tmp_list->prev->next = new_list;
  325. new_list->prev = tmp_list->prev;
  326. }
  327. new_list->next = tmp_list;
  328. tmp_list->prev = new_list;
  329. if (tmp_list == list)
  330. return new_list;
  331. else
  332. return list;
  333. }
  334. g_list_t* g_list_insert_before (g_list_t *list, g_list_t *sibling, void* data) {
  335. if (!list)
  336. {
  337. list = g_list_new ();
  338. list->data = data;
  339. return list;
  340. }
  341. else if (sibling)
  342. {
  343. g_list_t *node;
  344. node = g_list_new ();
  345. node->data = data;
  346. if (sibling->prev)
  347. {
  348. node->prev = sibling->prev;
  349. node->prev->next = node;
  350. node->next = sibling;
  351. sibling->prev = node;
  352. return list;
  353. }
  354. else
  355. {
  356. node->next = sibling;
  357. sibling->prev = node;
  358. return node;
  359. }
  360. }
  361. else
  362. {
  363. g_list_t *last;
  364. last = list;
  365. while (last->next)
  366. last = last->next;
  367. last->next = g_list_new ();
  368. last->next->data = data;
  369. last->next->prev = last;
  370. return list;
  371. }
  372. }
  373. g_list_t * g_list_concat (g_list_t *list1, g_list_t *list2) {
  374. g_list_t *tmp_list;
  375. if (list2)
  376. {
  377. tmp_list = g_list_last (list1);
  378. if (tmp_list)
  379. tmp_list->next = list2;
  380. else
  381. list1 = list2;
  382. list2->prev = tmp_list;
  383. }
  384. return list1;
  385. }
  386. g_list_t* g_list_remove (g_list_t *list, const void *data) {
  387. g_list_t *tmp;
  388. tmp = list;
  389. while (tmp)
  390. {
  391. if (tmp->data != data)
  392. tmp = tmp->next;
  393. else
  394. {
  395. if (tmp->prev)
  396. tmp->prev->next = tmp->next;
  397. if (tmp->next)
  398. tmp->next->prev = tmp->prev;
  399. if (list == tmp)
  400. list = list->next;
  401. _g_list_free_1 (tmp);
  402. break;
  403. }
  404. }
  405. return list;
  406. }
  407. g_list_t* g_list_remove_all (g_list_t *list, const void *data) {
  408. g_list_t *tmp = list;
  409. while (tmp)
  410. {
  411. if (tmp->data != data)
  412. tmp = tmp->next;
  413. else
  414. {
  415. g_list_t *next = tmp->next;
  416. if (tmp->prev)
  417. tmp->prev->next = next;
  418. else
  419. list = next;
  420. if (next)
  421. next->prev = tmp->prev;
  422. _g_list_free_1 (tmp);
  423. tmp = next;
  424. }
  425. }
  426. return list;
  427. }
  428. static inline g_list_t* _g_list_remove_link (g_list_t *list, g_list_t *link) {
  429. if (link)
  430. {
  431. if (link->prev)
  432. link->prev->next = link->next;
  433. if (link->next)
  434. link->next->prev = link->prev;
  435. if (link == list)
  436. list = list->next;
  437. link->next = NULL;
  438. link->prev = NULL;
  439. }
  440. return list;
  441. }
  442. g_list_t* g_list_remove_link (g_list_t *list, g_list_t *link) {
  443. return _g_list_remove_link (list, link);
  444. }
  445. g_list_t* g_list_delete_link (g_list_t *list, g_list_t *link) {
  446. list = _g_list_remove_link (list, link);
  447. _g_list_free_1 (link);
  448. return list;
  449. }
  450. g_list_t* g_list_copy (g_list_t *list) {
  451. g_list_t *new_list = NULL;
  452. if (list)
  453. {
  454. g_list_t *last;
  455. new_list = _g_list_new ();
  456. new_list->data = list->data;
  457. last = new_list;
  458. list = list->next;
  459. while (list)
  460. {
  461. last->next = _g_list_new ();
  462. last->next->prev = last;
  463. last = last->next;
  464. last->data = list->data;
  465. list = list->next;
  466. }
  467. }
  468. return new_list;
  469. }
  470. g_list_t* g_list_reverse (g_list_t *list) {
  471. g_list_t *last;
  472. last = NULL;
  473. while (list)
  474. {
  475. last = list;
  476. list = last->next;
  477. last->next = last->prev;
  478. last->prev = list;
  479. }
  480. return last;
  481. }
  482. g_list_t* g_list_nth (g_list_t *list, unsigned int n) {
  483. while ((n-- > 0) && list)
  484. list = list->next;
  485. return list;
  486. }
  487. g_list_t* g_list_nth_prev (g_list_t *list, unsigned int n) {
  488. while ((n-- > 0) && list)
  489. list = list->prev;
  490. return list;
  491. }
  492. void* g_list_nth_data (g_list_t *list, unsigned int n) {
  493. while ((n-- > 0) && list)
  494. list = list->next;
  495. return list ? list->data : NULL;
  496. }
  497. g_list_t* g_list_find (g_list_t *list, const void *data) {
  498. while (list)
  499. {
  500. if (list->data == data)
  501. break;
  502. list = list->next;
  503. }
  504. return list;
  505. }
  506. g_list_t* g_list_find_custom (g_list_t *list, const void *data, list_compare func) {
  507. while (list)
  508. {
  509. if (! func (list->data, data))
  510. return list;
  511. list = list->next;
  512. }
  513. return NULL;
  514. }
  515. int g_list_position (g_list_t *list, g_list_t *link) {
  516. int i;
  517. i = 0;
  518. while (list)
  519. {
  520. if (list == link)
  521. return i;
  522. i++;
  523. list = list->next;
  524. }
  525. return -1;
  526. }
  527. int g_list_index (g_list_t *list, const void *data) {
  528. int i;
  529. i = 0;
  530. while (list)
  531. {
  532. if (list->data == data)
  533. return i;
  534. i++;
  535. list = list->next;
  536. }
  537. return -1;
  538. }
  539. g_list_t* g_list_last (g_list_t *list) {
  540. if (list)
  541. {
  542. while (list->next)
  543. list = list->next;
  544. }
  545. return list;
  546. }
  547. g_list_t* g_list_first (g_list_t *list) {
  548. if (list)
  549. {
  550. while (list->prev)
  551. list = list->prev;
  552. }
  553. return list;
  554. }
  555. unsigned int g_list_length (g_list_t *list) {
  556. unsigned int length;
  557. length = 0;
  558. while (list)
  559. {
  560. length++;
  561. list = list->next;
  562. }
  563. return length;
  564. }
  565. void g_list_foreach (g_list_t *list, list_func func, void *user_data) {
  566. while (list)
  567. {
  568. g_list_t *next = list->next;
  569. (*func) (list->data, user_data);
  570. list = next;
  571. }
  572. }
  573. g_list_t* g_list_insert_sorted (g_list_t *list, void *data, list_compare func) {
  574. g_list_t *tmp_list = list;
  575. g_list_t *new_list;
  576. int cmp;
  577. if (!func) return list;
  578. if (!list)
  579. {
  580. new_list = _g_list_new ();
  581. new_list->data = data;
  582. return new_list;
  583. }
  584. cmp = (*func) (data, tmp_list->data);
  585. while ((tmp_list->next) && (cmp > 0))
  586. {
  587. tmp_list = tmp_list->next;
  588. cmp = (*func) (data, tmp_list->data);
  589. }
  590. new_list = _g_list_new ();
  591. new_list->data = data;
  592. if ((!tmp_list->next) && (cmp > 0))
  593. {
  594. tmp_list->next = new_list;
  595. new_list->prev = tmp_list;
  596. return list;
  597. }
  598. if (tmp_list->prev)
  599. {
  600. tmp_list->prev->next = new_list;
  601. new_list->prev = tmp_list->prev;
  602. }
  603. new_list->next = tmp_list;
  604. tmp_list->prev = new_list;
  605. if (tmp_list == list)
  606. return new_list;
  607. else
  608. return list;
  609. }
  610. static g_list_t *g_list_sort_merge (g_list_t *l1, g_list_t *l2, list_func compare_func,
  611. int use_data, void *user_data) {
  612. g_list_t list, *l, *lprev;
  613. int cmp;
  614. l = &list;
  615. lprev = NULL;
  616. while (l1 && l2)
  617. {
  618. if (use_data)
  619. cmp = ((list_compare_data) compare_func) (l1->data, l2->data, user_data);
  620. else
  621. cmp = ((list_compare) compare_func) (l1->data, l2->data);
  622. if (cmp <= 0)
  623. {
  624. l->next = l1;
  625. l = l->next;
  626. l->prev = lprev;
  627. lprev = l;
  628. l1 = l1->next;
  629. }
  630. else
  631. {
  632. l->next = l2;
  633. l = l->next;
  634. l->prev = lprev;
  635. lprev = l;
  636. l2 = l2->next;
  637. }
  638. }
  639. l->next = l1 ? l1 : l2;
  640. l->next->prev = l;
  641. return list.next;
  642. }
  643. static g_list_t* g_list_sort_real (g_list_t *list, list_func compare_func,
  644. int use_data, void *user_data) {
  645. g_list_t *l1, *l2;
  646. if (!list)
  647. return NULL;
  648. if (!list->next)
  649. return list;
  650. l1 = list;
  651. l2 = list->next;
  652. while ((l2 = l2->next) != NULL)
  653. {
  654. if ((l2 = l2->next) == NULL)
  655. break;
  656. l1 = l1->next;
  657. }
  658. l2 = l1->next;
  659. l1->next = NULL;
  660. return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
  661. g_list_sort_real (l2, compare_func, use_data, user_data),
  662. compare_func,
  663. use_data,
  664. user_data);
  665. }
  666. g_list_t *g_list_sort (g_list_t *list, list_compare compare_func) {
  667. return g_list_sort_real (list, (list_func) compare_func, 0, NULL);
  668. }
  669. g_list_t * g_list_sort_with_data (g_list_t *list, list_compare compare_func, void *user_data) {
  670. return g_list_sort_real (list, (list_func) compare_func, 1, user_data);
  671. }
  672. #if 0
  673. static g_list_t* g_list_sort2 (g_list_t *list, list_compare compare_func) {
  674. g_list_t *runs = NULL;
  675. g_list_t *tmp;
  676. /* Degenerate case. */
  677. if (!list) return NULL;
  678. /* Assume: list = [12,2,4,11,2,4,6,1,1,12]. */
  679. for (tmp = list; tmp; )
  680. {
  681. g_list_t *tmp2;
  682. for (tmp2 = tmp;
  683. tmp2->next && compare_func (tmp2->data, tmp2->next->data) <= 0;
  684. tmp2 = tmp2->next)
  685. /* Nothing */;
  686. runs = g_list_append (runs, tmp);
  687. tmp = tmp2->next;
  688. tmp2->next = NULL;
  689. }
  690. /* Now: runs = [[12],[2,4,11],[2,4,6],[1,1,12]]. */
  691. while (runs->next)
  692. {
  693. /* We have more than one run. Merge pairwise. */
  694. g_list_t *dst, *src, *dstprev = NULL;
  695. dst = src = runs;
  696. while (src && src->next)
  697. {
  698. dst->data = g_list_sort_merge (src->data,
  699. src->next->data,
  700. (list_func) compare_func,
  701. 0, NULL);
  702. dstprev = dst;
  703. dst = dst->next;
  704. src = src->next->next;
  705. }
  706. /* If number of runs was odd, just keep the last. */
  707. if (src)
  708. {
  709. dst->data = src->data;
  710. dstprev = dst;
  711. dst = dst->next;
  712. }
  713. dstprev->next = NULL;
  714. g_list_free (dst);
  715. }
  716. /* After 1st loop: runs = [[2,4,11,12],[1,1,2,4,6,12]]. */
  717. /* After 2nd loop: runs = [[1,1,2,2,4,4,6,11,12,12]]. */
  718. list = runs->data;
  719. g_list_free (runs);
  720. return list;
  721. }
  722. #endif