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:
5
src/yycc/carton/clap.hpp
Normal file
5
src/yycc/carton/clap.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace yycc::carton::clap {
|
||||
|
||||
}
|
||||
5
src/yycc/carton/clap/option.cpp
Normal file
5
src/yycc/carton/clap/option.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "option.hpp"
|
||||
|
||||
namespace yycc::carton::clap::option {
|
||||
|
||||
}
|
||||
85
src/yycc/carton/clap/option.hpp
Normal file
85
src/yycc/carton/clap/option.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
#include "types.hpp"
|
||||
#include "../../macro/class_copy_move.hpp"
|
||||
#include "../../string/op.hpp"
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <format>
|
||||
#include <string>
|
||||
|
||||
#define NS_YYCC_CLAP_TYPES ::yycc::carton::clap::types
|
||||
|
||||
namespace yycc::carton::clap::option {
|
||||
|
||||
class Option {
|
||||
public:
|
||||
Option(std::optional<std::u8string_view> short_name,
|
||||
std::optional<std::u8string_view> long_name,
|
||||
std::optional<std::u8string_view> value_hint,
|
||||
const std::u8string& description) :
|
||||
short_name(short_name), long_name(long_name), value_hint(value_hint), description(description) {
|
||||
if (!short_name.has_value() && !long_name.has_value()) {
|
||||
throw std::logic_error("must have at least one name, short or long name");
|
||||
}
|
||||
|
||||
if (short_name.has_value()) {
|
||||
const auto& short_name_value = short_name.value();
|
||||
if (!legal_short_name(short_name_value)) {
|
||||
throw std::logic_error(std::format("invalid short name {}", short_name_value));
|
||||
}
|
||||
}
|
||||
if (long_name.has_value()) {
|
||||
const auto& long_name_value = long_name.value();
|
||||
if (!legal_long_name(long_name_value)) {
|
||||
throw std::logic_error(std::format("invalid long name {}", long_name_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
~Option() {}
|
||||
YYCC_DEFAULT_COPY_MOVE(Option)
|
||||
|
||||
public:
|
||||
std::optional<std::u8string_view> get_short_name() const { return this->short_name; }
|
||||
std::optional<std::u8string_view> get_long_name() const { return this->long_name; }
|
||||
std::optional<std::u8string_view> get_value_hint() const { return this->value_hint; }
|
||||
std::u8string_view get_description() const { return this->description; }
|
||||
|
||||
std::u8string to_showcase_name() {
|
||||
namespace op = ::yycc::string::op;
|
||||
|
||||
if (short_name.has_value()) {
|
||||
if (long_name.has_value()) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
} else {
|
||||
if (long_name.has_value()) {
|
||||
op::printf
|
||||
} else {
|
||||
throw std::runtime_error("both long name and short name are empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static bool legal_short_name(const std::u8string_view& name) {
|
||||
if (name.empty()) return false;
|
||||
if (name.starts_with(NS_YYCC_CLAP_TYPES::DASH)) return false;
|
||||
return true;
|
||||
}
|
||||
static bool legal_long_name(const std::u8string_view& name) {
|
||||
if (name.empty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<std::u8string> short_name;
|
||||
std::optional<std::u8string> long_name;
|
||||
std::optional<std::u8string> value_hint;
|
||||
std::u8string description;
|
||||
};
|
||||
|
||||
} // namespace yycc::carton::clap::option
|
||||
|
||||
#undef NS_YYCC_CLAP_TYPES
|
||||
19
src/yycc/carton/clap/types.hpp
Normal file
19
src/yycc/carton/clap/types.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <expected>
|
||||
#include <string_view>
|
||||
|
||||
namespace yycc::carton::clap::types {
|
||||
|
||||
enum class ClapError {
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using ClapResult = std::expected<T, ClapError>;
|
||||
|
||||
inline constexpr std::u8string_view DASH = u8"-";
|
||||
inline constexpr std::u8string_view DOUBLE_DASH = u8"--";
|
||||
|
||||
using Token = size_t;
|
||||
|
||||
} // namespace yycc::carton::clap::types
|
||||
@ -108,9 +108,7 @@ namespace yycc::carton::csconsole {
|
||||
if (GetConsoleMode(hStdOut, &dwConsoleMode)) {
|
||||
// console handle, use WriteConsoleW.
|
||||
// convert utf8 string to wide char first
|
||||
auto rv = ENC::to_wchar(strl);
|
||||
if (!rv.has_value()) return;
|
||||
std::wstring wstrl(std::move(rv.value()));
|
||||
std::wstring wstrl = ENC::to_wchar(strl).value();
|
||||
size_t wstrl_size = wstrl.size();
|
||||
// write string with size check
|
||||
if (wstrl_size <= std::numeric_limits<DWORD>::max()) {
|
||||
@ -171,11 +169,8 @@ namespace yycc::carton::csconsole {
|
||||
// treat as format string
|
||||
va_list argcpy;
|
||||
va_copy(argcpy, argptr);
|
||||
auto rv = OP::vprintf(u8_fmt, argcpy);
|
||||
strl = OP::vprintf(u8_fmt, argcpy);
|
||||
va_end(argcpy);
|
||||
// check format result
|
||||
if (!rv.has_value()) return;
|
||||
else strl = std::move(rv.value());
|
||||
} else {
|
||||
// treat as plain string
|
||||
strl = u8_fmt;
|
||||
|
||||
@ -63,11 +63,9 @@ namespace yycc::carton::ironpad {
|
||||
// check singleton
|
||||
// build mutex string first
|
||||
auto mutex_name = OP::printf(u8"Global\\%" PRIu32 ".{61634294-d23c-43f9-8490-b5e09837eede}", GetCurrentProcessId());
|
||||
if (!mutex_name.has_value()) return false;
|
||||
auto w_mutex_name = ENC::to_wchar(mutex_name.value());
|
||||
if (!w_mutex_name.has_value()) return false;
|
||||
auto wmutex_name = ENC::to_wchar(mutex_name).value();
|
||||
// create mutex
|
||||
m_SingletonMutex = CreateMutexW(NULL, FALSE, w_mutex_name.value().c_str());
|
||||
m_SingletonMutex = CreateMutexW(NULL, FALSE, wmutex_name.c_str());
|
||||
DWORD errcode = GetLastError();
|
||||
// check whether be created
|
||||
if (m_SingletonMutex == NULL) return false;
|
||||
@ -303,18 +301,17 @@ namespace yycc::carton::ironpad {
|
||||
DWORD process_id = GetCurrentProcessId();
|
||||
// conbine them as a file name prefix
|
||||
auto u8_filename_prefix = OP::printf(u8"%s.%" PRIu32, u8_process_name.c_str(), process_id);
|
||||
if (!u8_filename_prefix.has_value()) return std::nullopt;
|
||||
// then get file name for log and minidump
|
||||
std::u8string u8_filename;
|
||||
switch (kind) {
|
||||
case FileKind::LogFile:
|
||||
u8_filename = u8_filename_prefix.value() + u8".log";
|
||||
u8_filename = u8_filename_prefix + u8".log";
|
||||
break;
|
||||
case FileKind::CoredumpFile:
|
||||
u8_filename = u8_filename_prefix.value() + u8".dmp";
|
||||
u8_filename = u8_filename_prefix + u8".dmp";
|
||||
break;
|
||||
default:
|
||||
u8_filename = u8_filename_prefix.value();
|
||||
u8_filename = u8_filename_prefix;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -451,11 +448,9 @@ namespace yycc::carton::ironpad {
|
||||
* @details This function will write coredump of given exception into given file path.
|
||||
*/
|
||||
void do_coredump(const std::u8string_view& u8_filename, LPEXCEPTION_POINTERS info) {
|
||||
// convert file encoding
|
||||
// if convertion failed, return
|
||||
auto filename_rv = ENC::to_wchar(u8_filename);
|
||||
if (!filename_rv.has_value()) return;
|
||||
std::wstring filename = filename_rv.value();
|
||||
// convert file encoding.
|
||||
// it must be okey.
|
||||
auto filename = ENC::to_wchar(u8_filename).value();
|
||||
|
||||
// open file and write
|
||||
HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
@ -554,15 +549,11 @@ namespace yycc::carton::ironpad {
|
||||
* @param[in] ... The argument to be formatted.
|
||||
*/
|
||||
void log_format_line(std::FILE* fs, const char8_t* fmt, ...) {
|
||||
// do format first
|
||||
// write to file and console
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
auto fmt_rv = OP::vprintf(fmt, arg);
|
||||
log_write_line(fs, OP::vprintf(fmt, arg).c_str());
|
||||
va_end(arg);
|
||||
// write to file and console
|
||||
if (fmt_rv.has_value()) {
|
||||
log_write_line(fs, fmt_rv.value().c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -468,11 +468,8 @@ namespace yycc::carton::wcwidth {
|
||||
}
|
||||
|
||||
Result<size_t> wcswidth(const std::u8string_view& rhs) {
|
||||
// Cast encoding
|
||||
auto u32str = ENC::to_utf32(rhs);
|
||||
if (!u32str.has_value()) return std::unexpected(Error::BadEncoding);
|
||||
// Call underlying function
|
||||
return wcswidth(u32str.value());
|
||||
// Cast encoding and call underlying function
|
||||
return wcswidth(ENC::to_utf32(rhs).value());
|
||||
}
|
||||
|
||||
} // namespace yycc::carton::wcwidth
|
||||
|
||||
@ -31,7 +31,6 @@ namespace yycc::carton::wcwidth {
|
||||
|
||||
/// @brief Error occurs in this module
|
||||
enum class Error {
|
||||
BadEncoding, ///< Given
|
||||
BadAnsiEscSeq, ///< Bad char when processing ANSI Escape Sequence
|
||||
BadCsiSeq, ///< Bad char when processing CSI Sequence.
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user