qsort.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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(SizedObject const& a, SizedObject const& b)
  27. {
  28. VERIFY(a.size() == b.size());
  29. size_t const size = a.size();
  30. auto const a_data = reinterpret_cast<char*>(a.data());
  31. auto const 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. SizedObject const 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. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/qsort.html
  54. void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(void const*, void const*))
  55. {
  56. if (nmemb <= 1) {
  57. return;
  58. }
  59. SizedObjectSlice slice { bot, size };
  60. AK::dual_pivot_quick_sort(slice, 0, nmemb - 1, [=](SizedObject const& a, SizedObject const& b) { return compar(a.data(), b.data()) < 0; });
  61. }
  62. void qsort_r(void* bot, size_t nmemb, size_t size, int (*compar)(void const*, void const*, void*), void* arg)
  63. {
  64. if (nmemb <= 1) {
  65. return;
  66. }
  67. SizedObjectSlice slice { bot, size };
  68. AK::dual_pivot_quick_sort(slice, 0, nmemb - 1, [=](SizedObject const& a, SizedObject const& b) { return compar(a.data(), b.data(), arg) < 0; });
  69. }