File indexing completed on 2025-09-17 08:33:45
0001 #ifndef BOOST_HASH2_SIPHASH_HPP_INCLUDED
0002 #define BOOST_HASH2_SIPHASH_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010 #include <boost/hash2/detail/read.hpp>
0011 #include <boost/hash2/detail/rot.hpp>
0012 #include <boost/hash2/detail/memcpy.hpp>
0013 #include <boost/hash2/detail/memset.hpp>
0014 #include <boost/hash2/detail/config.hpp>
0015 #include <boost/assert.hpp>
0016 #include <cstdint>
0017 #include <cstring>
0018 #include <cstddef>
0019
0020 namespace boost
0021 {
0022 namespace hash2
0023 {
0024
0025 class siphash_64
0026 {
0027 private:
0028
0029 std::uint64_t v0 = 0x736f6d6570736575ULL;
0030 std::uint64_t v1 = 0x646f72616e646f6dULL;
0031 std::uint64_t v2 = 0x6c7967656e657261ULL;
0032 std::uint64_t v3 = 0x7465646279746573ULL;
0033
0034 unsigned char buffer_[ 8 ] = {};
0035 std::size_t m_ = 0;
0036
0037 std::uint64_t n_ = 0;
0038
0039 private:
0040
0041 BOOST_CXX14_CONSTEXPR void sipround()
0042 {
0043 v0 += v1;
0044 v1 = detail::rotl(v1, 13);
0045 v1 ^= v0;
0046 v0 = detail::rotl(v0, 32);
0047 v2 += v3;
0048 v3 = detail::rotl(v3, 16);
0049 v3 ^= v2;
0050 v0 += v3;
0051 v3 = detail::rotl(v3, 21);
0052 v3 ^= v0;
0053 v2 += v1;
0054 v1 = detail::rotl(v1, 17);
0055 v1 ^= v2;
0056 v2 = detail::rotl(v2, 32);
0057 }
0058
0059 BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p )
0060 {
0061 std::uint64_t m = detail::read64le( p );
0062
0063 v3 ^= m;
0064
0065 sipround();
0066 sipround();
0067
0068 v0 ^= m;
0069 }
0070
0071 public:
0072
0073 using result_type = std::uint64_t;
0074
0075 siphash_64() = default;
0076
0077 BOOST_CXX14_CONSTEXPR explicit siphash_64( std::uint64_t seed )
0078 {
0079 v0 ^= seed;
0080 v2 ^= seed;
0081 }
0082
0083 BOOST_CXX14_CONSTEXPR siphash_64( unsigned char const * p, std::size_t n )
0084 {
0085 if( n == 16 )
0086 {
0087 std::uint64_t k0 = detail::read64le( p + 0 );
0088 std::uint64_t k1 = detail::read64le( p + 8 );
0089
0090 v0 ^= k0;
0091 v1 ^= k1;
0092 v2 ^= k0;
0093 v3 ^= k1;
0094 }
0095 else if( n != 0 )
0096 {
0097 update( p, n );
0098 result();
0099 }
0100 }
0101
0102 siphash_64( void const * p, std::size_t n ): siphash_64( static_cast<unsigned char const*>( p ), n )
0103 {
0104 }
0105
0106 BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0107 {
0108 BOOST_ASSERT( m_ == n_ % 8 );
0109
0110 if( n == 0 ) return;
0111
0112 n_ += n;
0113
0114 if( m_ > 0 )
0115 {
0116 std::size_t k = 8 - m_;
0117
0118 if( n < k )
0119 {
0120 k = n;
0121 }
0122
0123 detail::memcpy( buffer_ + m_, p, k );
0124
0125 p += k;
0126 n -= k;
0127 m_ += k;
0128
0129 if( m_ < 8 ) return;
0130
0131 BOOST_ASSERT( m_ == 8 );
0132
0133 update_( buffer_ );
0134 m_ = 0;
0135
0136
0137 detail::memset( buffer_, 0, 8 );
0138 }
0139
0140 BOOST_ASSERT( m_ == 0 );
0141
0142 while( n >= 8 )
0143 {
0144 update_( p );
0145
0146 p += 8;
0147 n -= 8;
0148 }
0149
0150 BOOST_ASSERT( n < 8 );
0151
0152 if( n > 0 )
0153 {
0154 detail::memcpy( buffer_, p, n );
0155 m_ = n;
0156 }
0157
0158 BOOST_ASSERT( m_ == n_ % 8 );
0159 }
0160
0161 void update( void const* pv, std::size_t n )
0162 {
0163 unsigned char const* p = static_cast<unsigned char const*>( pv );
0164 update( p, n );
0165 }
0166
0167 BOOST_CXX14_CONSTEXPR std::uint64_t result()
0168 {
0169 BOOST_ASSERT( m_ == n_ % 8 );
0170
0171 detail::memset( buffer_ + m_, 0, 8 - m_ );
0172
0173 buffer_[ 7 ] = static_cast<unsigned char>( n_ & 0xFF );
0174
0175 update_( buffer_ );
0176
0177 v2 ^= 0xFF;
0178
0179 sipround();
0180 sipround();
0181 sipround();
0182 sipround();
0183
0184 n_ += 8 - m_;
0185 m_ = 0;
0186
0187
0188 detail::memset( buffer_, 0, 8 );
0189
0190 return v0 ^ v1 ^ v2 ^ v3;
0191 }
0192 };
0193
0194 class siphash_32
0195 {
0196 private:
0197
0198 std::uint32_t v0 = 0;
0199 std::uint32_t v1 = 0;
0200 std::uint32_t v2 = 0x6c796765;
0201 std::uint32_t v3 = 0x74656462;
0202
0203 unsigned char buffer_[ 4 ] = {};
0204 std::uint32_t m_ = 0;
0205
0206 std::uint32_t n_ = 0;
0207
0208 private:
0209
0210 BOOST_CXX14_CONSTEXPR void sipround()
0211 {
0212 v0 += v1;
0213 v1 = detail::rotl(v1, 5);
0214 v1 ^= v0;
0215 v0 = detail::rotl(v0, 16);
0216 v2 += v3;
0217 v3 = detail::rotl(v3, 8);
0218 v3 ^= v2;
0219 v0 += v3;
0220 v3 = detail::rotl(v3, 7);
0221 v3 ^= v0;
0222 v2 += v1;
0223 v1 = detail::rotl(v1, 13);
0224 v1 ^= v2;
0225 v2 = detail::rotl(v2, 16);
0226 }
0227
0228 BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p )
0229 {
0230 std::uint32_t m = detail::read32le( p );
0231
0232 v3 ^= m;
0233
0234 sipround();
0235 sipround();
0236
0237 v0 ^= m;
0238 }
0239
0240 public:
0241
0242 using result_type = std::uint32_t;
0243
0244 siphash_32() = default;
0245
0246 BOOST_CXX14_CONSTEXPR explicit siphash_32( std::uint64_t seed )
0247 {
0248 std::uint32_t k0 = static_cast<std::uint32_t>( seed );
0249 std::uint32_t k1 = static_cast<std::uint32_t>( seed >> 32 );
0250
0251 v0 ^= k0;
0252 v1 ^= k1;
0253 v2 ^= k0;
0254 v3 ^= k1;
0255 }
0256
0257 BOOST_CXX14_CONSTEXPR siphash_32( unsigned char const * p, std::size_t n )
0258 {
0259 if( n == 8 )
0260 {
0261 std::uint32_t k0 = detail::read32le( p + 0 );
0262 std::uint32_t k1 = detail::read32le( p + 4 );
0263
0264 v0 ^= k0;
0265 v1 ^= k1;
0266 v2 ^= k0;
0267 v3 ^= k1;
0268 }
0269 else if( n != 0 )
0270 {
0271 update( p, n );
0272 result();
0273 }
0274 }
0275
0276 siphash_32( void const * p, std::size_t n ): siphash_32( static_cast<unsigned char const*>( p ), n )
0277 {
0278 }
0279
0280 BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0281 {
0282 BOOST_ASSERT( m_ == n_ % 4 );
0283
0284 if( n == 0 ) return;
0285
0286 n_ += static_cast<std::uint32_t>( n );
0287
0288 if( m_ > 0 )
0289 {
0290 std::uint32_t k = 4 - m_;
0291
0292 if( n < k )
0293 {
0294 k = static_cast<std::uint32_t>( n );
0295 }
0296
0297 detail::memcpy( buffer_ + m_, p, k );
0298
0299 p += k;
0300 n -= k;
0301 m_ += k;
0302
0303 if( m_ < 4 ) return;
0304
0305 BOOST_ASSERT( m_ == 4 );
0306
0307 update_( buffer_ );
0308 m_ = 0;
0309
0310
0311 detail::memset( buffer_, 0, 4 );
0312 }
0313
0314 BOOST_ASSERT( m_ == 0 );
0315
0316 while( n >= 4 )
0317 {
0318 update_( p );
0319
0320 p += 4;
0321 n -= 4;
0322 }
0323
0324 BOOST_ASSERT( n < 4 );
0325
0326 if( n > 0 )
0327 {
0328 detail::memcpy( buffer_, p, n );
0329 m_ = static_cast<std::uint32_t>( n );
0330 }
0331
0332 BOOST_ASSERT( m_ == n_ % 4 );
0333 }
0334
0335 void update( void const* pv, std::size_t n )
0336 {
0337 unsigned char const* p = static_cast<unsigned char const*>( pv );
0338 update( p, n );
0339 }
0340
0341 BOOST_CXX14_CONSTEXPR std::uint32_t result()
0342 {
0343 BOOST_ASSERT( m_ == n_ % 4 );
0344
0345 detail::memset( buffer_ + m_, 0, 4 - m_ );
0346
0347 buffer_[ 3 ] = static_cast<unsigned char>( n_ & 0xFF );
0348
0349 update_( buffer_ );
0350
0351 v2 ^= 0xFF;
0352
0353 sipround();
0354 sipround();
0355 sipround();
0356 sipround();
0357
0358 n_ += 4 - m_;
0359 m_ = 0;
0360
0361
0362 detail::memset( buffer_, 0, 4 );
0363
0364 return v1 ^ v3;
0365 }
0366 };
0367
0368 }
0369 }
0370
0371 #endif