search.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2021, the SerenityOS developers.
  3. * Copyright (c) 2021, Tim Schumacher <timschumi@gmx.de>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Format.h>
  8. #include <bits/search.h>
  9. #include <search.h>
  10. struct search_tree_node* new_tree_node(void const* key)
  11. {
  12. auto* node = static_cast<struct search_tree_node*>(malloc(sizeof(struct search_tree_node)));
  13. if (!node)
  14. return nullptr;
  15. node->key = key;
  16. node->left = nullptr;
  17. node->right = nullptr;
  18. return node;
  19. }
  20. void delete_node_recursive(struct search_tree_node* node)
  21. {
  22. if (!node)
  23. return;
  24. delete_node_recursive(node->left);
  25. delete_node_recursive(node->right);
  26. free(node);
  27. }
  28. extern "C" {
  29. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/tsearch.html
  30. void* tsearch(void const* key, void** rootp, int (*comparator)(void const*, void const*))
  31. {
  32. if (!rootp)
  33. return nullptr;
  34. if (!*rootp) {
  35. *rootp = new_tree_node(key);
  36. return *rootp;
  37. }
  38. auto node = static_cast<struct search_tree_node*>(*rootp);
  39. while (node != nullptr) {
  40. auto comp = comparator(key, node->key);
  41. if (comp < 0 && node->left) {
  42. node = node->left;
  43. } else if (comp < 0 && !node->left) {
  44. node->left = new_tree_node(key);
  45. return node->left;
  46. } else if (comp > 0 && node->right) {
  47. node = node->right;
  48. } else if (comp > 0 && !node->right) {
  49. node->right = new_tree_node(key);
  50. return node->right;
  51. } else {
  52. return node;
  53. }
  54. }
  55. VERIFY_NOT_REACHED();
  56. }
  57. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/tfind.html
  58. void* tfind(void const* key, void* const* rootp, int (*comparator)(void const*, void const*))
  59. {
  60. if (!rootp)
  61. return nullptr;
  62. auto node = static_cast<struct search_tree_node*>(*rootp);
  63. while (node != nullptr) {
  64. auto comp = comparator(key, node->key);
  65. if (comp < 0)
  66. node = node->left;
  67. else if (comp > 0)
  68. node = node->right;
  69. else
  70. return node;
  71. }
  72. return nullptr;
  73. }
  74. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/tdelete.html
  75. void* tdelete(void const*, void**, int (*)(void const*, void const*))
  76. {
  77. dbgln("FIXME: Implement tdelete()");
  78. return nullptr;
  79. }
  80. static void twalk_internal(const struct search_tree_node* node, void (*action)(void const*, VISIT, int), int depth)
  81. {
  82. if (!node)
  83. return;
  84. if (!node->right && !node->left) {
  85. action(node, leaf, depth);
  86. return;
  87. }
  88. action(node, preorder, depth);
  89. twalk_internal(node->left, action, depth + 1);
  90. action(node, postorder, depth);
  91. twalk_internal(node->right, action, depth + 1);
  92. action(node, endorder, depth);
  93. }
  94. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/twalk.html
  95. void twalk(void const* rootp, void (*action)(void const*, VISIT, int))
  96. {
  97. auto node = static_cast<const struct search_tree_node*>(rootp);
  98. twalk_internal(node, action, 0);
  99. }
  100. }