qsort.cpp 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Assertions.h>
  7. #include <AK/QuickSort.h>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. class SizedObject {
  11. public:
  12. SizedObject() = delete;
  13. SizedObject(void* data, size_t size)
  14. : m_data(data)
  15. , m_size(size)
  16. {
  17. }
  18. void* data() const { return m_data; }
  19. size_t size() const { return m_size; }
  20. private:
  21. void* m_data;
  22. size_t m_size;
  23. };
  24. namespace AK {
  25. template<>
  26. inline void swap(const SizedObject& a, const SizedObject& b)
  27. {
  28. VERIFY(a.size() == b.size());
  29. const size_t size = a.size();
  30. const auto a_data = reinterpret_cast<char*>(a.data());
  31. const auto b_data = reinterpret_cast<char*>(b.data());
  32. for (auto i = 0u; i < size; ++i) {
  33. swap(a_data[i], b_data[i]);
  34. }
  35. }
  36. }
  37. class SizedObjectSlice {
  38. public:
  39. SizedObjectSlice() = delete;
  40. SizedObjectSlice(void* data, size_t element_size)
  41. : m_data(data)
  42. , m_element_size(element_size)
  43. {
  44. }
  45. const SizedObject operator[](size_t index)
  46. {
  47. return { static_cast<char*>(m_data) + index * m_element_size, m_element_size };
  48. }
  49. private:
  50. void* m_data;
  51. size_t m_element_size;
  52. };
  53. void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*))
  54. {
  55. if (nmemb <= 1) {
  56. return;
  57. }
  58. SizedObjectSlice slice { bot, size };
  59. AK::dual_pivot_quick_sort(slice, 0, nmemb - 1, [=](const SizedObject& a, const SizedObject& b) { return compar(a.data(), b.data()) < 0; });
  60. }
  61. void qsort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg)
  62. {
  63. if (nmemb <= 1) {
  64. return;
  65. }
  66. SizedObjectSlice slice { bot, size };
  67. AK::dual_pivot_quick_sort(slice, 0, nmemb - 1, [=](const SizedObject& a, const SizedObject& b) { return compar(a.data(), b.data(), arg) < 0; });
  68. }