Merge pull request #11960 from Minty-Meeo/dolphin-tool-code-review-4

DolphinTool: Use {fmt} library
This commit is contained in:
Admiral H. Curtiss 2023-06-17 14:18:21 +02:00 committed by GitHub
commit 79d5850e6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 72 deletions

View File

@ -16,6 +16,7 @@ PRIVATE
discio discio
uicommon uicommon
cpp-optparse cpp-optparse
fmt::fmt
) )
if(MSVC) if(MSVC)

View File

@ -11,6 +11,8 @@
#include <vector> #include <vector>
#include <OptionParser.h> #include <OptionParser.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "DiscIO/Blob.h" #include "DiscIO/Blob.h"
@ -120,7 +122,7 @@ int ConvertCommand(const std::vector<std::string>& args)
// --input // --input
if (!options.is_set("input")) if (!options.is_set("input"))
{ {
std::cerr << "Error: No input set" << std::endl; fmt::print(std::cerr, "Error: No input set\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const std::string& input_file_path = options["input"]; const std::string& input_file_path = options["input"];
@ -128,7 +130,7 @@ int ConvertCommand(const std::vector<std::string>& args)
// --output // --output
if (!options.is_set("output")) if (!options.is_set("output"))
{ {
std::cerr << "Error: No output set" << std::endl; fmt::print(std::cerr, "Error: No output set\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const std::string& output_file_path = options["output"]; const std::string& output_file_path = options["output"];
@ -137,7 +139,7 @@ int ConvertCommand(const std::vector<std::string>& args)
const std::optional<DiscIO::BlobType> format_o = ParseFormatString(options["format"]); const std::optional<DiscIO::BlobType> format_o = ParseFormatString(options["format"]);
if (!format_o.has_value()) if (!format_o.has_value())
{ {
std::cerr << "Error: No output format set" << std::endl; fmt::print(std::cerr, "Error: No output format set\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const DiscIO::BlobType format = format_o.value(); const DiscIO::BlobType format = format_o.value();
@ -146,7 +148,7 @@ int ConvertCommand(const std::vector<std::string>& args)
std::unique_ptr<DiscIO::BlobReader> blob_reader = DiscIO::CreateBlobReader(input_file_path); std::unique_ptr<DiscIO::BlobReader> blob_reader = DiscIO::CreateBlobReader(input_file_path);
if (!blob_reader) if (!blob_reader)
{ {
std::cerr << "Error: The input file could not be opened." << std::endl; fmt::print(std::cerr, "Error: The input file could not be opened.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -159,19 +161,19 @@ int ConvertCommand(const std::vector<std::string>& args)
{ {
if (scrub) if (scrub)
{ {
std::cerr << "Error: Scrubbing is only supported for GC/Wii disc images." << std::endl; fmt::print(std::cerr, "Error: Scrubbing is only supported for GC/Wii disc images.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::cerr << "Warning: The input file is not a GC/Wii disc image. Continuing anyway." fmt::print(std::cerr,
<< std::endl; "Warning: The input file is not a GC/Wii disc image. Continuing anyway.\n");
} }
if (scrub) if (scrub)
{ {
if (volume->IsDatelDisc()) if (volume->IsDatelDisc())
{ {
std::cerr << "Error: Scrubbing a Datel disc is not supported." << std::endl; fmt::print(std::cerr, "Error: Scrubbing a Datel disc is not supported.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -179,37 +181,34 @@ int ConvertCommand(const std::vector<std::string>& args)
if (!blob_reader) if (!blob_reader)
{ {
std::cerr << "Error: Unable to process disc image. Try again without --scrub." << std::endl; fmt::print(std::cerr, "Error: Unable to process disc image. Try again without --scrub.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (scrub && format == DiscIO::BlobType::RVZ) if (scrub && format == DiscIO::BlobType::RVZ)
{ {
std::cerr << "Warning: Scrubbing an RVZ container does not offer significant space advantages. " fmt::print(std::cerr, "Warning: Scrubbing an RVZ container does not offer significant space "
"Continuing anyway." "advantages. Continuing anyway.\n");
<< std::endl;
} }
if (scrub && format == DiscIO::BlobType::PLAIN) if (scrub && format == DiscIO::BlobType::PLAIN)
{ {
std::cerr << "Warning: Scrubbing does not save space when converting to ISO unless using " fmt::print(std::cerr, "Warning: Scrubbing does not save space when converting to ISO unless "
"external compression. Continuing anyway." "using external compression. Continuing anyway.\n");
<< std::endl;
} }
if (!scrub && format == DiscIO::BlobType::GCZ && volume && if (!scrub && format == DiscIO::BlobType::GCZ && volume &&
volume->GetVolumeType() == DiscIO::Platform::WiiDisc && !volume->IsDatelDisc()) volume->GetVolumeType() == DiscIO::Platform::WiiDisc && !volume->IsDatelDisc())
{ {
std::cerr << "Warning: Converting Wii disc images to GCZ without scrubbing may not offer space " fmt::print(std::cerr, "Warning: Converting Wii disc images to GCZ without scrubbing may not "
"advantages over ISO. Continuing anyway." "offer space advantages over ISO. Continuing anyway.\n");
<< std::endl;
} }
if (volume && volume->IsNKit()) if (volume && volume->IsNKit())
{ {
std::cerr << "Warning: Converting an NKit file, output will still be NKit! Continuing anyway." fmt::print(std::cerr,
<< std::endl; "Warning: Converting an NKit file, output will still be NKit! Continuing anyway.\n");
} }
// --block_size // --block_size
@ -222,31 +221,30 @@ int ConvertCommand(const std::vector<std::string>& args)
{ {
if (!block_size_o.has_value()) if (!block_size_o.has_value())
{ {
std::cerr << "Error: Block size must be set for GCZ/RVZ/WIA" << std::endl; fmt::print(std::cerr, "Error: Block size must be set for GCZ/RVZ/WIA\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!DiscIO::IsDiscImageBlockSizeValid(block_size_o.value(), format)) if (!DiscIO::IsDiscImageBlockSizeValid(block_size_o.value(), format))
{ {
std::cerr << "Error: Block size is not valid for this format" << std::endl; fmt::print(std::cerr, "Error: Block size is not valid for this format\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (block_size_o.value() < DiscIO::PREFERRED_MIN_BLOCK_SIZE || if (block_size_o.value() < DiscIO::PREFERRED_MIN_BLOCK_SIZE ||
block_size_o.value() > DiscIO::PREFERRED_MAX_BLOCK_SIZE) block_size_o.value() > DiscIO::PREFERRED_MAX_BLOCK_SIZE)
{ {
std::cerr << "Warning: Block size is not ideal for performance. Continuing anyway." fmt::print(std::cerr,
<< std::endl; "Warning: Block size is not ideal for performance. Continuing anyway.\n");
} }
if (format == DiscIO::BlobType::GCZ && volume && if (format == DiscIO::BlobType::GCZ && volume &&
!DiscIO::IsGCZBlockSizeLegacyCompatible(block_size_o.value(), volume->GetDataSize())) !DiscIO::IsGCZBlockSizeLegacyCompatible(block_size_o.value(), volume->GetDataSize()))
{ {
std::cerr << "Warning: For GCZs to be compatible with Dolphin < 5.0-11893, " fmt::print(std::cerr,
"the file size must be an integer multiple of the block size " "Warning: For GCZs to be compatible with Dolphin < 5.0-11893, the file size "
"and must not be an integer multiple of the block size multiplied by 32. " "must be an integer multiple of the block size and must not be an integer "
"Continuing anyway." "multiple of the block size multiplied by 32. Continuing anyway.\n");
<< std::endl;
} }
} }
@ -262,7 +260,7 @@ int ConvertCommand(const std::vector<std::string>& args)
{ {
if (!compression_o.has_value()) if (!compression_o.has_value())
{ {
std::cerr << "Error: Compression format must be set for WIA or RVZ" << std::endl; fmt::print(std::cerr, "Error: Compression format must be set for WIA or RVZ\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -271,7 +269,7 @@ int ConvertCommand(const std::vector<std::string>& args)
(format == DiscIO::BlobType::RVZ && (format == DiscIO::BlobType::RVZ &&
compression_o.value() == DiscIO::WIARVZCompressionType::Purge)) compression_o.value() == DiscIO::WIARVZCompressionType::Purge))
{ {
std::cerr << "Error: Compression type is not supported for the container format" << std::endl; fmt::print(std::cerr, "Error: Compression type is not supported for the container format\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -283,8 +281,8 @@ int ConvertCommand(const std::vector<std::string>& args)
{ {
if (!compression_level_o.has_value()) if (!compression_level_o.has_value())
{ {
std::cerr << "Error: Compression level must be set when compression type is not 'none'" fmt::print(std::cerr,
<< std::endl; "Error: Compression level must be set when compression type is not 'none'\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -292,7 +290,7 @@ int ConvertCommand(const std::vector<std::string>& args)
DiscIO::GetAllowedCompressionLevels(compression_o.value(), false); DiscIO::GetAllowedCompressionLevels(compression_o.value(), false);
if (compression_level_o.value() < range.first || compression_level_o.value() > range.second) if (compression_level_o.value() < range.first || compression_level_o.value() > range.second)
{ {
std::cerr << "Error: Compression level not in acceptable range" << std::endl; fmt::print(std::cerr, "Error: Compression level not in acceptable range\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -346,7 +344,7 @@ int ConvertCommand(const std::vector<std::string>& args)
if (!success) if (!success)
{ {
std::cerr << "Error: Conversion failed" << std::endl; fmt::print(std::cerr, "Error: Conversion failed\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -9,6 +9,8 @@
#include <vector> #include <vector>
#include <OptionParser.h> #include <OptionParser.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include "DiscIO/Blob.h" #include "DiscIO/Blob.h"
#include "DiscIO/Volume.h" #include "DiscIO/Volume.h"
@ -46,7 +48,7 @@ int HeaderCommand(const std::vector<std::string>& args)
const std::string& input_file_path = options["input"]; const std::string& input_file_path = options["input"];
if (input_file_path.empty()) if (input_file_path.empty())
{ {
std::cerr << "Error: No input set" << std::endl; fmt::print(std::cerr, "Error: No input set\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -58,7 +60,7 @@ int HeaderCommand(const std::vector<std::string>& args)
const std::unique_ptr<DiscIO::BlobReader> blob_reader = DiscIO::CreateBlobReader(input_file_path); const std::unique_ptr<DiscIO::BlobReader> blob_reader = DiscIO::CreateBlobReader(input_file_path);
if (!blob_reader) if (!blob_reader)
{ {
std::cerr << "Error: Unable to open disc image" << std::endl; fmt::print(std::cerr, "Error: Unable to open disc image\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -68,25 +70,25 @@ int HeaderCommand(const std::vector<std::string>& args)
{ {
const auto block_size = blob_reader->GetBlockSize(); const auto block_size = blob_reader->GetBlockSize();
if (block_size == 0) if (block_size == 0)
std::cout << "N/A" << std::endl; fmt::print(std::cout, "N/A\n");
else else
std::cout << block_size << std::endl; fmt::print(std::cout, "{}\n", block_size);
} }
if (enable_compression_method) if (enable_compression_method)
{ {
const auto compression_method = blob_reader->GetCompressionMethod(); const auto compression_method = blob_reader->GetCompressionMethod();
if (compression_method == "") if (compression_method == "")
std::cout << "N/A" << std::endl; fmt::print(std::cout, "N/A\n");
else else
std::cout << compression_method << std::endl; fmt::print(std::cout, "{}\n", compression_method);
} }
if (enable_compression_level) if (enable_compression_level)
{ {
const auto compression_level_o = blob_reader->GetCompressionLevel(); const auto compression_level_o = blob_reader->GetCompressionLevel();
if (compression_level_o == std::nullopt) if (compression_level_o == std::nullopt)
std::cout << "N/A" << std::endl; fmt::print(std::cout, "N/A\n");
else else
std::cout << compression_level_o.value() << std::endl; fmt::print(std::cout, "{}\n", compression_level_o.value());
} }
} }
else else
@ -94,14 +96,14 @@ int HeaderCommand(const std::vector<std::string>& args)
const auto blob_type = blob_reader->GetBlobType(); const auto blob_type = blob_reader->GetBlobType();
if (blob_type == DiscIO::BlobType::GCZ) if (blob_type == DiscIO::BlobType::GCZ)
{ {
std::cout << "Block Size: " << blob_reader->GetBlockSize() << std::endl; fmt::print(std::cout, "Block Size: {}\nCompression Method: {}\n", blob_reader->GetBlockSize(),
std::cout << "Compression Method: " << blob_reader->GetCompressionMethod() << std::endl; blob_reader->GetCompressionMethod());
} }
if (blob_type == DiscIO::BlobType::WIA || blob_type == DiscIO::BlobType::RVZ) if (blob_type == DiscIO::BlobType::WIA || blob_type == DiscIO::BlobType::RVZ)
{ {
std::cout << "Block Size: " << blob_reader->GetBlockSize() << std::endl; fmt::print(std::cout, "Block Size: {}\nCompression Method: {}\nCompression Level: {}\n",
std::cout << "Compression Method: " << blob_reader->GetCompressionMethod() << std::endl; blob_reader->GetBlockSize(), blob_reader->GetCompressionMethod(),
std::cout << "Compression Level: " << blob_reader->GetCompressionLevel().value() << std::endl; blob_reader->GetCompressionLevel().value());
} }
} }

View File

@ -9,6 +9,9 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "Common/Version.h" #include "Common/Version.h"
#include "Core/Core.h" #include "Core/Core.h"
@ -19,8 +22,9 @@
static void PrintUsage() static void PrintUsage()
{ {
std::cerr << "usage: dolphin-tool COMMAND -h" << std::endl << std::endl; fmt::print(std::cerr, "usage: dolphin-tool COMMAND -h\n"
std::cerr << "commands supported: [convert, verify, header]" << std::endl; "\n"
"commands supported: [convert, verify, header]\n");
} }
#ifdef _WIN32 #ifdef _WIN32

View File

@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include <OptionParser.h> #include <OptionParser.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "DiscIO/VolumeDisc.h" #include "DiscIO/VolumeDisc.h"
@ -30,46 +32,44 @@ static std::string HashToHexString(const std::vector<u8>& hash)
static void PrintFullReport(const DiscIO::VolumeVerifier::Result& result) static void PrintFullReport(const DiscIO::VolumeVerifier::Result& result)
{ {
if (!result.hashes.crc32.empty()) if (!result.hashes.crc32.empty())
std::cout << "CRC32: " << HashToHexString(result.hashes.crc32) << std::endl; fmt::print(std::cout, "CRC32: {}\n", HashToHexString(result.hashes.crc32));
else else
std::cout << "CRC32 not computed" << std::endl; fmt::print(std::cout, "CRC32 not computed\n");
if (!result.hashes.md5.empty()) if (!result.hashes.md5.empty())
std::cout << "MD5: " << HashToHexString(result.hashes.md5) << std::endl; fmt::print(std::cout, "MD5: {}\n", HashToHexString(result.hashes.md5));
else else
std::cout << "MD5 not computed" << std::endl; fmt::print(std::cout, "MD5 not computed\n");
if (!result.hashes.sha1.empty()) if (!result.hashes.sha1.empty())
std::cout << "SHA1: " << HashToHexString(result.hashes.sha1) << std::endl; fmt::print(std::cout, "SHA1: {}\n", HashToHexString(result.hashes.sha1));
else else
std::cout << "SHA1 not computed" << std::endl; fmt::print(std::cout, "SHA1 not computed\n");
std::cout << "Problems Found: " << (result.problems.empty() ? "No" : "Yes") << std::endl; fmt::print(std::cout, "Problems Found: {}\n", result.problems.empty() ? "No" : "Yes");
for (const auto& problem : result.problems) for (const auto& problem : result.problems)
{ {
std::cout << std::endl << "Severity: "; fmt::print(std::cout, "\nSeverity: ");
switch (problem.severity) switch (problem.severity)
{ {
case DiscIO::VolumeVerifier::Severity::Low: case DiscIO::VolumeVerifier::Severity::Low:
std::cout << "Low"; fmt::print(std::cout, "Low");
break; break;
case DiscIO::VolumeVerifier::Severity::Medium: case DiscIO::VolumeVerifier::Severity::Medium:
std::cout << "Medium"; fmt::print(std::cout, "Medium");
break; break;
case DiscIO::VolumeVerifier::Severity::High: case DiscIO::VolumeVerifier::Severity::High:
std::cout << "High"; fmt::print(std::cout, "High");
break; break;
case DiscIO::VolumeVerifier::Severity::None: case DiscIO::VolumeVerifier::Severity::None:
std::cout << "None"; fmt::print(std::cout, "None");
break; break;
default: default:
ASSERT(false); ASSERT(false);
break; break;
} }
std::cout << std::endl; fmt::print(std::cout, "\nSummary: {}\n\n", problem.text);
std::cout << "Summary: " << problem.text << std::endl << std::endl;
} }
} }
@ -109,7 +109,7 @@ int VerifyCommand(const std::vector<std::string>& args)
// Validate options // Validate options
if (!options.is_set("input")) if (!options.is_set("input"))
{ {
std::cerr << "Error: No input set" << std::endl; fmt::print(std::cerr, "Error: No input set\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const std::string& input_file_path = options["input"]; const std::string& input_file_path = options["input"];
@ -134,7 +134,7 @@ int VerifyCommand(const std::vector<std::string>& args)
if (!hashes_to_calculate.crc32 && !hashes_to_calculate.md5 && !hashes_to_calculate.sha1) if (!hashes_to_calculate.crc32 && !hashes_to_calculate.md5 && !hashes_to_calculate.sha1)
{ {
// optparse should protect from this // optparse should protect from this
std::cerr << "Error: No algorithms selected for the operation" << std::endl; fmt::print(std::cerr, "Error: No algorithms selected for the operation\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -142,7 +142,7 @@ int VerifyCommand(const std::vector<std::string>& args)
const std::unique_ptr<DiscIO::VolumeDisc> volume = DiscIO::CreateDisc(input_file_path); const std::unique_ptr<DiscIO::VolumeDisc> volume = DiscIO::CreateDisc(input_file_path);
if (!volume) if (!volume)
{ {
std::cerr << "Error: Unable to open disc image" << std::endl; fmt::print(std::cerr, "Error: Unable to open disc image\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -164,14 +164,14 @@ int VerifyCommand(const std::vector<std::string>& args)
else else
{ {
if (hashes_to_calculate.crc32 && !result.hashes.crc32.empty()) if (hashes_to_calculate.crc32 && !result.hashes.crc32.empty())
std::cout << HashToHexString(result.hashes.crc32) << std::endl; fmt::print(std::cout, "{}\n", HashToHexString(result.hashes.crc32));
else if (hashes_to_calculate.md5 && !result.hashes.md5.empty()) else if (hashes_to_calculate.md5 && !result.hashes.md5.empty())
std::cout << HashToHexString(result.hashes.md5) << std::endl; fmt::print(std::cout, "{}\n", HashToHexString(result.hashes.md5));
else if (hashes_to_calculate.sha1 && !result.hashes.sha1.empty()) else if (hashes_to_calculate.sha1 && !result.hashes.sha1.empty())
std::cout << HashToHexString(result.hashes.sha1) << std::endl; fmt::print(std::cout, "{}\n", HashToHexString(result.hashes.sha1));
else else
{ {
std::cerr << "Error: No hash computed" << std::endl; fmt::print(std::cerr, "Error: No hash computed\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }