refactor: add result wrapper for env vars and args
This commit is contained in:
@ -177,7 +177,10 @@ namespace yycc::carton::clap::parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TYPES::ClapResult<Parser> Parser::from_system(const APPLICATION::Application& app) {
|
TYPES::ClapResult<Parser> Parser::from_system(const APPLICATION::Application& app) {
|
||||||
auto args = ENV::get_args();
|
auto rv_args = ENV::get_args();
|
||||||
|
if (!rv_args.has_value()) return std::unexpected(TYPES::ClapError::Others);
|
||||||
|
auto args = std::move(rv_args.value());
|
||||||
|
|
||||||
auto rv = capture(app, args | std::views::transform([](const auto& s) {
|
auto rv = capture(app, args | std::views::transform([](const auto& s) {
|
||||||
return std::u8string_view(s);
|
return std::u8string_view(s);
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -54,7 +54,10 @@ namespace yycc::carton::clap::resolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TYPES::ClapResult<Resolver> Resolver::from_system(const APPLICATION::Application& app) {
|
TYPES::ClapResult<Resolver> Resolver::from_system(const APPLICATION::Application& app) {
|
||||||
auto vars = ENV::get_vars();
|
auto rv_vars = ENV::get_vars();
|
||||||
|
if (!rv_vars.has_value()) return std::unexpected(TYPES::ClapError::Others);
|
||||||
|
auto vars = std::move(rv_vars.value());
|
||||||
|
|
||||||
auto rv = capture(app, vars | std::views::transform([](const auto& p) {
|
auto rv = capture(app, vars | std::views::transform([](const auto& p) {
|
||||||
return std::make_pair<std::u8string_view, std::u8string_view>(p.first, p.second);
|
return std::make_pair<std::u8string_view, std::u8string_view>(p.first, p.second);
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -11,7 +11,8 @@ namespace yycc::carton::clap::types {
|
|||||||
UnexpectedValue, ///< When parsing commandline argument, reach associated value unexpected.
|
UnexpectedValue, ///< When parsing commandline argument, reach associated value unexpected.
|
||||||
LostValue, ///< When parsing commandline argument, fail to find associated value.
|
LostValue, ///< When parsing commandline argument, fail to find associated value.
|
||||||
NotCaptured, ///< When fetching option or variable, given option or variable is not captured.
|
NotCaptured, ///< When fetching option or variable, given option or variable is not captured.
|
||||||
BadCast ///< When fetching option or variable, the content of given option or variable can not be cast into expected type.
|
BadCast, ///< When fetching option or variable, the content of given option or variable can not be cast into expected type.
|
||||||
|
Others, ///< Any other errors.
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief The result type used in this module.
|
/// @brief The result type used in this module.
|
||||||
|
|||||||
@ -173,7 +173,7 @@ namespace yycc::env {
|
|||||||
using SmartEnvironmentStrings = std::unique_ptr<std::remove_pointer_t<LPWCH>, EnvironmentStringsDeleter>;
|
using SmartEnvironmentStrings = std::unique_ptr<std::remove_pointer_t<LPWCH>, EnvironmentStringsDeleter>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<VarPair> get_vars() {
|
VarResult<std::vector<VarPair>> get_vars() {
|
||||||
// TODO: Considering whether replace return value with an iterator.
|
// TODO: Considering whether replace return value with an iterator.
|
||||||
std::vector<VarPair> rv;
|
std::vector<VarPair> rv;
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ namespace yycc::env {
|
|||||||
// Reference: https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getenvironmentstringsw
|
// Reference: https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getenvironmentstringsw
|
||||||
|
|
||||||
SmartEnvironmentStrings env_block(GetEnvironmentStringsW());
|
SmartEnvironmentStrings env_block(GetEnvironmentStringsW());
|
||||||
if (env_block == nullptr) throw std::runtime_error("GetEnvironmentStringsW call failed");
|
if (env_block == nullptr) return std::unexpected(VarError::SysCall);
|
||||||
|
|
||||||
wchar_t *current = env_block.get();
|
wchar_t *current = env_block.get();
|
||||||
while (*current != L'\0') {
|
while (*current != L'\0') {
|
||||||
@ -193,17 +193,17 @@ namespace yycc::env {
|
|||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
auto key = entry.substr(0, pos);
|
auto key = entry.substr(0, pos);
|
||||||
auto value = entry.substr(pos + 1);
|
auto value = entry.substr(pos + 1);
|
||||||
if (key.empty()) throw std::runtime_error("unexpected empty variable name");
|
if (key.empty()) return std::unexpected(VarError::NullPointer);
|
||||||
|
|
||||||
auto u8key = ENC::to_utf8(key);
|
auto u8key = ENC::to_utf8(key);
|
||||||
auto u8value = ENC::to_utf8(value);
|
auto u8value = ENC::to_utf8(value);
|
||||||
if (u8key.has_value() && u8value.has_value()) {
|
if (u8key.has_value() && u8value.has_value()) {
|
||||||
rv.emplace_back(std::make_pair(std::move(u8key.value()), std::move(u8value.value())));
|
rv.emplace_back(std::make_pair(std::move(u8key.value()), std::move(u8value.value())));
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("bad encoding of variable");
|
return std::unexpected(VarError::BadEncoding);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("bad variable syntax");
|
return std::unexpected(VarError::Others);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase the pointer
|
// Increase the pointer
|
||||||
@ -221,10 +221,10 @@ namespace yycc::env {
|
|||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
auto key = entry.substr(0, pos);
|
auto key = entry.substr(0, pos);
|
||||||
auto value = entry.substr(pos + 1);
|
auto value = entry.substr(pos + 1);
|
||||||
if (key.empty()) throw std::runtime_error("unexpected empty variable name");
|
if (key.empty()) return std::unexpected(VarError::NullPointer);
|
||||||
rv.emplace_back(std::make_pair(REINTERPRET::as_utf8(key), REINTERPRET::as_utf8(value)));
|
rv.emplace_back(std::make_pair(REINTERPRET::as_utf8(key), REINTERPRET::as_utf8(value)));
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("bad variable syntax");
|
return std::unexpected(VarError::Others);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -362,7 +362,7 @@ namespace yycc::env {
|
|||||||
else return std::unexpected(PathError::SysCall);
|
else return std::unexpected(PathError::SysCall);
|
||||||
#else
|
#else
|
||||||
// Reference: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
// Reference: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||||
|
|
||||||
// HOME is an environment variable in POSIX standard.
|
// HOME is an environment variable in POSIX standard.
|
||||||
auto home = get_var(u8"HOME");
|
auto home = get_var(u8"HOME");
|
||||||
if (home.has_value()) rv = std::move(home.value());
|
if (home.has_value()) rv = std::move(home.value());
|
||||||
@ -385,7 +385,7 @@ namespace yycc::env {
|
|||||||
class CommandLineArgvDeleter {
|
class CommandLineArgvDeleter {
|
||||||
public:
|
public:
|
||||||
CommandLineArgvDeleter() {}
|
CommandLineArgvDeleter() {}
|
||||||
void operator()(LPWCH ptr) {
|
void operator()(LPWSTR* ptr) {
|
||||||
if (ptr != nullptr) {
|
if (ptr != nullptr) {
|
||||||
LocalFree(ptr);
|
LocalFree(ptr);
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ namespace yycc::env {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<std::u8string> get_args() {
|
ArgResult<std::vector<std::u8string>> get_args() {
|
||||||
// TODO: Considering whether use iterator as return value.
|
// TODO: Considering whether use iterator as return value.
|
||||||
std::vector<std::u8string> rv;
|
std::vector<std::u8string> rv;
|
||||||
|
|
||||||
@ -405,18 +405,18 @@ namespace yycc::env {
|
|||||||
// Fetch args from Win32 functions
|
// Fetch args from Win32 functions
|
||||||
int argc;
|
int argc;
|
||||||
SmartCommandLineArgv argv(CommandLineToArgvW(GetCommandLineW(), &argc));
|
SmartCommandLineArgv argv(CommandLineToArgvW(GetCommandLineW(), &argc));
|
||||||
if (argv == nullptr) throw std::runtime_error("unexpected blank command line tuple");
|
if (argv == nullptr) return std::unexpected(ArgError::NullPointer);
|
||||||
|
|
||||||
// Analyse it
|
// Analyse it
|
||||||
for (int i = 1; i < argc; ++i) { // starts with 1 to remove first part (executable self)
|
for (int i = 1; i < argc; ++i) { // starts with 1 to remove first part (executable self)
|
||||||
auto arg = argv.get()[i];
|
auto arg = argv.get()[i];
|
||||||
if (arg == nullptr) throw std::runtime_error("unexpected nullptr argument");
|
if (arg == nullptr) return std::unexpected(ArgError::NullPointer);
|
||||||
|
|
||||||
auto u8arg = ENC::to_utf8(arg);
|
auto u8arg = ENC::to_utf8(arg);
|
||||||
if (u8arg.has_value()) {
|
if (u8arg.has_value()) {
|
||||||
rv.emplace_back(std::move(u8arg.value()));
|
rv.emplace_back(std::move(u8arg.value()));
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("bad encoding of argument");
|
return std::unexpected(ArgError::BadEncoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ namespace yycc::env {
|
|||||||
// We use NUL as delimiter
|
// We use NUL as delimiter
|
||||||
std::getline(cmdline, arg, '\0');
|
std::getline(cmdline, arg, '\0');
|
||||||
// Check whether reading is okey.
|
// Check whether reading is okey.
|
||||||
if (!cmdline.good()) throw std::runtime_error("bad reading");
|
if (!cmdline.good()) return std::unexpected(ArgError::Others);
|
||||||
// If return string is empty, it means that we reach the tail.
|
// If return string is empty, it means that we reach the tail.
|
||||||
if (arg.empty()) break;
|
if (arg.empty()) break;
|
||||||
|
|
||||||
@ -447,7 +447,7 @@ namespace yycc::env {
|
|||||||
// Close file
|
// Close file
|
||||||
cmdline.close();
|
cmdline.close();
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("fail to open cmdline file");
|
return std::unexpected(ArgError::Others);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(YYCC_OS_MACOS)
|
#elif defined(YYCC_OS_MACOS)
|
||||||
@ -457,11 +457,11 @@ namespace yycc::env {
|
|||||||
if (apple_argv && apple_argc) {
|
if (apple_argv && apple_argc) {
|
||||||
for (int i = 0; i < *apple_argc; ++i) {
|
for (int i = 0; i < *apple_argc; ++i) {
|
||||||
auto ptr = (*apple_argv)[i];
|
auto ptr = (*apple_argv)[i];
|
||||||
if (ptr == nullptr) throw std::runtime_error("unexpected nullptr argument");
|
if (ptr == nullptr) return std::unexpected(ArgError::NullPointer);
|
||||||
else rv.emplace_back(REINTERPRET::as_utf8(ptr));
|
else rv.emplace_back(REINTERPRET::as_utf8(ptr));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("fail to get pointer to argument data");
|
return std::unexpected(ArgError::SysCall);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error "Not supported OS"
|
#error "Not supported OS"
|
||||||
|
|||||||
@ -21,12 +21,13 @@ namespace yycc::env {
|
|||||||
|
|
||||||
/// @brief The error occurs in environment variable operations.
|
/// @brief The error occurs in environment variable operations.
|
||||||
enum class VarError {
|
enum class VarError {
|
||||||
SysCall, ///< Error occurs when calling backend functions.
|
SysCall, ///< Error occurs when calling backend functions.
|
||||||
NoSuchName, ///< The variable with given name is not presented.
|
NoSuchName, ///< The variable with given name is not presented.
|
||||||
BadName, ///< Given name is ill-formated (empty string or has "=" character).
|
BadName, ///< Given name is ill-formated (empty string or has "=" character).
|
||||||
BadEncoding, ///< Error when performing encoding convertion.
|
BadEncoding, ///< Error when performing encoding convertion.
|
||||||
NoMemory, ///< No enough memory to finish this operation.
|
NoMemory, ///< No enough memory to finish this operation.
|
||||||
Others, ///< Any other error types.
|
NullPointer, ///< Unexpected null pointer occurs during operation.
|
||||||
|
Others, ///< Any other error types.
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief The result type in environment variable operations.
|
/// @brief The result type in environment variable operations.
|
||||||
@ -74,7 +75,7 @@ namespace yycc::env {
|
|||||||
* @return The list holding all variables.
|
* @return The list holding all variables.
|
||||||
* @exception std::runtime_error Error occurs when getting variables.
|
* @exception std::runtime_error Error occurs when getting variables.
|
||||||
*/
|
*/
|
||||||
std::vector<VarPair> get_vars();
|
VarResult<std::vector<VarPair>> get_vars();
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
@ -121,8 +122,10 @@ namespace yycc::env {
|
|||||||
|
|
||||||
/// @brief Error occurs when operating argument related functions.
|
/// @brief Error occurs when operating argument related functions.
|
||||||
enum class ArgError {
|
enum class ArgError {
|
||||||
SysCall, ///< Underlying system calling error.
|
SysCall, ///< Underlying system calling error.
|
||||||
Others, ///< Any other error types.
|
BadEncoding, ///< Error when performing encoding convertion.
|
||||||
|
NullPointer, ///< Unexpected null pointer occurs during operation.
|
||||||
|
Others, ///< Any other error types.
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief The result type used for argument related functions;
|
/// @brief The result type used for argument related functions;
|
||||||
@ -134,7 +137,7 @@ namespace yycc::env {
|
|||||||
* @return The list holding all argument one by one.
|
* @return The list holding all argument one by one.
|
||||||
* @exception std::runtime_error Error occurs when getting arguments.
|
* @exception std::runtime_error Error occurs when getting arguments.
|
||||||
*/
|
*/
|
||||||
std::vector<std::u8string> get_args();
|
ArgResult<std::vector<std::u8string>> get_args();
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user