intlist.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Based on intlist.c by:
  4. * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
  5. */
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <linux/compiler.h>
  9. #include "intlist.h"
  10. static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
  11. const void *entry)
  12. {
  13. int i = (int)((long)entry);
  14. struct rb_node *rc = NULL;
  15. struct int_node *node = malloc(sizeof(*node));
  16. if (node != NULL) {
  17. node->i = i;
  18. node->priv = NULL;
  19. rc = &node->rb_node;
  20. }
  21. return rc;
  22. }
  23. static void int_node__delete(struct int_node *ilist)
  24. {
  25. free(ilist);
  26. }
  27. static void intlist__node_delete(struct rblist *rblist __maybe_unused,
  28. struct rb_node *rb_node)
  29. {
  30. struct int_node *node = container_of(rb_node, struct int_node, rb_node);
  31. int_node__delete(node);
  32. }
  33. static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
  34. {
  35. int i = (int)((long)entry);
  36. struct int_node *node = container_of(rb_node, struct int_node, rb_node);
  37. return node->i - i;
  38. }
  39. int intlist__add(struct intlist *ilist, int i)
  40. {
  41. return rblist__add_node(&ilist->rblist, (void *)((long)i));
  42. }
  43. void intlist__remove(struct intlist *ilist, struct int_node *node)
  44. {
  45. rblist__remove_node(&ilist->rblist, &node->rb_node);
  46. }
  47. static struct int_node *__intlist__findnew(struct intlist *ilist,
  48. int i, bool create)
  49. {
  50. struct int_node *node = NULL;
  51. struct rb_node *rb_node;
  52. if (ilist == NULL)
  53. return NULL;
  54. if (create)
  55. rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
  56. else
  57. rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
  58. if (rb_node)
  59. node = container_of(rb_node, struct int_node, rb_node);
  60. return node;
  61. }
  62. struct int_node *intlist__find(struct intlist *ilist, int i)
  63. {
  64. return __intlist__findnew(ilist, i, false);
  65. }
  66. struct int_node *intlist__findnew(struct intlist *ilist, int i)
  67. {
  68. return __intlist__findnew(ilist, i, true);
  69. }
  70. static int intlist__parse_list(struct intlist *ilist, const char *s)
  71. {
  72. char *sep;
  73. int err;
  74. do {
  75. long value = strtol(s, &sep, 10);
  76. err = -EINVAL;
  77. if (*sep != ',' && *sep != '\0')
  78. break;
  79. err = intlist__add(ilist, value);
  80. if (err)
  81. break;
  82. s = sep + 1;
  83. } while (*sep != '\0');
  84. return err;
  85. }
  86. struct intlist *intlist__new(const char *slist)
  87. {
  88. struct intlist *ilist = malloc(sizeof(*ilist));
  89. if (ilist != NULL) {
  90. rblist__init(&ilist->rblist);
  91. ilist->rblist.node_cmp = intlist__node_cmp;
  92. ilist->rblist.node_new = intlist__node_new;
  93. ilist->rblist.node_delete = intlist__node_delete;
  94. if (slist && intlist__parse_list(ilist, slist))
  95. goto out_delete;
  96. }
  97. return ilist;
  98. out_delete:
  99. intlist__delete(ilist);
  100. return NULL;
  101. }
  102. void intlist__delete(struct intlist *ilist)
  103. {
  104. if (ilist != NULL)
  105. rblist__delete(&ilist->rblist);
  106. }
  107. struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
  108. {
  109. struct int_node *node = NULL;
  110. struct rb_node *rb_node;
  111. rb_node = rblist__entry(&ilist->rblist, idx);
  112. if (rb_node)
  113. node = container_of(rb_node, struct int_node, rb_node);
  114. return node;
  115. }