File indexing completed on 2026-08-17 08:39:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_BLOOM_FILTER_HPP
0012 #define BOOST_BLOOM_FILTER_HPP
0013
0014 #include <boost/bloom/block.hpp>
0015 #include <boost/bloom/detail/bloom_printers.hpp>
0016 #include <boost/bloom/detail/core.hpp>
0017 #include <boost/bloom/detail/mulx64.hpp>
0018 #include <boost/bloom/detail/type_traits.hpp>
0019 #include <boost/config.hpp>
0020 #include <boost/container_hash/hash.hpp>
0021 #include <boost/container_hash/hash_is_avalanching.hpp>
0022 #include <boost/core/allocator_traits.hpp>
0023 #include <boost/core/empty_value.hpp>
0024 #include <cstdint>
0025 #include <initializer_list>
0026 #include <iterator>
0027 #include <memory>
0028 #include <type_traits>
0029 #include <utility>
0030
0031 namespace boost{
0032 namespace bloom{
0033 namespace detail{
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 struct no_mix_policy
0046 {
0047 template<typename Hash,typename T>
0048
0049 static inline std::uint64_t mix(const Hash& h,const T& x)
0050 {
0051 return (std::uint64_t)h(x);
0052 }
0053 };
0054
0055 struct mulx64_mix_policy
0056 {
0057 template<typename Hash,typename T>
0058
0059 static inline std::uint64_t mix(const Hash& h,const T& x)
0060 {
0061 return mulx64((std::uint64_t)h(x));
0062 }
0063 };
0064
0065 }
0066
0067 #if defined(BOOST_MSVC)
0068 #pragma warning(push)
0069 #pragma warning(disable:4714)
0070 #endif
0071
0072 template<
0073 typename T,std::size_t K,
0074 typename Subfilter=block<unsigned char,1>,std::size_t Stride=0,
0075 typename Hash=boost::hash<T>,typename Allocator=std::allocator<unsigned char>
0076 >
0077 class
0078
0079 #if defined(_MSC_VER)&&_MSC_FULL_VER>=190023918
0080 __declspec(empty_bases)
0081 #endif
0082
0083 filter:
0084 detail::filter_core<
0085 K,Subfilter,Stride,allocator_rebind_t<Allocator,unsigned char>
0086 >,
0087 empty_value<Hash,0>
0088 {
0089 BOOST_BLOOM_STATIC_ASSERT_IS_CV_UNQUALIFIED_OBJECT(T);
0090 static_assert(
0091 std::is_same<unsigned char,allocator_value_type_t<Allocator>>::value,
0092 "Allocator's value_type must be unsigned char");
0093 using super=detail::filter_core<K,Subfilter,Stride,Allocator>;
0094 using mix_policy=typename std::conditional<
0095 boost::hash_is_avalanching<Hash>::value&&
0096 sizeof(std::size_t)>=sizeof(std::uint64_t),
0097 detail::no_mix_policy,
0098 detail::mulx64_mix_policy
0099 >::type;
0100
0101 public:
0102 using value_type=T;
0103 using super::k;
0104 using subfilter=typename super::subfilter;
0105 using super::stride;
0106 using hasher=Hash;
0107 using allocator_type=Allocator;
0108 using size_type=typename super::size_type;
0109 using difference_type=typename super::difference_type;
0110 using reference=value_type&;
0111 using const_reference=const value_type&;
0112 using pointer=value_type*;
0113 using const_pointer=const value_type*;
0114 static constexpr std::size_t bulk_insert_size=super::bulk_insert_size;
0115 static constexpr std::size_t bulk_may_contain_size=
0116 super::bulk_may_contain_size;
0117
0118 filter()=default;
0119
0120 explicit filter(
0121 std::size_t m,const hasher& h=hasher(),
0122 const allocator_type& al=allocator_type()):
0123 super{m,al},hash_base{empty_init,h}{}
0124
0125 filter(
0126 std::size_t n,double fpr,const hasher& h=hasher(),
0127 const allocator_type& al=allocator_type()):
0128 super{n,fpr,al},hash_base{empty_init,h}{}
0129
0130 template<typename InputIterator>
0131 filter(
0132 InputIterator first,InputIterator last,
0133 std::size_t m,const hasher& h=hasher(),
0134 const allocator_type& al=allocator_type()):
0135 filter{m,h,al}
0136 {
0137 insert(first,last);
0138 }
0139
0140 template<typename InputIterator>
0141 filter(
0142 InputIterator first,InputIterator last,
0143 std::size_t n,double fpr,const hasher& h=hasher(),
0144 const allocator_type& al=allocator_type()):
0145 filter{n,fpr,h,al}
0146 {
0147 insert(first,last);
0148 }
0149
0150 filter(const filter&)=default;
0151 filter(filter&&)=default;
0152
0153 template<typename InputIterator>
0154 filter(
0155 InputIterator first,InputIterator last,
0156 std::size_t m,const allocator_type& al):
0157 filter{first,last,m,hasher(),al}{}
0158
0159 template<typename InputIterator>
0160 filter(
0161 InputIterator first,InputIterator last,
0162 std::size_t n,double fpr,const allocator_type& al):
0163 filter{first,last,n,fpr,hasher(),al}{}
0164
0165 explicit filter(const allocator_type& al):filter{0,al}{}
0166
0167 filter(const filter& x,const allocator_type& al):
0168 super{x,al},hash_base{empty_init,x.h()}{}
0169
0170 filter(filter&& x,const allocator_type& al):
0171 super{std::move(x),al},hash_base{empty_init,std::move(x.h())}{}
0172
0173 filter(
0174 std::initializer_list<value_type> il,
0175 std::size_t m,const hasher& h=hasher(),
0176 const allocator_type& al=allocator_type()):
0177 filter{il.begin(),il.end(),m,h,al}{}
0178
0179 filter(
0180 std::initializer_list<value_type> il,
0181 std::size_t n,double fpr,const hasher& h=hasher(),
0182 const allocator_type& al=allocator_type()):
0183 filter{il.begin(),il.end(),n,fpr,h,al}{}
0184
0185 filter(std::size_t m,const allocator_type& al):
0186 filter{m,hasher(),al}{}
0187
0188 filter(std::size_t n,double fpr,const allocator_type& al):
0189 filter{n,fpr,hasher(),al}{}
0190
0191 filter(
0192 std::initializer_list<value_type> il,
0193 std::size_t m,const allocator_type& al):
0194 filter{il.begin(),il.end(),m,hasher(),al}{}
0195
0196 filter(
0197 std::initializer_list<value_type> il,
0198 std::size_t n,double fpr,const allocator_type& al):
0199 filter{il.begin(),il.end(),n,fpr,hasher(),al}{}
0200
0201 filter& operator=(const filter& x)
0202 {
0203 BOOST_BLOOM_STATIC_ASSERT_IS_NOTHROW_SWAPPABLE(Hash);
0204 using std::swap;
0205
0206 auto x_h=x.h();
0207 super::operator=(x);
0208 swap(h(),x_h);
0209 return *this;
0210 }
0211
0212 filter& operator=(filter&& x)
0213 noexcept(noexcept(std::declval<super&>()=(std::declval<super&&>())))
0214 {
0215 BOOST_BLOOM_STATIC_ASSERT_IS_NOTHROW_SWAPPABLE(Hash);
0216 using std::swap;
0217
0218 super::operator=(std::move(x));
0219 swap(h(),x.h());
0220 return *this;
0221 }
0222
0223 filter& operator=(std::initializer_list<value_type> il)
0224 {
0225 clear();
0226 insert(il);
0227 return *this;
0228 }
0229
0230 using super::get_allocator;
0231 using super::capacity;
0232 using super::capacity_for;
0233 using super::fpr_for;
0234 using super::array;
0235
0236 BOOST_FORCEINLINE void insert(const T& x)
0237 {
0238 super::insert(hash_for(x));
0239 }
0240
0241 template<
0242 typename U,
0243 typename H=hasher,detail::enable_if_transparent_t<H>* =nullptr
0244 >
0245 BOOST_FORCEINLINE void insert(const U& x)
0246 {
0247 super::insert(hash_for(x));
0248 }
0249
0250 template<typename InputIterator>
0251 void insert(InputIterator first,InputIterator last)
0252 {
0253 insert_impl(
0254 first,last,
0255 std::integral_constant<
0256 bool,detail::is_forward_iterator<InputIterator>::value>{});
0257 }
0258
0259 void insert(std::initializer_list<value_type> il)
0260 {
0261 insert(il.begin(),il.end());
0262 }
0263
0264 void swap(filter& x)
0265 noexcept(noexcept(std::declval<super&>().swap(std::declval<super&>())))
0266 {
0267 BOOST_BLOOM_STATIC_ASSERT_IS_NOTHROW_SWAPPABLE(Hash);
0268 using std::swap;
0269
0270 super::swap(x);
0271 swap(h(),x.h());
0272 }
0273
0274 using super::clear;
0275 using super::reset;
0276
0277 filter& operator&=(const filter& x)
0278 {
0279 super::operator&=(x);
0280 return *this;
0281 }
0282
0283 filter& operator|=(const filter& x)
0284 {
0285 super::operator|=(x);
0286 return *this;
0287 }
0288
0289 hasher hash_function()const
0290 {
0291 return h();
0292 }
0293
0294 BOOST_FORCEINLINE bool may_contain(const T& x)const
0295 {
0296 return super::may_contain(hash_for(x));
0297 }
0298
0299 template<
0300 typename U,
0301 typename H=hasher,detail::enable_if_transparent_t<H>* =nullptr
0302 >
0303 BOOST_FORCEINLINE bool may_contain(const U& x)const
0304 {
0305 return super::may_contain(hash_for(x));
0306 }
0307
0308 template<typename ForwardIterator,typename F>
0309 void may_contain(
0310 ForwardIterator first,ForwardIterator last,F f)const
0311 {
0312 BOOST_BLOOM_STATIC_ASSERT_IS_FORWARD_ITERATOR(ForwardIterator);
0313
0314 super::bulk_may_contain(
0315 [this,first]()mutable{return promoting_hash_for(*first++);},
0316 static_cast<std::size_t>(std::distance(first,last)),
0317 [&f,first](bool res)mutable{f(*first++,res);});
0318 }
0319
0320 private:
0321 template<
0322 typename T1,std::size_t K1,typename SF,std::size_t S,typename H,typename A
0323 >
0324 bool friend operator==(
0325 const filter<T1,K1,SF,S,H,A>& x,const filter<T1,K1,SF,S,H,A>& y);
0326
0327 using hash_base=empty_value<Hash,0>;
0328
0329 const Hash& h()const{return hash_base::get();}
0330 Hash& h(){return hash_base::get();}
0331
0332 template<typename U>
0333
0334 inline std::uint64_t hash_for(const U& x)const
0335 {
0336 return mix_policy::mix(h(),x);
0337 }
0338
0339
0340
0341
0342
0343
0344 inline std::uint64_t promoting_hash_for(const T& x)const
0345 {
0346 return hash_for(x);
0347 }
0348
0349 template<
0350 typename U,
0351 typename H=hasher,detail::enable_if_transparent_t<H>* =nullptr
0352 >
0353
0354 inline std::uint64_t promoting_hash_for(const U& x)const
0355 {
0356 return hash_for(x);
0357 }
0358
0359 template<typename Iterator>
0360 void insert_impl(
0361 Iterator first,Iterator last,std::false_type )
0362 {
0363 while(first!=last)insert(*first++);
0364 }
0365
0366 template<typename Iterator>
0367 void insert_impl(
0368 Iterator first,Iterator last,std::true_type )
0369 {
0370 super::bulk_insert(
0371 [this,first]()mutable{return promoting_hash_for(*first++);},
0372 static_cast<std::size_t>(std::distance(first,last)));
0373 }
0374 };
0375
0376 template<
0377 typename T,std::size_t K,typename SF,std::size_t S,typename H,typename A
0378 >
0379 bool operator==(const filter<T,K,SF,S,H,A>& x,const filter<T,K,SF,S,H,A>& y)
0380 {
0381 using super=typename filter<T,K,SF,S,H,A>::super;
0382 return static_cast<const super&>(x)==static_cast<const super&>(y);
0383 }
0384
0385 template<
0386 typename T,std::size_t K,typename SF,std::size_t S,typename H,typename A
0387 >
0388 bool operator!=(const filter<T,K,SF,S,H,A>& x,const filter<T,K,SF,S,H,A>& y)
0389 {
0390 return !(x==y);
0391 }
0392
0393 template<
0394 typename T,std::size_t K,typename SF,std::size_t S,typename H,typename A
0395 >
0396 void swap(filter<T,K,SF,S,H,A>& x,filter<T,K,SF,S,H,A>& y)
0397 noexcept(noexcept(x.swap(y)))
0398 {
0399 x.swap(y);
0400 }
0401
0402 #if defined(BOOST_MSVC)
0403 #pragma warning(pop)
0404 #endif
0405
0406 }
0407 }
0408 #endif