algorithm.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include <QtCore/QLatin1String>
  9. #include <QtCore/QString>
  10. #include <memory>
  11. namespace base {
  12. template <typename Type>
  13. inline constexpr Type take(Type &value) noexcept {
  14. return std::exchange(value, Type {});
  15. }
  16. template <typename Type>
  17. inline constexpr Type duplicate(const Type &value) {
  18. return value;
  19. }
  20. template <typename Type, size_t Size>
  21. inline constexpr size_t array_size(const Type(&)[Size]) noexcept {
  22. return Size;
  23. }
  24. template <typename Container, typename T>
  25. inline bool contains(const Container &container, const T &value) {
  26. const auto end = std::end(container);
  27. return std::find(std::begin(container), end, value) != end;
  28. }
  29. template <typename Container>
  30. inline void reorder(Container &container, int oldPosition, int newPosition) {
  31. const auto b = container.begin();
  32. if (oldPosition < newPosition) {
  33. std::rotate(
  34. b + oldPosition,
  35. b + oldPosition + 1,
  36. b + newPosition + 1);
  37. } else if (newPosition < oldPosition) {
  38. std::rotate(
  39. b + newPosition,
  40. b + oldPosition,
  41. b + oldPosition + 1);
  42. }
  43. }
  44. [[nodiscard]] inline int reorder_index(
  45. int index,
  46. int oldPosition,
  47. int newPosition) {
  48. return (index == oldPosition)
  49. ? newPosition
  50. : (oldPosition < index && index <= newPosition)
  51. ? (index - 1)
  52. : (oldPosition > index && index >= newPosition)
  53. ? (index + 1)
  54. : index;
  55. }
  56. template <typename D, typename T>
  57. inline constexpr D up_cast(T object) {
  58. using DV = std::decay_t<decltype(*D())>;
  59. using TV = std::decay_t<decltype(*T())>;
  60. if constexpr (std::is_base_of_v<DV, TV>) {
  61. return object;
  62. } else {
  63. return nullptr;
  64. }
  65. }
  66. // We need a custom comparator for set<std::unique_ptr<T>>::find to work with pointers.
  67. // thanks to http://stackoverflow.com/questions/18939882/raw-pointer-lookup-for-sets-of-unique-ptrs
  68. template <typename T>
  69. struct pointer_comparator {
  70. using is_transparent = std::true_type;
  71. // helper does some magic in order to reduce the number of
  72. // pairs of types we need to know how to compare: it turns
  73. // everything into a pointer, and then uses `std::less<T*>`
  74. // to do the comparison:
  75. struct helper {
  76. const T *ptr = nullptr;
  77. helper() = default;
  78. helper(const helper &other) = default;
  79. helper(const T *p) : ptr(p) {
  80. }
  81. template <typename ...Ts>
  82. helper(const std::shared_ptr<Ts...> &other) : ptr(other.get()) {
  83. }
  84. template <typename ...Ts>
  85. helper(const std::unique_ptr<Ts...> &other) : ptr(other.get()) {
  86. }
  87. bool operator<(helper other) const {
  88. return std::less<const T*>()(ptr, other.ptr);
  89. }
  90. };
  91. // without helper, we'd need 2^n different overloads, where
  92. // n is the number of types we want to support (so, 8 with
  93. // raw pointers, unique pointers, and shared pointers). That
  94. // seems silly.
  95. // && helps enforce rvalue use only
  96. bool operator()(const helper &&lhs, const helper &&rhs) const {
  97. return lhs < rhs;
  98. }
  99. };
  100. inline QString FromUtf8Safe(const char *string, int size = -1) {
  101. if (!string || !size) {
  102. return QString();
  103. } else if (size < 0) {
  104. size = strlen(string);
  105. }
  106. const auto result = QString::fromUtf8(string, size);
  107. const auto back = result.toUtf8();
  108. return (back.size() != size || memcmp(back.constData(), string, size))
  109. ? QString::fromLocal8Bit(string, size)
  110. : result;
  111. }
  112. inline QString FromUtf8Safe(const QByteArray &string) {
  113. return FromUtf8Safe(string.constData(), string.size());
  114. }
  115. [[nodiscard]] double SafeRound(double value);
  116. [[nodiscard]] QString CleanAndSimplify(QString text);
  117. template <typename T>
  118. [[nodiscard]] bool OppositeSigns(T a, T b) {
  119. // For zero returns false!
  120. return (a < 0 && b > 0) || (a > 0 && b < 0);
  121. }
  122. } // namespace base
  123. template <typename T>
  124. inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; }
  125. template <typename T>
  126. inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; }
  127. template <size_t Size>
  128. QLatin1String qstr(const char(&string)[Size]) {
  129. return QLatin1String(string, int(Size) - 1);
  130. }