diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h
index 8959a766b..05be881ee 100644
--- a/library/include/MiscUtils.h
+++ b/library/include/MiscUtils.h
@@ -66,36 +66,116 @@ void print_bits ( T val, DFHack::Console& out )
out.print(strs.str().c_str());
}
-//FIXME: Error 8 error C4519: default template arguments are only allowed on a class template
-template
-CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value)
+/*
+ * Binary search in vectors.
+ */
+
+template
+int binsearch_index(const std::vector &vec, FT key, bool exact = true)
+{
+ // Returns the index of the value >= the key
+ int min = -1, max = (int)vec.size();
+ const FT *p = vec.data();
+ for (;;)
+ {
+ int mid = (min + max)>>1;
+ if (mid == min)
+ return exact ? -1 : max;
+ FT midv = p[mid];
+ if (midv == key)
+ return mid;
+ else if (midv < key)
+ min = mid;
+ else
+ max = mid;
+ }
+}
+
+template
+int binsearch_index(const std::vector &vec, FT CT::*field, FT key, bool exact = true)
{
+ // Returns the index of the value >= the key
int min = -1, max = (int)vec.size();
- CT **p = vec.data();
- FT key = (FT)value;
+ CT *const *p = vec.data();
for (;;)
{
int mid = (min + max)>>1;
if (mid == min)
- {
- return NULL;
- }
+ return exact ? -1 : max;
FT midv = p[mid]->*field;
if (midv == key)
- {
- return p[mid];
- }
+ return mid;
else if (midv < key)
- {
min = mid;
- }
else
- {
max = mid;
- }
}
}
+template
+inline int binsearch_index(const std::vector &vec, typename CT::key_field_type key, bool exact = true)
+{
+ return CT::binsearch_index(vec, key, exact);
+}
+
+template
+inline int binsearch_index(const std::vector &vec, typename CT::key_pointer_type key, bool exact = true)
+{
+ return CT::binsearch_index(vec, key, exact);
+}
+
+template
+inline bool vector_contains(const std::vector &vec, KT key)
+{
+ return binsearch_index(vec, key) >= 0;
+}
+
+template
+inline bool vector_contains(const std::vector &vec, FT CT::*field, FT key)
+{
+ return binsearch_index(vec, field, key) >= 0;
+}
+
+template
+unsigned insert_into_vector(std::vector &vec, FT key, bool *inserted = NULL)
+{
+ unsigned pos = (unsigned)binsearch_index(vec, key, false);
+ bool to_ins = (pos >= vec.size() || vec[pos] != key);
+ if (inserted) *inserted = to_ins;
+ if (to_ins)
+ vec.insert(vec.begin()+pos,key);
+ return pos;
+}
+
+template
+unsigned insert_into_vector(std::vector &vec, FT CT::*field, CT *obj, bool *inserted = NULL)
+{
+ unsigned pos = (unsigned)binsearch_index(vec, field, obj->*field, false);
+ bool to_ins = (pos >= vec.size() || vec[pos] != obj);
+ if (inserted) *inserted = to_ins;
+ if (to_ins)
+ vec.insert(vec.begin()+pos,obj);
+ return pos;
+}
+
+template
+CT *binsearch_in_vector(const std::vector &vec, KT value)
+{
+ int idx = binsearch_index(vec, value);
+ return idx < 0 ? NULL : vec[idx];
+}
+
+template
+CT *binsearch_in_vector(const std::vector &vec, FT CT::*field, FT value)
+{
+ int idx = binsearch_index(vec, field, value);
+ return idx < 0 ? NULL : vec[idx];
+}
+
+/*
+ * MISC
+ */
+
/**
* Returns the amount of milliseconds elapsed since the UNIX epoch.
* Works on both windows and linux.
diff --git a/library/xml b/library/xml
index 7b89e5958..c99be2349 160000
--- a/library/xml
+++ b/library/xml
@@ -1 +1 @@
-Subproject commit 7b89e595811ed81b012a805131aa10a89d451e76
+Subproject commit c99be2349fef32db026af7541676e2e4f24e4636