p2p/lib/dt_p2p/stingray_sdk/plugin_foundation/pair.h

179 lines
5.6 KiB
C++

#pragma once
#include <algorithm>
#include "allocator.h"
#include "template_tools.h"
namespace stingray_plugin_foundation {
// A replacement for std::pair that is allocator aware, so that any
// of the pair members that need to be constructed with an allocator is.
//
// The default template implementation is used when none of the types
// are allocator aware.
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
struct Pair {
typedef Pair<FIRST, SECOND, firstaware, secondaware> this_type;
typedef FIRST first_type;
typedef SECOND second_type;
Pair() : first(first_type()), second(second_type()) {}
Pair(Allocator &) : first(first_type()), second(second_type()) {}
Pair(const this_type &t) : first(t.first), second(t.second) {}
Pair(const first_type &f, const second_type &s) : first(f), second(s) {}
void swap(this_type &right) {
std::swap(first, right.first);
std::swap(second, right.second);
}
template <class STREAM> void serialize(STREAM &s) {s & first & second;}
first_type first;
second_type second;
};
// Template specialization to use when the first type is allocator aware.
template <class FIRST, class SECOND>
struct Pair<FIRST, SECOND, true, false>
{
ALLOCATOR_AWARE;
typedef Pair<FIRST, SECOND, true, false> this_type;
typedef FIRST first_type;
typedef SECOND second_type;
Pair(Allocator &a) : first(a), second(second_type()) {}
Pair(const first_type &f, const second_type &s) : first(f), second(s) {}
void swap(this_type &right) {
std::swap(first, right.first);
std::swap(second, right.second);
}
template <class STREAM> void serialize(STREAM &s) {s & first & second;}
first_type first;
second_type second;
};
// Template specialization to use when the second type is allocator aware.
template <class FIRST, class SECOND>
struct Pair<FIRST, SECOND, false, true>
{
ALLOCATOR_AWARE;
typedef Pair<FIRST, SECOND, false, true> this_type;
typedef FIRST first_type;
typedef SECOND second_type;
Pair(Allocator &a) : first(first_type()), second(a) {}
Pair(const first_type &f, const second_type &s) : first(f), second(s) {}
void swap(this_type &right) {
std::swap(first, right.first);
std::swap(second, right.second);
}
template <class STREAM> void serialize(STREAM &s) {s & first & second;}
first_type first;
second_type second;
};
// Template specialization to use when both types are allocator aware.
template <class FIRST, class SECOND>
struct Pair<FIRST, SECOND, true, true>
{
ALLOCATOR_AWARE;
typedef Pair<FIRST, SECOND, true, true> this_type;
typedef FIRST first_type;
typedef SECOND second_type;
Pair(Allocator &a) : first(a), second(a) {}
Pair(const first_type &f, const second_type &s) : first(f), second(s) {}
void swap(this_type &right) {
std::swap(first, right.first);
std::swap(second, right.second);
}
template <class STREAM> void serialize(STREAM &s) {s & first & second;}
first_type first;
second_type second;
};
// Comparison operators.
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator==(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return left.first == right.first && left.second == right.second;
}
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator!=(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return !(left == right);
}
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator<(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return left.first < right.first ||
(!(right.first < left.first) && left.second < right.second);
}
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator>(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return (right < left);
}
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator<=(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return !(right < left);
}
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
bool operator>=(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
return !(left < right);
}
// make_pair function that constructs a Pair of the right type
template <class FIRST, class SECOND>
Pair<FIRST, SECOND, IS_ALLOCATOR_AWARE(FIRST), IS_ALLOCATOR_AWARE(SECOND)> make_pair(const FIRST &f, const SECOND &s)
{
return Pair<FIRST, SECOND, IS_ALLOCATOR_AWARE(FIRST), IS_ALLOCATOR_AWARE(SECOND)>(f, s);
}
// swap implementation for Pair
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
void swap(const Pair<FIRST,SECOND,firstaware,secondaware> &left,
const Pair<FIRST,SECOND,firstaware,secondaware> &right) {
left.swap(right);
}
// Declaration needed for GCC-based compilers
unsigned murmur_hash( const void * key, int len, unsigned seed );
// Pair hashing
template <class HASH_FIRST, class HASH_SECOND = HASH_FIRST>
struct pair_hash
{
template <class FIRST, class SECOND, bool firstaware, bool secondaware>
unsigned operator()(const Pair<FIRST, SECOND, firstaware, secondaware> &pair) const
{
HASH_FIRST hash_first;
HASH_SECOND hash_second;
const unsigned result[2] = { hash_first(pair.first), hash_second(pair.second) };
const unsigned hash = murmur_hash(&result[0], sizeof(result), 0);
return hash;
}
};
} // namespace stingray_plugin_foundation