#ifndef STREAM_2019_01_11_H #define STREAM_2019_01_11_H #include // AXIVION Next Line AutosarC++19_03-A16.2.2: AUTOSAR permitted #include #include #include // AXIVION Next Line AutosarC++19_03-A16.2.2: AUTOSAR permitted #include #if(__cplusplus >= 201703L) namespace al::crypto::stream { #else namespace al { namespace crypto { namespace stream { #endif namespace detail { template struct is_std_array : std::false_type { }; template struct is_std_array> : std::true_type { }; inline auto nibble_to_char(const std::size_t nibble, const bool uppercase) -> std::size_t { const auto ch = static_cast ( // AXIVION Next Line AutosarC++19_03-A5.16.1: AUTOSAR permitted uppercase ? static_cast(nibble + (0x41U - 10U)) : static_cast(nibble + (0x61U - 10U)) ); return ch; } } // namespace detail template class stream { }; template class stream::value>::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; auto hash(const std::uint8_t* message, const std::size_t count) -> void { this->initialize(); this->process_data(message, count); this->finalize(); } // AXIVION Next Line AutosarC++19_03-A27.0.4: AUTOSAR permitted auto hash(const char* message, const std::size_t count) -> void { auto p_msg = // NOLINT(llvm-qualified-auto,readability-qualified-auto) // AXIVION Next Line AutosarC++19_03-M5.2.8: AUTOSAR permitted static_cast ( static_cast(message) ); hash(p_msg, count); } auto hash_and_get_result(const std::uint8_t* message, const std::size_t count, typename result_type::pointer result_data) -> void { this->initialize(); this->process_data(message, count); this->finalize_and_get_result(result_data); } virtual auto finalize_and_get_result(typename result_type::pointer result_data) -> void { this->finalize(); const auto result = this->get_result(); static_cast ( std::copy(result.cbegin(), result.cend(), result_data) ); } auto get_result_as_char_array(const bool uppercase = false) -> result_char_array_type { const auto rb = this->get_result(); auto rc = result_char_array_type { }; for(auto i = static_cast(UINT8_C(0)); i < rb.size(); ++i) { const auto nibble_lo = static_cast ( static_cast(rb[i] >> static_cast(UINT8_C(0))) // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) & static_cast(UINT8_C(0xF)) ); const auto nibble_hi = static_cast ( static_cast(rb[i] >> static_cast(UINT8_C(4))) // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) & static_cast(UINT8_C(0xF)) ); const auto next_char_hi = static_cast ( // AXIVION Next Line AutosarC++19_03-A5.16.1: AUTOSAR permitted (nibble_hi <= static_cast(UINT8_C(9))) ? static_cast(nibble_hi + static_cast(UINT8_C(0x30))) : detail::nibble_to_char(nibble_hi, uppercase) ); const auto next_char_lo = static_cast ( // AXIVION Next Line AutosarC++19_03-A5.16.1: AUTOSAR permitted (nibble_lo <= static_cast(UINT8_C(9))) ? static_cast(nibble_lo + static_cast(UINT8_C(0x30))) : detail::nibble_to_char(nibble_lo, uppercase) ); const auto rc_index_2_00 = static_cast ( static_cast(i * static_cast(UINT8_C(2))) + static_cast(UINT8_C(0)) ); const auto rc_index_2_01 = static_cast ( static_cast(i * static_cast(UINT8_C(2))) + static_cast(UINT8_C(1)) ); rc[rc_index_2_00] = static_cast(next_char_hi); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) rc[rc_index_2_01] = static_cast(next_char_lo); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) } return rc; } protected: stream() = default; stream(const stream&) = default; stream(stream&&) noexcept = default; auto operator=(const stream&) -> stream& = default; auto operator=(stream&&) noexcept -> stream& = default; private: AL_CRYPTO_NODISCARD virtual auto get_result() const -> result_type = 0; }; template class stream::value) && (std::is_unsigned::value))>::type> { public: using result_type = ResultType; virtual ~stream() = default; virtual auto initialize() -> void = 0; virtual auto process_data(const std::uint8_t*, const std::size_t) -> void = 0; virtual auto finalize() -> void = 0; auto hash(const std::uint8_t* message, const std::size_t count) -> void { this->initialize(); this->process_data(message, count); this->finalize(); } virtual auto finalize_and_get_result(result_type& result_value) -> void { this->finalize(); result_value = this->get_result(); } // TBD: Implement get_result_as_char_array(...). protected: stream() = default; stream(const stream&) = default; stream(stream&&) noexcept = default; auto operator=(const stream&) -> stream& = default; auto operator=(stream&&) noexcept -> stream& = default; private: AL_CRYPTO_NODISCARD virtual auto get_result() const -> result_type = 0; }; template<> class stream { public: using result_type = void*; virtual ~stream() = default; protected: stream() = default; stream(const stream&) = default; stream(stream&&) noexcept = default; auto operator=(const stream&) -> stream& = default; auto operator=(stream&&) noexcept -> stream& = default; private: AL_CRYPTO_NODISCARD virtual auto get_result() const -> result_type = 0; }; #if(__cplusplus >= 201703L) } // namespace al::crypto::stream #else } // namespace stream } // namespace crypto } // namespace al #endif #endif // STREAM_2019_01_11_H