#ifndef STREAM_2019_01_11_H_ #define STREAM_2019_01_11_H_ #include #include #include #include #include #include namespace al { namespace crypto { namespace stream { namespace detail { template struct is_std_array : std::false_type { }; template struct is_std_array> : std::true_type { }; } template class stream { }; template class stream::value == true>::type> { public: using result_type = ResultType; using result_char_array_type = std::array::value * 2U>; virtual ~stream() = default; virtual void initialize() = 0; virtual void process_data(const std::uint8_t* message, const std::size_t count) = 0; virtual void finalize() = 0; void hash(const std::uint8_t* message, const std::size_t count) { this->initialize(); this->process_data(message, count); this->finalize(); } void hash(const char* message, const std::size_t count) { hash(reinterpret_cast(message), count); } void hash_and_get_result(const std::uint8_t* message, const std::size_t count, typename result_type::pointer result_data) { this->initialize(); this->process_data(message, count); this->finalize_and_get_result(result_data); } virtual void finalize_and_get_result(typename result_type::pointer result_data) { this->finalize(); const result_type result = this->get_result(); std::copy(result.cbegin(), result.cend(), result_data); } result_char_array_type get_result_as_char_array(const bool uppercase = false) { const result_type rb = this->get_result(); result_char_array_type rc; for(std::size_t i = 0U; i < rb.size(); ++i) { const std::size_t nibble_lo = (std::size_t) ((std::size_t) (rb[i] >> 0U) & 0xFU); const std::size_t nibble_hi = (std::size_t) ((std::size_t) (rb[i] >> 4U) & 0xFU); const std::size_t next_char_hi = ((nibble_hi <= 9U) ? nibble_hi + 0x30U : (uppercase ? nibble_hi + (0x41U - 10U) : nibble_hi + (0x61U - 10U))); const std::size_t next_char_lo = ((nibble_lo <= 9U) ? nibble_lo + 0x30U : (uppercase ? nibble_lo + (0x41U - 10U) : nibble_lo + (0x61U - 10U))); rc[(i * 2U) + 0U] = static_cast(next_char_hi); rc[(i * 2U) + 1U] = static_cast(next_char_lo); } return rc; } protected: stream() = default; stream(const stream&) = default; stream& operator=(const stream&) = default; private: virtual result_type get_result() const { return result_type(); } }; template class stream::value == true) && (std::is_unsigned::value == true))>::type> { public: using result_type = ResultType; virtual ~stream() = default; virtual void initialize() = 0; virtual void process_data(const std::uint8_t*, const std::size_t) = 0; virtual void finalize() = 0; void hash(const std::uint8_t* message, const std::size_t count) { this->initialize(); this->process_data(message, count); this->finalize(); } virtual void finalize_and_get_result(result_type& result_value) { this->finalize(); result_value = this->get_result(); } // TBD: Implement get_result_as_char_array(...). protected: stream() = default; stream(const stream&) = default; stream& operator=(const stream&) = default; private: virtual result_type get_result() const { return result_type(); } }; template<> class stream { public: using result_type = void*; virtual ~stream() = default; protected: stream() = default; stream(const stream&) = default; stream& operator=(const stream&) = default; private: virtual result_type get_result() const { return nullptr; } }; } } } // al::crpyto::stream #endif // STREAM_2019_01_11_H_