#ifndef SPROUT_CHECKSUM_SUM_HPP #define SPROUT_CHECKSUM_SUM_HPP #include #include #include #include #include #include #include #include #include #include #include namespace sprout { static_assert(CHAR_BIT == 8, "CHAR_BIT == 8"); // // sum_basic // template class sum_basic { static_assert(Bits % 8 == 0, "Bits % 8 == 0"); public: typedef typename sprout::detail::uint_t::least value_type; typedef sum_basic const const_type; typedef typename std::conditional< sizeof(std::size_t) < sizeof(value_type), value_type, std::size_t >::type sum_type; private: sum_type sum_; private: template SPROUT_CONSTEXPR sum_type calc_sum(Iterator first, Iterator last) const { return sprout::accumulate( sprout::make_bytes_iterator(first), sprout::make_bytes_iterator(last), sum_ ); } public: SPROUT_CONSTEXPR sum_basic() = default; SPROUT_CONSTEXPR sum_basic(sum_basic const&) = default; explicit SPROUT_CONSTEXPR sum_basic(sum_type sum) : sum_(sum) {} void reset(sum_type new_sum = 0) { sum_ = new_sum; } SPROUT_CONSTEXPR sum_basic const process_byte(std::uint8_t byte) const { return sum_basic(sum_ + byte); } template SPROUT_CONSTEXPR sum_basic const process_block(Iterator bytes_begin, Iterator bytes_end) const { return sum_basic(calc_sum(bytes_begin, bytes_end)); } template SPROUT_CONSTEXPR sum_basic const process_bytes(Iterator buffer, std::size_t byte_count) const { return process_block(buffer, sprout::next(buffer, byte_count)); } template SPROUT_CONSTEXPR sum_basic const process_range(Range const& bytes_range) const { return process_block(sprout::begin(bytes_range), sprout::end(bytes_range)); } void process_byte(std::uint8_t byte) { sum_ += byte; } template void process_block(Iterator bytes_begin, Iterator bytes_end) { sum_ = calc_sum(bytes_begin, bytes_end); } template void process_bytes(Iterator buffer, std::size_t byte_count) { process_block(buffer, sprout::next(buffer, byte_count)); } template void process_range(Range const& bytes_range) { process_block(sprout::begin(bytes_range), sprout::end(bytes_range)); } SPROUT_CONSTEXPR value_type checksum() const { return static_cast(sum_ & sprout::numeric_limits::max()); } SPROUT_CONSTEXPR value_type operator()() const { return checksum(); } }; // // sum8 // sum16 // sum32 // typedef sprout::sum_basic<8> sum8; typedef sprout::sum_basic<16> sum16; typedef sprout::sum_basic<32> sum32; } // namespace sprout #endif // #ifndef SPROUT_CHECKSUM_SUM_HPP