File indexing completed on 2024-04-06 12:02:32
0001 #pragma once
0002
0003 #include <typeinfo>
0004 #include <type_traits>
0005
0006 #include <algorithm>
0007
0008 #include <string>
0009 #include <bitset>
0010 #include <utility>
0011 #include <tuple>
0012 #include <memory>
0013 #include <array>
0014 #include <vector>
0015 #include <deque>
0016 #include <forward_list>
0017 #include <list>
0018 #include <set>
0019 #include <unordered_set>
0020 #include <map>
0021 #include <unordered_map>
0022
0023 #include <cstddef>
0024 #include <cmath>
0025
0026 #include "CondFormats/Serialization/interface/Serializable.h"
0027
0028 namespace cond {
0029 namespace serialization {
0030
0031 template <typename T>
0032 bool equal(const T& first, const T& second) {
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 return access<T>::equal_(first, second);
0044 }
0045
0046 template <typename T>
0047 struct access<T, typename std::enable_if<std::is_integral<T>::value or std::is_enum<T>::value>::type> {
0048 static bool equal_(const T first, const T second) { return first == second; }
0049 };
0050
0051 template <typename T>
0052 struct access<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
0053 static bool equal_(const T first, const T second) {
0054
0055 if (std::isnan(first) or std::isnan(second))
0056 return std::isnan(first) and std::isnan(second);
0057
0058 if (std::isinf(first) or std::isinf(second))
0059 return std::isinf(first) and std::isinf(second) and std::signbit(first) == std::signbit(second);
0060
0061
0062 return first == second;
0063 }
0064 };
0065
0066 template <>
0067 struct access<std::string> {
0068 static bool equal_(const std::string& first, const std::string& second) { return first == second; }
0069 };
0070
0071 template <std::size_t N>
0072 struct access<std::bitset<N>> {
0073 static bool equal_(const std::bitset<N>& first, const std::bitset<N>& second) { return first == second; }
0074 };
0075
0076 template <typename T, typename U>
0077 struct access<std::pair<T, U>> {
0078 static bool equal_(const std::pair<T, U>& first, const std::pair<T, U>& second) {
0079 return equal(first.first, second.first) and equal(first.second, second.second);
0080 }
0081 };
0082
0083 template <std::size_t N, typename... Ts>
0084 struct equal_tuple {
0085 static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) {
0086 if (not equal(std::get<N - 1>(first), std::get<N - 1>(second)))
0087 return false;
0088
0089 return equal_tuple<N - 1, Ts...>::equal_(first, second);
0090 }
0091 };
0092
0093 template <typename... Ts>
0094 struct equal_tuple<0, Ts...> {
0095 static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) { return true; }
0096 };
0097
0098 template <typename... Ts>
0099 struct access<std::tuple<Ts...>> {
0100 static bool equal_(const std::tuple<Ts...>& first, const std::tuple<Ts...>& second) {
0101 return equal_tuple<sizeof...(Ts), Ts...>::equal_(first, second);
0102 }
0103 };
0104
0105 template <typename T>
0106 struct access<T, typename std::enable_if<std::is_pointer<T>::value>::type> {
0107 static bool equal_(const T first, const T second) {
0108 if (first == nullptr or second == nullptr)
0109 return first == second;
0110
0111
0112
0113
0114
0115 return first == second or equal(*first, *second);
0116 }
0117 };
0118
0119 #define equal_pointer(TYPE) \
0120 template <typename T> \
0121 struct access<TYPE<T>> { \
0122 static bool equal_(const TYPE<T>& first, const TYPE<T>& second) { return equal(first.get(), second.get()); } \
0123 };
0124
0125 equal_pointer(std::unique_ptr);
0126 equal_pointer(std::shared_ptr);
0127 #undef equal_pointer
0128
0129 template <typename T, std::size_t N>
0130 struct access<T[N]> {
0131 static bool equal_(const T (&first)[N], const T (&second)[N]) {
0132 for (std::size_t i = 0; i < N; ++i)
0133 if (not equal(first[i], second[i]))
0134 return false;
0135 return true;
0136 }
0137 };
0138
0139 template <typename T, std::size_t N>
0140 struct access<std::array<T, N>> {
0141 static bool equal_(const std::array<T, N>& first, const std::array<T, N>& second) {
0142 for (std::size_t i = 0; i < N; ++i)
0143 if (not equal(first[i], second[i]))
0144 return false;
0145 return true;
0146 }
0147 };
0148
0149 #define equal_sequence(TYPE) \
0150 template <typename T> \
0151 struct access<TYPE<T>> { \
0152 static bool equal_(const TYPE<T>& first, const TYPE<T>& second) { \
0153 return first.size() == second.size() && \
0154 std::equal(first.cbegin(), \
0155 first.cend(), \
0156 second.cbegin(), \
0157 [](decltype(*first.cbegin()) a, decltype(*first.cbegin()) b) -> bool { return equal(a, b); }); \
0158 } \
0159 };
0160
0161 equal_sequence(std::vector);
0162 equal_sequence(std::deque);
0163 equal_sequence(std::list);
0164 equal_sequence(std::set);
0165 equal_sequence(std::multiset);
0166 #undef equal_sequence
0167
0168
0169
0170 template <typename T>
0171 struct access<std::forward_list<T>> {
0172 static bool equal_(const std::forward_list<T>& first, const std::forward_list<T>& second) {
0173 auto first_it = first.cbegin();
0174 auto second_it = second.cbegin();
0175
0176 while (first_it != first.cend() and second_it != second.cend()) {
0177 if (not equal(*first_it, *second_it))
0178 return false;
0179 first_it++;
0180 second_it++;
0181 }
0182
0183 return first_it == first.cend() and second_it == second.cend();
0184 }
0185 };
0186
0187
0188 #define equal_mapping(TYPE) \
0189 template <typename T, typename U> \
0190 struct access<TYPE<T, U>> { \
0191 static bool equal_(const TYPE<T, U>& first, const TYPE<T, U>& second) { \
0192 return first.size() == second.size() && \
0193 std::equal(first.cbegin(), \
0194 first.cend(), \
0195 second.cbegin(), \
0196 [](decltype(*first.cbegin()) a, decltype(*first.cbegin()) b) -> bool { return equal(a, b); }); \
0197 } \
0198 };
0199
0200 equal_mapping(std::map);
0201 #undef equal_mapping
0202
0203 #define equal_unorderedmapping(TYPE) \
0204 template <typename T, typename U> \
0205 struct access<TYPE<T, U>> { \
0206 static bool equal_(const TYPE<T, U>& first, const TYPE<T, U>& second) { \
0207 if (first.size() != second.size()) \
0208 return false; \
0209 \
0210 auto first_it = first.cbegin(); \
0211 while (first_it != first.cend()) { \
0212 auto second_it = second.find(first_it->first); \
0213 if (second_it == second.cend()) \
0214 return false; \
0215 if (not equal(first_it->second, second_it->second)) \
0216 return false; \
0217 first_it++; \
0218 } \
0219 return true; \
0220 } \
0221 };
0222
0223 equal_unorderedmapping(std::unordered_map);
0224 #undef equal_unorderedmapping
0225
0226 }
0227 }