diff --git a/Chaos/Padding/PadderPkcs7.hpp b/Chaos/Padding/PadderPkcs7.hpp index 479e404..59d31e4 100644 --- a/Chaos/Padding/PadderPkcs7.hpp +++ b/Chaos/Padding/PadderPkcs7.hpp @@ -1,14 +1,13 @@ #ifndef CHAOS_PADDING_PADDERPKCS7_HPP #define CHAOS_PADDING_PADDERPKCS7_HPP -#include #include #include #include #include -#include #include "Padding/Padder.hpp" +#include "Service/Branchless.hpp" #include "Service/ChaosException.hpp" namespace Chaos::Padding @@ -51,7 +50,7 @@ public: } const uint8_t padSize = *std::prev(end); - uint8_t isOkay = ~BlIsZero(padSize); + uint8_t isOkay = ~Branchless::IsZero(padSize); size_t suffixSize = 0; InputIt it = end; @@ -60,89 +59,21 @@ public: --it; ++suffixSize; - isOkay &= (BlEq(*it, padSize) | - BlGt(suffixSize, padSize)); + isOkay &= (Branchless::Eq(*it, padSize) | + Branchless::Gt(suffixSize, padSize)); } - isOkay &= BlGe(suffixSize, padSize); + isOkay &= Branchless::Ge(suffixSize, padSize); return { .IsOkay_ = static_cast(isOkay), - .PadSize_ = BlSel(isOkay, padSize, 0) + .PadSize_ = Branchless::Sel(isOkay, padSize, 0) }; } private: - template - static constexpr OutUInt BlMsb(InUInt in) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - - constexpr uint8_t shift = (sizeof(InUInt) * CHAR_BIT) - 1; - return static_cast(0) - (in >> shift); - } - - template - static constexpr OutUInt BlLt(InUInt lhs, InUInt rhs) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - static_assert(sizeof(InUInt) <= sizeof(uint64_t)); - - const uint64_t lhsEx = lhs; - const uint64_t rhsEx = rhs; - - return BlMsb(lhsEx ^ ((lhsEx ^ rhsEx) | ((lhsEx - rhsEx) ^ lhsEx))); - } - - template - static constexpr OutUInt BlIsZero(InUInt in) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - static_assert(sizeof(InUInt) <= sizeof(uint64_t)); - - const uint64_t inEx = in; - - return BlMsb(~inEx & (inEx - 1U)); - } - - template - static constexpr OutUInt BlEq(InUInt lhs, InUInt rhs) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - - return BlIsZero(lhs ^ rhs); - } - - template - static constexpr OutUInt BlGe(InUInt lhs, InUInt rhs) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - - return ~BlLt(lhs, rhs); - } - - template - static constexpr OutUInt BlGt(InUInt lhs, InUInt rhs) noexcept - { - static_assert(std::is_unsigned_v && - std::is_unsigned_v); - - return BlLt(rhs, lhs); - } - - template - static constexpr UInt BlSel(UInt mask, UInt onTrue, UInt onFalse) noexcept - { - static_assert(std::is_unsigned_v); - - return (mask & onTrue) | (~mask & onFalse); - } + using Branchless = Service::Branchless; }; } // namespace Chaos::Padding diff --git a/Chaos/Service/Branchless.hpp b/Chaos/Service/Branchless.hpp new file mode 100644 index 0000000..5e8336f --- /dev/null +++ b/Chaos/Service/Branchless.hpp @@ -0,0 +1,86 @@ +#ifndef CHAOS_SERVICE_BRANCHLESS_HPP +#define CHAOS_SERVICE_BRANCHLESS_HPP + +#include +#include +#include + +namespace Chaos::Service +{ + +struct Branchless +{ + template + static constexpr OutUInt Msb(InUInt in) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + + constexpr uint8_t shift = (sizeof(InUInt) * CHAR_BIT) - 1; + return static_cast(0) - (in >> shift); + } + + template + static constexpr OutUInt Lt(InUInt lhs, InUInt rhs) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + static_assert(sizeof(InUInt) <= sizeof(uint64_t)); + + const uint64_t lhsEx = lhs; + const uint64_t rhsEx = rhs; + + return Msb(lhsEx ^ ((lhsEx ^ rhsEx) | ((lhsEx - rhsEx) ^ lhsEx))); + } + + template + static constexpr OutUInt IsZero(InUInt in) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + static_assert(sizeof(InUInt) <= sizeof(uint64_t)); + + const uint64_t inEx = in; + + return Msb(~inEx & (inEx - 1U)); + } + + template + static constexpr OutUInt Eq(InUInt lhs, InUInt rhs) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + + return IsZero(lhs ^ rhs); + } + + template + static constexpr OutUInt Ge(InUInt lhs, InUInt rhs) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + + return ~Lt(lhs, rhs); + } + + template + static constexpr OutUInt Gt(InUInt lhs, InUInt rhs) noexcept + { + static_assert(std::is_unsigned_v && + std::is_unsigned_v); + + return Lt(rhs, lhs); + } + + template + static constexpr UInt Sel(UInt mask, UInt onTrue, UInt onFalse) noexcept + { + static_assert(std::is_unsigned_v); + + return (mask & onTrue) | (~mask & onFalse); + } +}; + +} // namespace Chaos::Service + +#endif // CHAOS_SERVICE_BRANCHLESS_HPP