1
0

fix: change the behavior of printf in string op.

- add compiler hint for checking the arguments of printf.
- change the return value of printf. from std::expected to normal value. use C++ exception to indicate error.
	* the error of printf usually caused by programmer. so it can be found when testing program.
	* so i use std::logic_error to indicate this and programmer should fix this before releasing program.
- change the use of encoding convertion. for those cases that convertion must be safe, we unwrap it directly.
This commit is contained in:
2025-09-22 22:14:36 +08:00
parent 45e4031b5c
commit c85830902b
22 changed files with 240 additions and 164 deletions

View File

@@ -130,21 +130,15 @@ namespace yycc::windows::dialog {
// build new Windows oriented string vector
for (const auto& item : m_Filters) {
// convert name to wchar
auto win_name = ENC::to_wchar(item.first);
if (!win_name.has_value()) {
return std::unexpected(DialogError::BadEncoding);
}
auto win_name = ENC::to_wchar(item.first).value();
// join pattern string and convert to wchar
const auto& modes = item.second;
auto joined_modes = OP::join(modes.begin(), modes.end(), u8";");
auto win_modes = ENC::to_wchar(joined_modes);
if (!win_modes.has_value()) {
return std::unexpected(DialogError::BadEncoding);
}
auto win_modes = ENC::to_wchar(joined_modes).value();
// append this pair
rv.m_WinFilters.emplace_back(std::make_pair(win_name.value(), win_modes.value()));
rv.m_WinFilters.emplace_back(std::make_pair(win_name, win_modes));
}
// update data struct
@@ -305,28 +299,21 @@ namespace yycc::windows::dialog {
// build title and init file name
if (m_Title.has_value()) {
auto win_title = ENC::to_wchar(m_Title.value());
if (!win_title.has_value()) return std::unexpected(DialogError::BadEncoding);
else rv.m_WinTitle = win_title.value();
rv.m_WinTitle = ENC::to_wchar(m_Title.value()).value();
} else rv.m_WinTitle = std::nullopt;
if (m_InitFileName.has_value()) {
auto win_init_file_name = ENC::to_wchar(m_InitFileName.value());
if (!win_init_file_name.has_value()) return std::unexpected(DialogError::BadEncoding);
else rv.m_WinInitFileName = win_init_file_name.value();
rv.m_WinInitFileName = ENC::to_wchar(m_InitFileName.value()).value();
} else rv.m_WinInitFileName = std::nullopt;
// fetch init directory
if (m_InitDirectory.has_value()) {
// convert to wchar path
auto w_init_dir = ENC::to_wchar(m_InitDirectory.value());
if (!w_init_dir.has_value()) {
return std::unexpected(DialogError::BadEncoding);
}
auto w_init_dir = ENC::to_wchar(m_InitDirectory.value()).value();
// fetch IShellItem*
// Ref: https://stackoverflow.com/questions/76306324/how-to-set-default-folder-for-ifileopendialog-interface
IShellItem* init_directory = NULL;
HRESULT hr = SHCreateItemFromParsingName(w_init_dir.value().c_str(), NULL, IID_PPV_ARGS(&init_directory));
HRESULT hr = SHCreateItemFromParsingName(w_init_dir.c_str(), NULL, IID_PPV_ARGS(&init_directory));
if (FAILED(hr)) return std::unexpected(DialogError::NoSuchDir);
// assign IShellItem*
@@ -378,7 +365,7 @@ namespace yycc::windows::dialog {
WINCOM::SmartLPWSTR display_name(display_name_ptr);
// convert result and return
return ENC::to_utf8(display_name.get()).transform_error([](auto err) { return DialogError::BadEncoding; });
return ENC::to_utf8(display_name.get()).value();
}
/**

View File

@@ -29,7 +29,6 @@ namespace yycc::windows::dialog {
/// @brief The error occurs in this module.
enum class DialogError {
BadEncoding, ///< Error occurs when perform encoding convertion.
TooManyFilters, ///< The size of file filters list is too large for Windows.
IndexOverflow, ///< Default filter index is too large for Windows.
EmptyFilters, ///< File filters is empty when picking file.
@@ -310,7 +309,7 @@ namespace yycc::windows::dialog {
*/
DialogResult<DialogOutcome<std::u8string>> open_folder(const FileDialog& params);
}
} // namespace yycc::windows::dialog
#undef NS_YYCC_WINDOWS_COM

View File

@@ -21,7 +21,7 @@ namespace yycc::windows::winfct {
(LPCWSTR) get_current_module,
&hModule);
if (rv) return hModule;
else return std::unexpected(WinFctError::Backend);
else return std::unexpected(WinFctError::Win32);
}
WinFctResult<std::u8string> get_temp_directory() {
@@ -33,7 +33,7 @@ namespace yycc::windows::winfct {
while (true) {
if ((expected_size = ::GetTempPathW(static_cast<DWORD>(wpath.size()), wpath.data())) == 0) {
// failed, return
return std::unexpected(WinFctError::Backend);
return std::unexpected(WinFctError::Win32);
}
if (expected_size > static_cast<DWORD>(wpath.size())) {
@@ -47,7 +47,7 @@ namespace yycc::windows::winfct {
}
// convert to utf8 and return
return ENC::to_utf8(wpath).transform_error([](auto err) { return WinFctError::Encoding; });
return ENC::to_utf8(wpath).value();
}
WinFctResult<std::u8string> get_module_file_name(HINSTANCE hModule) {
@@ -58,7 +58,7 @@ namespace yycc::windows::winfct {
while (true) {
if ((copied_size = ::GetModuleFileNameW(hModule, wpath.data(), static_cast<DWORD>(wpath.size()))) == 0) {
// failed, return
return std::unexpected(WinFctError::Backend);
return std::unexpected(WinFctError::Win32);
}
// check insufficient buffer
@@ -73,7 +73,7 @@ namespace yycc::windows::winfct {
}
// convert to utf8 and return
return ENC::to_utf8(wpath).transform_error([](auto err) { return WinFctError::Encoding; });
return ENC::to_utf8(wpath).value();
}
bool is_valid_code_page(UINT code_page) {
@@ -82,41 +82,32 @@ namespace yycc::windows::winfct {
}
WinFctResult<void> copy_file(const std::u8string_view& lpExistingFileName, const std::u8string_view& lpNewFileName, BOOL bFailIfExists) {
auto wExistingFileName = ENC::to_wchar(lpExistingFileName);
auto wNewFileName = ENC::to_wchar(lpNewFileName);
if (!(wExistingFileName.has_value() && wNewFileName.has_value())) {
return std::unexpected(WinFctError::Encoding);
}
auto wExistingFileName = ENC::to_wchar(lpExistingFileName).value();
auto wNewFileName = ENC::to_wchar(lpNewFileName).value();
if (!::CopyFileW(wExistingFileName.value().c_str(), wNewFileName.value().c_str(), bFailIfExists)) {
return std::unexpected(WinFctError::Backend);
if (!::CopyFileW(wExistingFileName.c_str(), wNewFileName.c_str(), bFailIfExists)) {
return std::unexpected(WinFctError::Win32);
}
return {};
}
WinFctResult<void> move_file(const std::u8string_view& lpExistingFileName, const std::u8string_view& lpNewFileName) {
auto wExistingFileName = ENC::to_wchar(lpExistingFileName);
auto wNewFileName = ENC::to_wchar(lpNewFileName);
if (!(wExistingFileName.has_value() && wNewFileName.has_value())) {
return std::unexpected(WinFctError::Encoding);
}
auto wExistingFileName = ENC::to_wchar(lpExistingFileName).value();
auto wNewFileName = ENC::to_wchar(lpNewFileName).value();
if (!::MoveFileW(wExistingFileName.value().c_str(), wNewFileName.value().c_str())) {
return std::unexpected(WinFctError::Backend);
if (!::MoveFileW(wExistingFileName.c_str(), wNewFileName.c_str())) {
return std::unexpected(WinFctError::Win32);
}
return {};
}
WinFctResult<void> delete_file(const std::u8string_view& lpFileName) {
auto wFileName = ENC::to_wchar(lpFileName);
if (!wFileName.has_value()) {
return std::unexpected(WinFctError::Encoding);
}
auto wFileName = ENC::to_wchar(lpFileName).value();
if (!::DeleteFileW(wFileName.value().c_str())) {
return std::unexpected(WinFctError::Backend);
if (!::DeleteFileW(wFileName.c_str())) {
return std::unexpected(WinFctError::Win32);
}
return {};
@@ -144,11 +135,11 @@ namespace yycc::windows::winfct {
// fetch path
LPWSTR raw_known_path;
HRESULT hr = SHGetKnownFolderPath(*pId, KF_FLAG_CREATE, NULL, &raw_known_path);
if (FAILED(hr)) return std::unexpected(WinFctError::Backend);
if (FAILED(hr)) return std::unexpected(WinFctError::Win32);
COM::SmartLPWSTR known_path(raw_known_path);
// convert to utf8 and return
return ENC::to_utf8(known_path.get()).transform_error([](auto err) { return WinFctError::Encoding; });
return ENC::to_utf8(known_path.get()).value();
}
#endif

View File

@@ -15,8 +15,7 @@ namespace yycc::windows::winfct {
/// @brief All errors occur in this module.
enum class WinFctError {
Backend, ///< Error occurs when calling Win32 functions.
Encoding, ///< Can not perform encoding convertion.
Win32, ///< Error occurs when calling Win32 functions.
NoCom, ///< No COM environment.
};