SGPath: add comparison operators (<, >, <=, >=) and an std::hash specialization
This allows one to use SGPath in containers such as std::map, std::unordered_map and std::unordered_set. Like the existing == and !=, all these operators rely solely on the UTF-8 internal representation of the path.
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@@ -286,6 +290,49 @@ void test_permissions()
|
||||
SG_CHECK_EQUAL(fileInRW.canWrite(), false);
|
||||
}
|
||||
|
||||
void test_comparisons()
|
||||
{
|
||||
std::cout << "Testing comparisons\n";
|
||||
|
||||
SG_CHECK_EQUAL(SGPath("/abc/def ghi"), SGPath("/abc/def ghi"));
|
||||
SG_CHECK_NE(SGPath("/abc"), SGPath("abc"));
|
||||
SG_CHECK_LT(SGPath(""), SGPath("/"));
|
||||
SG_CHECK_LT(SGPath("A"), SGPath("a"));
|
||||
SG_CHECK_LE(SGPath(""), SGPath("/"));
|
||||
SG_CHECK_LE(SGPath("/"), SGPath("/"));
|
||||
SG_CHECK_GT(SGPath("a"), SGPath("A"));
|
||||
SG_CHECK_GE(SGPath("a"), SGPath("A"));
|
||||
SG_CHECK_GE(SGPath("a"), SGPath("a"));
|
||||
|
||||
std::vector<SGPath> origVector({
|
||||
std::string("/zer/gh/tr aze"),
|
||||
std::string("/abc/def/ttt"),
|
||||
std::string("/abc/def/ddd"),
|
||||
std::string("/a"),
|
||||
std::string("")});
|
||||
std::vector<SGPath> sortedVector({
|
||||
std::string(""),
|
||||
std::string("/a"),
|
||||
std::string("/abc/def/ddd"),
|
||||
std::string("/abc/def/ttt"),
|
||||
std::string("/zer/gh/tr aze")});
|
||||
|
||||
std::sort(origVector.begin(), origVector.end());
|
||||
SG_CHECK_EQUAL_NOSTREAM(origVector, sortedVector);
|
||||
}
|
||||
|
||||
void test_hash_function()
|
||||
{
|
||||
std::cout << "Testing the std::hash<SGPath> specialization\n";
|
||||
|
||||
const SGPath nullPath{};
|
||||
const SGPath p{"/abc/def"};
|
||||
|
||||
SG_CHECK_EQUAL(std::hash<SGPath>{}(nullPath), std::hash<SGPath>{}(nullPath));
|
||||
SG_CHECK_EQUAL(std::hash<SGPath>{}(p), std::hash<SGPath>{}(p));
|
||||
SG_CHECK_NE(std::hash<SGPath>{}(p), std::hash<SGPath>{}(p / "foobar"));
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SGPath pa;
|
||||
@@ -389,12 +436,11 @@ int main(int argc, char* argv[])
|
||||
SG_CHECK_EQUAL(pp.canWrite(), false);
|
||||
|
||||
test_dir();
|
||||
|
||||
test_path_dir();
|
||||
|
||||
test_path_dir();
|
||||
test_permissions();
|
||||
|
||||
test_update_dir();
|
||||
test_update_dir();
|
||||
test_comparisons();
|
||||
test_hash_function();
|
||||
|
||||
cout << "all tests passed OK" << endl;
|
||||
return 0; // passed
|
||||
|
||||
@@ -742,6 +742,18 @@ bool SGPath::operator!=(const SGPath& other) const
|
||||
return (path != other.path);
|
||||
}
|
||||
|
||||
bool operator<(const SGPath& lhs, const SGPath& rhs)
|
||||
{ return lhs.path < rhs.path; }
|
||||
|
||||
bool operator>(const SGPath& lhs, const SGPath& rhs)
|
||||
{ return operator<(rhs, lhs); }
|
||||
|
||||
bool operator<=(const SGPath& lhs, const SGPath& rhs)
|
||||
{ return !operator>(lhs, rhs); }
|
||||
|
||||
bool operator>=(const SGPath& lhs, const SGPath& rhs)
|
||||
{ return !operator<(lhs, rhs); }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool SGPath::rename(const SGPath& newName)
|
||||
{
|
||||
|
||||
@@ -28,12 +28,14 @@
|
||||
#ifndef _SG_PATH_HXX
|
||||
#define _SG_PATH_HXX
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -91,6 +93,8 @@ public:
|
||||
|
||||
bool operator==(const SGPath& other) const;
|
||||
bool operator!=(const SGPath& other) const;
|
||||
// Other comparison operators are declared below
|
||||
friend bool operator<(const SGPath& lhs, const SGPath& rhs);
|
||||
|
||||
void setPermissionChecker(PermissionChecker validator);
|
||||
PermissionChecker getPermissionChecker() const;
|
||||
@@ -349,6 +353,24 @@ private:
|
||||
mutable size_t _size;
|
||||
};
|
||||
|
||||
// Other comparison operators are in the class definition block
|
||||
bool operator> (const SGPath& lhs, const SGPath& rhs);
|
||||
bool operator<=(const SGPath& lhs, const SGPath& rhs);
|
||||
bool operator>=(const SGPath& lhs, const SGPath& rhs);
|
||||
|
||||
// Hash function for SGPath
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<SGPath>
|
||||
{
|
||||
std::size_t operator()(const SGPath& path) const noexcept
|
||||
{
|
||||
return std::hash<std::string>{}(path.utf8Str());
|
||||
}
|
||||
};
|
||||
} // of namespace std
|
||||
|
||||
/// Output to an ostream
|
||||
template<typename char_type, typename traits_type>
|
||||
inline
|
||||
|
||||
Reference in New Issue
Block a user