[vcpkg hash] Refactor to reduce code duplication
MODIFY
src/vcpkg/commands.hash.cpp
src/vcpkg/commands.hash.cpp
@@ -18,7 +18,7 @@ namespace vcpkg::Commands::Hash
{
namespace
{
- static std::string to_hex(const unsigned char* string, const size_t bytes)
+ std::string to_hex(const unsigned char* string, const size_t bytes)
{
static constexpr char HEX_MAP[] = "0123456789abcdef";
@@ -58,31 +58,34 @@ namespace vcpkg::Commands::Hash
if (handle) BCryptDestroyHash(handle);
}
};
- }
- std::string get_file_hash(const fs::path& path, const std::string& hash_type)
+ struct BCryptHasher
{
- BCryptAlgorithmHandle algorithm_handle;
-
- NTSTATUS error_code = BCryptOpenAlgorithmProvider(
- &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0);
+ explicit BCryptHasher(const std::string& hash_type)
+ {
+ NTSTATUS error_code =
+ BCryptOpenAlgorithmProvider(&this->algorithm_handle.handle,
+ Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(),
+ nullptr,
+ 0);
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider");
DWORD hash_buffer_bytes;
DWORD cb_data;
- error_code = BCryptGetProperty(algorithm_handle.handle,
+ error_code = BCryptGetProperty(this->algorithm_handle.handle,
BCRYPT_HASH_LENGTH,
reinterpret_cast<PUCHAR>(&hash_buffer_bytes),
sizeof(DWORD),
&cb_data,
0);
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
- const ULONG length_in_bytes = hash_buffer_bytes;
+ this->length_in_bytes = hash_buffer_bytes;
+ }
+ std::string hash_file(const fs::path& path) const
+ {
BCryptHashHandle hash_handle;
-
- error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
+ this->initialize_hash_handle(hash_handle);
FILE* file = nullptr;
const auto ec = _wfopen_s(&file, path.c_str(), L"rb");
@@ -90,54 +93,58 @@ namespace vcpkg::Commands::Hash
unsigned char buffer[4096];
while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file))
{
- error_code = BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(actual_size), 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data");
+ hash_data(hash_handle, buffer, actual_size);
}
-
fclose(file);
- std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes);
-
- error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
-
- return to_hex(hash_buffer.get(), length_in_bytes);
+ return this->finalize_hash_handle(hash_handle);
}
- std::string get_string_hash(const std::string& s, const std::string& hash_type)
+ std::string hash_string(const std::string& s) const
{
- BCryptAlgorithmHandle algorithm_handle;
-
- NTSTATUS error_code = BCryptOpenAlgorithmProvider(
- &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider");
-
- DWORD hash_buffer_bytes;
- DWORD cb_data;
- error_code = BCryptGetProperty(algorithm_handle.handle,
- BCRYPT_HASH_LENGTH,
- reinterpret_cast<PUCHAR>(&hash_buffer_bytes),
- sizeof(DWORD),
- &cb_data,
- 0);
- Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
- const ULONG length_in_bytes = hash_buffer_bytes;
-
BCryptHashHandle hash_handle;
+ this->initialize_hash_handle(hash_handle);
+ hash_data(hash_handle, reinterpret_cast<unsigned char*>(const_cast<char*>(s.c_str())), s.size());
+ return this->finalize_hash_handle(hash_handle);
+ }
- error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
+ private:
+ void initialize_hash_handle(BCryptHashHandle& hash_handle) const
+ {
+ const NTSTATUS error_code =
+ BCryptCreateHash(this->algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
+ }
- auto* const buffer = reinterpret_cast<unsigned char*>(const_cast<char*>(s.c_str()));
- error_code = BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(s.size()), 0);
+ void hash_data(BCryptHashHandle& hash_handle, unsigned char* buffer, const size_t& data_size) const
+ {
+ const NTSTATUS error_code =
+ BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(data_size), 0);
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data");
+ }
- std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes);
-
- error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0);
+ std::string finalize_hash_handle(const BCryptHashHandle& hash_handle) const
+ {
+ std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(this->length_in_bytes);
+ const NTSTATUS error_code =
+ BCryptFinishHash(hash_handle.handle, hash_buffer.get(), this->length_in_bytes, 0);
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
+ return to_hex(hash_buffer.get(), this->length_in_bytes);
+ }
+
+ BCryptAlgorithmHandle algorithm_handle;
+ ULONG length_in_bytes;
+ };
+ }
- return to_hex(hash_buffer.get(), length_in_bytes);
+ std::string get_file_hash(const fs::path& path, const std::string& hash_type)
+ {
+ return BCryptHasher{hash_type}.hash_file(path);
+ }
+
+ std::string get_string_hash(const std::string& s, const std::string& hash_type)
+ {
+ return BCryptHasher{hash_type}.hash_string(s);
}
}

[vcpkg hash] Refactor to reduce code duplication