libos: Put everything under the os namespace
This commit is contained in:
parent
f1e2937528
commit
c752b2b343
@ -35,7 +35,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
StringView filename;
|
StringView filename;
|
||||||
|
|
||||||
ArgumentParser parser;
|
os::ArgumentParser parser;
|
||||||
parser.add_positional_argument(filename, "file"_sv, "-"_sv);
|
parser.add_positional_argument(filename, "file"_sv, "-"_sv);
|
||||||
Vector<StringView> extra_files = parser.parse(argc, argv).value();
|
Vector<StringView> extra_files = parser.parse(argc, argv).value();
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
StringView date;
|
StringView date;
|
||||||
|
|
||||||
ArgumentParser parser;
|
os::ArgumentParser parser;
|
||||||
parser.add_value_argument(date, 'd', "date"_sv, true);
|
parser.add_value_argument(date, 'd', "date"_sv, true);
|
||||||
parser.parse(argc, argv);
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ int main(int argc, char** argv)
|
|||||||
FILE* f;
|
FILE* f;
|
||||||
StringView pathname;
|
StringView pathname;
|
||||||
|
|
||||||
ArgumentParser parser;
|
os::ArgumentParser parser;
|
||||||
parser.add_positional_argument(pathname, "file"_sv, true);
|
parser.add_positional_argument(pathname, "file"_sv, true);
|
||||||
parser.parse(argc, argv);
|
parser.parse(argc, argv);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ int main(int argc, char** argv)
|
|||||||
bool show_all { false };
|
bool show_all { false };
|
||||||
bool show_almost_all { false };
|
bool show_almost_all { false };
|
||||||
|
|
||||||
ArgumentParser parser;
|
os::ArgumentParser parser;
|
||||||
parser.add_positional_argument(pathname, "directory"_sv, "/"_sv);
|
parser.add_positional_argument(pathname, "directory"_sv, "/"_sv);
|
||||||
parser.add_switch_argument(show_all, 'a', "all"_sv);
|
parser.add_switch_argument(show_all, 'a', "all"_sv);
|
||||||
parser.add_switch_argument(show_almost_all, 'A', "almost-all"_sv);
|
parser.add_switch_argument(show_almost_all, 'A', "almost-all"_sv);
|
||||||
|
@ -2,47 +2,50 @@
|
|||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
|
||||||
class ArgumentParser
|
namespace os
|
||||||
{
|
{
|
||||||
public:
|
class ArgumentParser
|
||||||
ArgumentParser() = default;
|
|
||||||
|
|
||||||
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
|
||||||
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
|
|
||||||
|
|
||||||
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
|
|
||||||
|
|
||||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required);
|
|
||||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback);
|
|
||||||
|
|
||||||
Result<Vector<StringView>> parse(int argc, char* const* argv);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct PositionalArgument
|
|
||||||
{
|
{
|
||||||
StringView* out;
|
public:
|
||||||
StringView name;
|
ArgumentParser() = default;
|
||||||
bool required;
|
|
||||||
StringView fallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SwitchArgument
|
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
||||||
{
|
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
|
||||||
bool* out;
|
|
||||||
char short_flag;
|
|
||||||
StringView long_flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ValueArgument
|
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
|
||||||
{
|
|
||||||
StringView* out;
|
|
||||||
char short_flag;
|
|
||||||
StringView long_flag;
|
|
||||||
bool required;
|
|
||||||
StringView fallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<PositionalArgument> m_positional_args;
|
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required);
|
||||||
Vector<SwitchArgument> m_switch_args;
|
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback);
|
||||||
Vector<ValueArgument> m_value_args;
|
|
||||||
};
|
Result<Vector<StringView>> parse(int argc, char* const* argv);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct PositionalArgument
|
||||||
|
{
|
||||||
|
StringView* out;
|
||||||
|
StringView name;
|
||||||
|
bool required;
|
||||||
|
StringView fallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SwitchArgument
|
||||||
|
{
|
||||||
|
bool* out;
|
||||||
|
char short_flag;
|
||||||
|
StringView long_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueArgument
|
||||||
|
{
|
||||||
|
StringView* out;
|
||||||
|
char short_flag;
|
||||||
|
StringView long_flag;
|
||||||
|
bool required;
|
||||||
|
StringView fallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<PositionalArgument> m_positional_args;
|
||||||
|
Vector<SwitchArgument> m_switch_args;
|
||||||
|
Vector<ValueArgument> m_value_args;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -2,148 +2,94 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required)
|
namespace os
|
||||||
{
|
{
|
||||||
PositionalArgument arg { &out, name, required, {} };
|
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required)
|
||||||
|
|
||||||
return m_positional_args.try_append(move(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, StringView fallback)
|
|
||||||
{
|
|
||||||
PositionalArgument arg { &out, name, false, fallback };
|
|
||||||
|
|
||||||
return m_positional_args.try_append(move(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, StringView long_flag)
|
|
||||||
{
|
|
||||||
SwitchArgument arg { &out, short_flag, long_flag };
|
|
||||||
|
|
||||||
return m_switch_args.try_append(move(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
|
||||||
bool value_required)
|
|
||||||
{
|
|
||||||
ValueArgument arg { &out, short_flag, long_flag, value_required, {} };
|
|
||||||
|
|
||||||
return m_value_args.try_append(move(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
|
||||||
StringView fallback)
|
|
||||||
{
|
|
||||||
ValueArgument arg { &out, short_flag, long_flag, false, fallback };
|
|
||||||
|
|
||||||
return m_value_args.try_append(move(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool looks_like_short_flag(StringView arg)
|
|
||||||
{
|
|
||||||
return arg.length() > 1 && arg[0] == '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool looks_like_long_flag(StringView arg)
|
|
||||||
{
|
|
||||||
return arg.length() > 2 && arg[0] == '-' && arg[1] == '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Vector<StringView>> ArgumentParser::parse(int argc, char* const* argv)
|
|
||||||
{
|
|
||||||
StringView program_name = argv[0];
|
|
||||||
|
|
||||||
Vector<StringView> leftovers;
|
|
||||||
|
|
||||||
Option<ValueArgument> current_value_argument = {};
|
|
||||||
bool is_parsing_value_argument = false;
|
|
||||||
|
|
||||||
bool is_still_parsing_flags = true;
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
|
||||||
{
|
{
|
||||||
StringView arg = argv[i];
|
PositionalArgument arg { &out, name, required, {} };
|
||||||
|
|
||||||
if (is_parsing_value_argument)
|
return m_positional_args.try_append(move(arg));
|
||||||
{
|
}
|
||||||
*current_value_argument->out = arg;
|
|
||||||
is_parsing_value_argument = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_still_parsing_flags)
|
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, StringView fallback)
|
||||||
|
{
|
||||||
|
PositionalArgument arg { &out, name, false, fallback };
|
||||||
|
|
||||||
|
return m_positional_args.try_append(move(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, StringView long_flag)
|
||||||
|
{
|
||||||
|
SwitchArgument arg { &out, short_flag, long_flag };
|
||||||
|
|
||||||
|
return m_switch_args.try_append(move(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
||||||
|
bool value_required)
|
||||||
|
{
|
||||||
|
ValueArgument arg { &out, short_flag, long_flag, value_required, {} };
|
||||||
|
|
||||||
|
return m_value_args.try_append(move(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
|
||||||
|
StringView fallback)
|
||||||
|
{
|
||||||
|
ValueArgument arg { &out, short_flag, long_flag, false, fallback };
|
||||||
|
|
||||||
|
return m_value_args.try_append(move(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool looks_like_short_flag(StringView arg)
|
||||||
|
{
|
||||||
|
return arg.length() > 1 && arg[0] == '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool looks_like_long_flag(StringView arg)
|
||||||
|
{
|
||||||
|
return arg.length() > 2 && arg[0] == '-' && arg[1] == '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Vector<StringView>> ArgumentParser::parse(int argc, char* const* argv)
|
||||||
|
{
|
||||||
|
StringView program_name = argv[0];
|
||||||
|
|
||||||
|
Vector<StringView> leftovers;
|
||||||
|
|
||||||
|
Option<ValueArgument> current_value_argument = {};
|
||||||
|
bool is_parsing_value_argument = false;
|
||||||
|
|
||||||
|
bool is_still_parsing_flags = true;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (arg == "--")
|
StringView arg = argv[i];
|
||||||
|
|
||||||
|
if (is_parsing_value_argument)
|
||||||
{
|
{
|
||||||
is_still_parsing_flags = false;
|
*current_value_argument->out = arg;
|
||||||
|
is_parsing_value_argument = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (looks_like_long_flag(arg))
|
if (is_still_parsing_flags)
|
||||||
{
|
{
|
||||||
StringView flag = &arg[2];
|
if (arg == "--")
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
for (const auto& current : m_switch_args)
|
|
||||||
{
|
{
|
||||||
if (current.long_flag == flag)
|
is_still_parsing_flags = false;
|
||||||
{
|
continue;
|
||||||
*current.out = true;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& current : m_value_args)
|
if (looks_like_long_flag(arg))
|
||||||
{
|
{
|
||||||
if (current.long_flag == flag)
|
StringView flag = &arg[2];
|
||||||
{
|
|
||||||
current_value_argument = current;
|
|
||||||
is_parsing_value_argument = true;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) continue;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
else if (looks_like_short_flag(arg))
|
|
||||||
{
|
|
||||||
StringView flags = &arg[1];
|
|
||||||
|
|
||||||
for (usize j = 0; j < flags.length(); j++)
|
|
||||||
{
|
|
||||||
char c = flags[j];
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
// Last flag, this could be a value flag
|
|
||||||
if (j + 1 == flags.length())
|
|
||||||
{
|
|
||||||
for (const auto& current : m_value_args)
|
|
||||||
{
|
|
||||||
if (current.short_flag == ' ') continue;
|
|
||||||
|
|
||||||
if (current.short_flag == c)
|
|
||||||
{
|
|
||||||
current_value_argument = current;
|
|
||||||
is_parsing_value_argument = true;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& current : m_switch_args)
|
for (const auto& current : m_switch_args)
|
||||||
{
|
{
|
||||||
if (current.short_flag == ' ') continue;
|
if (current.long_flag == flag)
|
||||||
|
|
||||||
if (current.short_flag == c)
|
|
||||||
{
|
{
|
||||||
*current.out = true;
|
*current.out = true;
|
||||||
found = true;
|
found = true;
|
||||||
@ -151,47 +97,104 @@ Result<Vector<StringView>> ArgumentParser::parse(int argc, char* const* argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& current : m_value_args)
|
||||||
|
{
|
||||||
|
if (current.long_flag == flag)
|
||||||
|
{
|
||||||
|
current_value_argument = current;
|
||||||
|
is_parsing_value_argument = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (found) continue;
|
if (found) continue;
|
||||||
|
|
||||||
fprintf(stderr, "%s: invalid option -- '%c'\n", program_name.chars(), c);
|
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
else if (looks_like_short_flag(arg))
|
||||||
|
{
|
||||||
|
StringView flags = &arg[1];
|
||||||
|
|
||||||
|
for (usize j = 0; j < flags.length(); j++)
|
||||||
|
{
|
||||||
|
char c = flags[j];
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
// Last flag, this could be a value flag
|
||||||
|
if (j + 1 == flags.length())
|
||||||
|
{
|
||||||
|
for (const auto& current : m_value_args)
|
||||||
|
{
|
||||||
|
if (current.short_flag == ' ') continue;
|
||||||
|
|
||||||
|
if (current.short_flag == c)
|
||||||
|
{
|
||||||
|
current_value_argument = current;
|
||||||
|
is_parsing_value_argument = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& current : m_switch_args)
|
||||||
|
{
|
||||||
|
if (current.short_flag == ' ') continue;
|
||||||
|
|
||||||
|
if (current.short_flag == c)
|
||||||
|
{
|
||||||
|
*current.out = true;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) continue;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: invalid option -- '%c'\n", program_name.chars(), c);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Option<PositionalArgument> current = m_positional_args.try_dequeue();
|
||||||
|
if (!current.has_value())
|
||||||
|
{
|
||||||
|
TRY(leftovers.try_append(arg));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*current->out = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Option<PositionalArgument> current = m_positional_args.try_dequeue();
|
if (is_parsing_value_argument)
|
||||||
if (!current.has_value())
|
|
||||||
{
|
{
|
||||||
TRY(leftovers.try_append(arg));
|
if (current_value_argument->required)
|
||||||
continue;
|
{
|
||||||
|
fprintf(stderr, "%s: option '--%s' requires an argument\n", program_name.chars(),
|
||||||
|
current_value_argument->long_flag.chars());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else { *current_value_argument->out = current_value_argument->fallback; }
|
||||||
}
|
}
|
||||||
|
|
||||||
*current->out = arg;
|
// Loop through all remaining positional arguments.
|
||||||
}
|
for (const auto& arg : m_positional_args)
|
||||||
|
|
||||||
if (is_parsing_value_argument)
|
|
||||||
{
|
|
||||||
if (current_value_argument->required)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: option '--%s' requires an argument\n", program_name.chars(),
|
if (arg.required)
|
||||||
current_value_argument->long_flag.chars());
|
{
|
||||||
exit(1);
|
fprintf(stderr, "%s: required argument '%s' not provided\n", program_name.chars(), arg.name.chars());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else { *arg.out = arg.fallback; }
|
||||||
}
|
}
|
||||||
else { *current_value_argument->out = current_value_argument->fallback; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through all remaining positional arguments.
|
return leftovers;
|
||||||
for (const auto& arg : m_positional_args)
|
|
||||||
{
|
|
||||||
if (arg.required)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: required argument '%s' not provided\n", program_name.chars(), arg.name.chars());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
else { *arg.out = arg.fallback; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return leftovers;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user