/* Copyright 2015, Michele Santullo * This file is part of DoorKeeper. * * DoorKeeper is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DoorKeeper is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DoorKeeper. If not, see . */ #ifndef id440C878EF94C4468948A57610C7C9B5A #define id440C878EF94C4468948A57610C7C9B5A #include "doorkeeper/primitivetypes.hpp" #include "doorkeeper/implem/dktypes.hpp" #include #include namespace dk { namespace implem { template struct uint_t { typedef typename int_t::type type; }; template =M) or (N%CHAR_BIT==0)> struct RoundToInt { private: enum { v = (N < M ? (N < CHAR_BIT ? CHAR_BIT : N) : M) }; static_assert(v > 0, "v must be greater than 0"); public: enum { value = ((((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) | ((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) >> 4)) | (((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) | ((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) >> 4)) >> 8)) | ((((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) | ((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) >> 4)) | (((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) | ((((v - 1) | ((v - 1) >> 1)) | (((v - 1) | ((v - 1) >> 1)) >> 2)) >> 4)) >> 8)) >> 16)) + 1 }; static_assert(value <= M, "value must be smaller than M"); static_assert(value and not (value bitand (value - 1)), "value must be a power of two"); }; template struct FillBits; template struct FillBits { enum { value = 1 bitor (FillBits::value << 1) }; }; template <> struct FillBits<0> { enum { value = 0 }; }; } //namespace implem template class SaltedID { static_assert(Salt + Indx <= 64, "Only indices up to 64 bits are currently supported"); public: enum { bit_size = implem::RoundToInt::value, max_index = implem::FillBits::value, max_salt = implem::FillBits::value }; private: typedef typename implem::uint_t::type compound_type; public: typedef typename implem::uint_t::value>::type salt_type; typedef typename implem::uint_t::value>::type index_type; SaltedID ( void ) = default; SaltedID ( const SaltedID& ) = default; SaltedID ( SaltedID&& parOther ); SaltedID ( index_type parIndex, salt_type parSalt ) : m_data(pack_index_salt(parIndex, parSalt)) { DK_ASSERT(index() == parIndex); DK_ASSERT(salt() == parSalt); } salt_type salt ( void ) const; index_type index ( void ) const; SaltedID& operator+= ( index_type parOther ) { m_data = pack_index_salt(index() + parOther, salt()); return *this; } SaltedID& operator-= ( index_type parOther ) { m_data = pack_index_salt(index() - parOther, salt()); return *this; } SaltedID& operator= ( const SaltedID& parOther ) = default; private: static compound_type pack_index_salt ( index_type parIndex, salt_type parSalt ); compound_type m_data; }; template SaltedID::SaltedID (SaltedID&& parOther) { std::swap(m_data, parOther.m_data); } template auto SaltedID::salt() const -> salt_type { return static_cast(m_data bitand implem::FillBits::value); } template auto SaltedID::index() const -> index_type { return static_cast(m_data >> Salt); } template auto SaltedID::pack_index_salt (index_type parIndex, salt_type parSalt) -> compound_type { DK_ASSERT(parIndex <= max_index); DK_ASSERT(parSalt <= max_salt); return (static_cast(parIndex) << Salt) bitor parSalt; } template inline bool operator< (const SaltedID& parLeft, const SaltedID& parRight) { return parLeft.index() < parRight.index(); } template inline SaltedID operator+ (SaltedID parLeft, typename SaltedID::index_type parRight) { return (parLeft += parRight); } template inline SaltedID operator+ (typename SaltedID::index_type parLeft, SaltedID parRight) { return (parRight += parLeft); } template inline SaltedID operator- (SaltedID parLeft, typename SaltedID::index_type parRight) { return (parLeft -= parRight); } template inline SaltedID operator- (typename SaltedID::index_type parLeft, SaltedID parRight) { return (parRight -= parLeft); } } //namespace dk #endif