java-topology/defects/endless-sky-0001/patch/endless-sky-0001.patch

62 lines
1.6 KiB
Diff

# UNDF: UNDF-2026-000000973
--- a/source/comparators/ByGivenOrder.h
+++ b/source/comparators/ByGivenOrder.h
@@ -16,8 +16,9 @@
#pragma once
-#include <algorithm>
+#include <cstddef>
+#include <unordered_map>
#include <vector>
@@ -26,18 +27,24 @@
template<class T>
class ByGivenOrder {
public:
- explicit ByGivenOrder(const std::vector<T> &order)
- : order(order)
- {}
+ explicit ByGivenOrder(const std::vector<T> &order)
+ {
+ // Pre-build a hash map from value to index for O(1) lookup.
+ // Original code used std::find() on the vector, which is O(N)
+ // per comparison, making any sort O(N^2 log N).
+ indexMap.reserve(order.size());
+ for(std::size_t i = 0; i < order.size(); ++i)
+ indexMap.emplace(order[i], i);
+ }
bool operator()(const T &a, const T &b) const
{
- const auto findA = std::find(order.begin(), order.end(), a);
- const auto findB = std::find(order.begin(), order.end(), b);
+ const auto findA = indexMap.find(a);
+ const auto findB = indexMap.find(b);
- if(findA == order.end() && findB == order.end())
+ if(findA == indexMap.end() && findB == indexMap.end())
{
// Neither a nor b is a known value. Fall back to default comparison.
return a < b;
@@ -45,12 +52,12 @@
else
{
// Whichever is first in the array is considered smaller.
- return findA < findB;
+ // Unknown values (end iterator) sort after all known values.
+ if(findA == indexMap.end())
+ return false;
+ if(findB == indexMap.end())
+ return true;
+ return findA->second < findB->second;
}
}
@@ -58,5 +65,5 @@
private:
- const std::vector<T> &order;
+ std::unordered_map<T, std::size_t> indexMap;
};