diff --git a/src/headers/parser/argument_parser.hpp b/src/headers/parser/argument_parser.hpp index c78972a..e752aed 100644 --- a/src/headers/parser/argument_parser.hpp +++ b/src/headers/parser/argument_parser.hpp @@ -5,361 +5,232 @@ #ifndef ARGUMENT_PARSER_HPP #define ARGUMENT_PARSER_HPP -#include -#include +#include #include +#include #include #include -#include -#include +#include #include #include +#include #include #include #include -#include -#include namespace argument_parser { - class action_base { - public: - virtual ~action_base() = default; - [[nodiscard]] virtual bool expects_parameter() const = 0; - virtual void invoke() const = 0; - virtual void invoke_with_parameter(const std::string& param) const = 0; - [[nodiscard]] virtual std::unique_ptr clone() const = 0; - }; + class action_base { + public: + virtual ~action_base() = default; + [[nodiscard]] virtual bool expects_parameter() const = 0; + virtual void invoke() const = 0; + virtual void invoke_with_parameter(const std::string ¶m) const = 0; + [[nodiscard]] virtual std::unique_ptr clone() const = 0; + }; - template - class parametered_action : public action_base { - public: - explicit parametered_action(std::function const& handler) : handler(handler) {} - - using parameter_type = T; - - void invoke(const T& arg) const { - handler(arg); - } + template class parametered_action : public action_base { + public: + explicit parametered_action(std::function const &handler) : handler(handler) {} + using parameter_type = T; + void invoke(const T &arg) const { + handler(arg); + } - [[nodiscard]] bool expects_parameter() const override { return true; } - - void invoke() const override { - throw std::runtime_error("Parametered action requires a parameter"); - } - - void invoke_with_parameter(const std::string& param) const override { - T parsed_value = parsing_traits::parser_trait::parse(param); - invoke(parsed_value); - } - - [[nodiscard]] std::unique_ptr clone() const override { - return std::make_unique>(handler); - } + [[nodiscard]] bool expects_parameter() const override { + return true; + } - private: - std::function handler; - }; + void invoke() const override { + throw std::runtime_error("Parametered action requires a parameter"); + } - class non_parametered_action : public action_base { - public: - explicit non_parametered_action(std::function const& handler) : handler(handler) {} - - void invoke() const override { - handler(); - } + void invoke_with_parameter(const std::string ¶m) const override { + T parsed_value = parsing_traits::parser_trait::parse(param); + invoke(parsed_value); + } - [[nodiscard]] bool expects_parameter() const override { return false; } - - void invoke_with_parameter(const std::string& param) const override { - invoke(); - } - - [[nodiscard]] std::unique_ptr clone() const override { - return std::make_unique(handler); - } + [[nodiscard]] std::unique_ptr clone() const override { + return std::make_unique>(handler); + } - private: - std::function handler; - }; + private: + std::function handler; + }; - class base_parser; + class non_parametered_action : public action_base { + public: + explicit non_parametered_action(std::function const &handler) : handler(handler) {} - class argument { - public: - argument() : id(0), name(), action(std::make_unique([](){})), required(false), invoked(false) {} + void invoke() const override { + handler(); + } - template - argument(const int id, std::string name, ActionType const& action) - : id(id), name(std::move(name)), action(action.clone()), required(false), invoked(false) {} + [[nodiscard]] bool expects_parameter() const override { + return false; + } - argument(const argument& other) - : id(other.id), name(other.name), action(other.action->clone()), - required(other.required), invoked(other.invoked), help_text(other.help_text) {} + void invoke_with_parameter(const std::string ¶m) const override { + invoke(); + } - argument& operator=(const argument& other) { - if (this != &other) { - id = other.id; - name = other.name; - action = other.action->clone(); - required = other.required; - invoked = other.invoked; - help_text = other.help_text; - } - return *this; - } + [[nodiscard]] std::unique_ptr clone() const override { + return std::make_unique(handler); + } - argument(argument&& other) noexcept = default; - argument& operator=(argument&& other) noexcept = default; + private: + std::function handler; + }; - [[nodiscard]] bool is_required() const { return required; } - [[nodiscard]] std::string get_name() const { return name; } - [[nodiscard]] bool is_invoked() const { return invoked; } + class base_parser; - [[nodiscard]] bool expects_parameter() const { - return action->expects_parameter(); - } + class argument { + public: + argument(); - private: - void set_required(bool val) { required = val; } - void set_invoked(bool val) { invoked = val; } - void set_help_text(std::string const& text) { help_text = text; } + template + argument(const int id, std::string name, ActionType const &action) + : id(id), name(std::move(name)), action(action.clone()), required(false), invoked(false) {} - friend class base_parser; + argument(const argument &other); + argument &operator=(const argument &other); + argument(argument &&other) noexcept = default; + argument &operator=(argument &&other) noexcept = default; - int id; - std::string name; - std::unique_ptr action; - bool required; - bool invoked; - std::string help_text; - }; + [[nodiscard]] bool is_required() const; + [[nodiscard]] std::string get_name() const; + [[nodiscard]] bool is_invoked() const; + [[nodiscard]] bool expects_parameter() const; + [[nodiscard]] std::string get_help_text() const; - namespace helpers { - template - static parametered_action make_parametered_action(std::function const& function) { - return parametered_action(function); - } + private: + void set_required(bool val); + void set_invoked(bool val); + void set_help_text(std::string const &text); - static non_parametered_action make_non_parametered_action(std::function const& function) { - return non_parametered_action(function); - } - } + friend class base_parser; - class base_parser { - public: - template - void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, parametered_action const& action, bool required) { - base_add_argument(short_arg, long_arg, help_text, action, required); - } + int id; + std::string name; + std::unique_ptr action; + bool required; + bool invoked; + std::string help_text; + }; - template - void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { - base_add_argument(short_arg, long_arg, help_text, required); - } + namespace helpers { + template + static parametered_action make_parametered_action(std::function const &function) { + return parametered_action(function); + } - void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, non_parametered_action const& action, bool required) { - base_add_argument(short_arg, long_arg, help_text, action, required); - } + static non_parametered_action make_non_parametered_action(std::function const &function) { + return non_parametered_action(function); + } + } // namespace helpers - void add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { - base_add_argument(short_arg, long_arg, help_text, required); - } + class base_parser { + public: + template + void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + parametered_action const &action, bool required) { + base_add_argument(short_arg, long_arg, help_text, action, required); + } - void on_complete(std::function const& action) { - on_complete_events.emplace_back(action); - } + template + void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + bool required) { + base_add_argument(short_arg, long_arg, help_text, required); + } - template - std::optional get_optional(std::string const& arg) const { - auto id = find_argument_id(arg); - if (id.has_value()) { - auto value = stored_arguments.find(id.value()); - if (value != stored_arguments.end() && value->second.has_value()) return std::any_cast(value->second); - } - return std::nullopt; - } + void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + non_parametered_action const &action, bool required) { + base_add_argument(short_arg, long_arg, help_text, action, required); + } - [[nodiscard]] std::string build_help_text(std::initializer_list convention_types) const { - std::stringstream ss; - ss << "Usage: " << program_name << " [OPTIONS]...\n"; - - for (auto const& [id, arg] : argument_map) { - auto short_arg = reverse_short_arguments.at(id); - auto long_arg = reverse_long_arguments.at(id); - ss << "\t"; - ss << "-" << short_arg << ", --" << long_arg; - ss << "\t\t" << arg.help_text << "\n"; - } - return ss.str(); - } + void add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + bool required) { + base_add_argument(short_arg, long_arg, help_text, required); + } - argument& get_argument(conventions::parsed_argument const& arg) { + void on_complete(std::function const &action); - if (arg.first == conventions::argument_type::LONG) { - auto long_pos = long_arguments.find(arg.second); - if (long_pos != long_arguments.end()) return argument_map.at(long_pos->second); - } else if (arg.first == conventions::argument_type::SHORT) { - auto short_pos = short_arguments.find(arg.second); - if (short_pos != short_arguments.end()) return argument_map.at(short_pos->second); - } else if (arg.first == conventions::argument_type::INTERCHANGABLE) { - auto long_pos = long_arguments.find(arg.second); - if (long_pos != long_arguments.end()) return argument_map.at(long_pos->second); - auto short_pos = short_arguments.find(arg.second); - if (short_pos != short_arguments.end()) return argument_map.at(short_pos->second); - } - throw std::runtime_error("Unknown argument: " + arg.second); - } + template std::optional get_optional(std::string const &arg) const { + auto id = find_argument_id(arg); + if (id.has_value()) { + auto value = stored_arguments.find(id.value()); + if (value != stored_arguments.end() && value->second.has_value()) + return std::any_cast(value->second); + } + return std::nullopt; + } - [[nodiscard]] std::optional find_argument_id(std::string const& arg) const { - auto long_pos = long_arguments.find(arg); - auto short_post = short_arguments.find(arg); + [[nodiscard]] std::string + build_help_text(std::initializer_list convention_types) const; + argument &get_argument(conventions::parsed_argument const &arg); + [[nodiscard]] std::optional find_argument_id(std::string const &arg) const; + void handle_arguments(std::initializer_list convention_types); + void display_help(std::initializer_list convention_types) const; - if (long_pos != long_arguments.end()) return long_pos->second; - if (short_post != short_arguments.end()) return short_post->second; - return std::nullopt; - } - - void handle_arguments(std::initializer_list convention_types) { - for (auto it = parsed_arguments.begin(); it != parsed_arguments.end(); ++it) { - std::stringstream error_stream; - bool arg_correctly_handled = false; + protected: + base_parser() = default; - for (auto const& convention_type : convention_types) { - auto extracted = convention_type->get_argument(*it); - if (extracted.first == conventions::argument_type::ERROR) { - error_stream << "Convention \"" << convention_type->name() << "\" failed with: " << extracted.second << "\n"; - continue; - } + std::string program_name; + std::vector parsed_arguments; - try { - argument& corresponding_argument = get_argument(extracted); - - if (corresponding_argument.expects_parameter()) { - if (convention_type->requires_next_token() && (it + 1) == parsed_arguments.end()) { - throw std::runtime_error("expected value for argument " + extracted.second); - } - auto value_raw = convention_type->requires_next_token() ? *(++it) : convention_type->extract_value(*it); - corresponding_argument.action->invoke_with_parameter(value_raw); - } else { - corresponding_argument.action->invoke(); - } + private: + void assert_argument_not_exist(std::string const &short_arg, std::string const &long_arg) const; + static void set_argument_status(bool is_required, std::string const &help_text, argument &arg); + void place_argument(int id, argument const &arg, std::string const &short_arg, std::string const &long_arg); - corresponding_argument.set_invoked(true); - arg_correctly_handled = true; - break; // Convention succeeded, move to the next argument token + template + void base_add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + ActionType const &action, bool required) { + assert_argument_not_exist(short_arg, long_arg); + int id = id_counter.fetch_add(1); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } - } catch (const std::runtime_error& e) { - error_stream << "Convention \"" << convention_type->name() << "\" failed with: " << e.what() << "\n"; - } - } + template + void base_add_argument(std::string const &short_arg, std::string const &long_arg, std::string const &help_text, + bool required) { + assert_argument_not_exist(short_arg, long_arg); + int id = id_counter.fetch_add(1); + if constexpr (std::is_same_v) { + auto action = + helpers::make_non_parametered_action([id, this] { stored_arguments[id] = std::any{true}; }); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } else { + auto action = helpers::make_parametered_action( + [id, this](StoreType const &value) { stored_arguments[id] = std::any{value}; }); + argument arg(id, short_arg + "|" + long_arg, action); + set_argument_status(required, help_text, arg); + place_argument(id, arg, short_arg, long_arg); + } + } - if (!arg_correctly_handled) { - throw std::runtime_error("All trials for argument: \n\t\"" + *it + "\"\n failed with: \n" + error_stream.str()); - } - } - check_for_required_arguments(convention_types); - fire_on_complete_events(); - } + void check_for_required_arguments(std::initializer_list convention_types); + void fire_on_complete_events() const; - void display_help(std::initializer_list convention_types) const { - std::cout << build_help_text(convention_types); - } + inline static std::atomic_int id_counter = 0; - protected: - base_parser() = default; + std::unordered_map stored_arguments; + std::unordered_map argument_map; + std::unordered_map short_arguments; + std::unordered_map reverse_short_arguments; + std::unordered_map long_arguments; + std::unordered_map reverse_long_arguments; - std::string program_name; - std::vector parsed_arguments; + std::list> on_complete_events; - private: - void assert_argument_not_exist(std::string const& short_arg, std::string const& long_arg) const { - if (short_arguments.contains(short_arg) || long_arguments.contains(long_arg)) { - throw std::runtime_error("The key already exists!"); - } - } - - static void set_argument_status(bool is_required, std::string const& help_text, argument& arg) { - arg.set_required(is_required); - arg.set_help_text(help_text); - } - - void place_argument(int id, argument const& arg, std::string const& short_arg, std::string const& long_arg) { - argument_map[id] = arg; - short_arguments[short_arg] = id; - reverse_short_arguments[id] = short_arg; - long_arguments[long_arg] = id; - reverse_long_arguments[id] = long_arg; - } - - template - void base_add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, ActionType const& action, bool required) { - assert_argument_not_exist(short_arg, long_arg); - int id = id_counter.fetch_add(1); - argument arg(id, short_arg + "|" + long_arg, action); - set_argument_status(required, help_text, arg); - place_argument(id, arg, short_arg, long_arg); - } - - template - void base_add_argument(std::string const& short_arg, std::string const& long_arg, std::string const& help_text, bool required) { - assert_argument_not_exist(short_arg, long_arg); - int id = id_counter.fetch_add(1); - if constexpr (std::is_same_v) { - auto action = helpers::make_non_parametered_action([id, this] { stored_arguments[id] = std::any{ true }; }); - argument arg(id, short_arg + "|" + long_arg, action); - set_argument_status(required, help_text, arg); - place_argument(id, arg, short_arg, long_arg); - } else { - auto action = helpers::make_parametered_action([id, this](StoreType const& value) { stored_arguments[id] = std::any{ value }; }); - argument arg(id, short_arg + "|" + long_arg, action); - set_argument_status(required, help_text, arg); - place_argument(id, arg, short_arg, long_arg); - } - } - - void check_for_required_arguments(std::initializer_list convention_types) { - std::vector> required_args; - for (const auto &arg: argument_map | std::views::values) { - if (arg.is_required() and not arg.is_invoked()) { - required_args.emplace_back>({ - reverse_short_arguments[arg.id], - reverse_long_arguments[arg.id] - }); - } - } - - if (not required_args.empty()) { - std::cerr << "These arguments were expected but not provided: "; - for (auto const& [s, l] : required_args) { - std::cerr << "[-" << s << ", --" << l << "] "; - } - std::cerr << "\n"; - display_help(convention_types); - } - } - - void fire_on_complete_events() const { - for(auto const& event : on_complete_events) { - event(*this); - } - } - - inline static std::atomic_int id_counter = 0; - - std::unordered_map stored_arguments; - std::unordered_map argument_map; - std::unordered_map short_arguments; - std::unordered_map reverse_short_arguments; - std::unordered_map long_arguments; - std::unordered_map reverse_long_arguments; - - std::list> on_complete_events; - - friend class linux_parser; - friend class windows_parser; - friend class macos_parser; - friend class fake_parser; - }; -} + friend class linux_parser; + friend class windows_parser; + friend class macos_parser; + friend class fake_parser; + }; +} // namespace argument_parser #endif // ARGUMENT_PARSER_HPP \ No newline at end of file diff --git a/src/headers/parser/platform_headers/macos_parser.hpp b/src/headers/parser/platform_headers/macos_parser.hpp index da55102..f63c2f5 100644 --- a/src/headers/parser/platform_headers/macos_parser.hpp +++ b/src/headers/parser/platform_headers/macos_parser.hpp @@ -9,34 +9,18 @@ #include namespace argument_parser { - class macos_parser : public base_parser { - public: - macos_parser() { - const int argc = *_NSGetArgc(); - if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { - program_name = (argv[0]); - for (int i = 1; i < argc; ++i) { - if (argv[i] != nullptr) parsed_arguments.emplace_back(argv[i]); - } - } - } - }; + class macos_parser : public base_parser { + public: + macos_parser(); + }; - namespace v2 { - class macos_parser : public v2::base_parser { - public: - macos_parser() { - const int argc = *_NSGetArgc(); - if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { - set_program_name(argv[0]); - for (int i = 1; i < argc; ++i) { - if (argv[i] != nullptr) ref_parsed_args().emplace_back(argv[i]); - } - } - } - }; - } -} + namespace v2 { + class macos_parser : public v2::base_parser { + public: + macos_parser(); + }; + } // namespace v2 +} // namespace argument_parser #endif #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c164094..a33bd5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include "macos_parser.hpp" #include #define ALLOW_DASH_FOR_WINDOWS 0 @@ -8,8 +7,10 @@ #include #include #include +#include #include + struct Point { int x, y; }; @@ -35,7 +36,7 @@ template <> struct argument_parser::parsing_traits::parser_trait { template <> struct argument_parser::parsing_traits::parser_trait> { static std::vector parse(const std::string &input) { std::vector result; - std::stringstream ss(input); + std::stringstream ss{input}; std::string item; while (std::getline(ss, item, ',')) { result.push_back(std::stoi(item)); diff --git a/src/source/parser/argument_parser.cpp b/src/source/parser/argument_parser.cpp new file mode 100644 index 0000000..dcbbf61 --- /dev/null +++ b/src/source/parser/argument_parser.cpp @@ -0,0 +1,205 @@ +#include "argument_parser.hpp" + +#include +#include + +bool contains(std::unordered_map const &map, std::string const &key) { + return map.find(key) != map.end(); +} + +namespace argument_parser { + argument::argument() + : id(0), name(), action(std::make_unique([]() {})), required(false), invoked(false) {} + + argument::argument(const argument &other) + : id(other.id), name(other.name), action(other.action->clone()), required(other.required), + invoked(other.invoked), help_text(other.help_text) {} + + argument &argument::operator=(const argument &other) { + if (this != &other) { + id = other.id; + name = other.name; + action = other.action->clone(); + required = other.required; + invoked = other.invoked; + help_text = other.help_text; + } + return *this; + } + + bool argument::is_required() const { + return required; + } + + bool argument::is_invoked() const { + return invoked; + } + + std::string argument::get_name() const { + return name; + } + + std::string argument::get_help_text() const { + return help_text; + } + + void argument::set_required(bool val) { + required = val; + } + + void argument::set_invoked(bool val) { + invoked = val; + } + + void argument::set_help_text(std::string const &text) { + help_text = text; + } + + void base_parser::on_complete(std::function const &handler) { + on_complete_events.emplace_back(handler); + } + + std::string + base_parser::build_help_text(std::initializer_list convention_types) const { + std::stringstream ss; + ss << "Usage: " << program_name << " [OPTIONS]...\n"; + + for (auto const &[id, arg] : argument_map) { + auto short_arg = reverse_short_arguments.at(id); + auto long_arg = reverse_long_arguments.at(id); + ss << "\t"; + for (auto const &convention : convention_types) { + ss << convention->short_prec() << short_arg << ", " << convention->long_prec() << long_arg << "\t"; + } + ss << arg.help_text << "\n"; + } + return ss.str(); + } + + argument &base_parser::get_argument(conventions::parsed_argument const &arg) { + if (arg.first == conventions::argument_type::LONG) { + auto long_pos = long_arguments.find(arg.second); + if (long_pos != long_arguments.end()) + return argument_map.at(long_pos->second); + } else if (arg.first == conventions::argument_type::SHORT) { + auto short_pos = short_arguments.find(arg.second); + if (short_pos != short_arguments.end()) + return argument_map.at(short_pos->second); + } else if (arg.first == conventions::argument_type::INTERCHANGABLE) { + auto long_pos = long_arguments.find(arg.second); + if (long_pos != long_arguments.end()) + return argument_map.at(long_pos->second); + auto short_pos = short_arguments.find(arg.second); + if (short_pos != short_arguments.end()) + return argument_map.at(short_pos->second); + } + throw std::runtime_error("Unknown argument: " + arg.second); + } + + void base_parser::handle_arguments(std::initializer_list convention_types) { + for (auto it = parsed_arguments.begin(); it != parsed_arguments.end(); ++it) { + std::stringstream error_stream; + bool arg_correctly_handled = false; + + for (auto const &convention_type : convention_types) { + auto extracted = convention_type->get_argument(*it); + if (extracted.first == conventions::argument_type::ERROR) { + error_stream << "Convention \"" << convention_type->name() << "\" failed with: " << extracted.second + << "\n"; + continue; + } + + try { + argument &corresponding_argument = get_argument(extracted); + + if (corresponding_argument.expects_parameter()) { + if (convention_type->requires_next_token() && (it + 1) == parsed_arguments.end()) { + throw std::runtime_error("expected value for argument " + extracted.second); + } + auto value_raw = + convention_type->requires_next_token() ? *(++it) : convention_type->extract_value(*it); + corresponding_argument.action->invoke_with_parameter(value_raw); + } else { + corresponding_argument.action->invoke(); + } + + corresponding_argument.set_invoked(true); + arg_correctly_handled = true; + break; // Convention succeeded, move to the next argument token + + } catch (const std::runtime_error &e) { + error_stream << "Convention \"" << convention_type->name() << "\" failed with: " << e.what() + << "\n"; + } + } + + if (!arg_correctly_handled) { + throw std::runtime_error("All trials for argument: \n\t\"" + *it + "\"\n failed with: \n" + + error_stream.str()); + } + } + check_for_required_arguments(convention_types); + fire_on_complete_events(); + } + + void base_parser::display_help(std::initializer_list convention_types) const { + std::cout << build_help_text(convention_types); + } + + std::optional base_parser::find_argument_id(std::string const &arg) const { + auto long_pos = long_arguments.find(arg); + auto short_post = short_arguments.find(arg); + + if (long_pos != long_arguments.end()) + return long_pos->second; + if (short_post != short_arguments.end()) + return short_post->second; + return std::nullopt; + } + + void base_parser::assert_argument_not_exist(std::string const &short_arg, std::string const &long_arg) const { + if (contains(short_arguments, short_arg) || contains(long_arguments, long_arg)) { + throw std::runtime_error("The key already exists!"); + } + } + + void base_parser::set_argument_status(bool is_required, std::string const &help_text, argument &arg) { + arg.set_required(is_required); + arg.set_help_text(help_text); + } + + void base_parser::place_argument(int id, argument const &arg, std::string const &short_arg, + std::string const &long_arg) { + argument_map[id] = arg; + short_arguments[short_arg] = id; + reverse_short_arguments[id] = short_arg; + long_arguments[long_arg] = id; + reverse_long_arguments[id] = long_arg; + } + + void base_parser::check_for_required_arguments( + std::initializer_list convention_types) { + std::vector> required_args; + for (auto const &[key, arg] : argument_map) { + if (arg.is_required() and not arg.is_invoked()) { + required_args.emplace_back>( + {reverse_short_arguments[key], reverse_long_arguments[key]}); + } + } + + if (not required_args.empty()) { + std::cerr << "These arguments were expected but not provided: "; + for (auto const &[s, l] : required_args) { + std::cerr << "[-" << s << ", --" << l << "] "; + } + std::cerr << "\n"; + display_help(convention_types); + } + } + + void base_parser::fire_on_complete_events() const { + for (auto const &event : on_complete_events) { + event(*this); + } + } +} // namespace argument_parser \ No newline at end of file diff --git a/src/source/parser/platform_parsers/macos_parser.cpp b/src/source/parser/platform_parsers/macos_parser.cpp new file mode 100644 index 0000000..b869077 --- /dev/null +++ b/src/source/parser/platform_parsers/macos_parser.cpp @@ -0,0 +1,31 @@ +#ifdef __APPLE__ + +#include "macos_parser.hpp" + +namespace argument_parser { + macos_parser::macos_parser() { + const int argc = *_NSGetArgc(); + if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { + program_name = (argv[0]); + for (int i = 1; i < argc; ++i) { + if (argv[i] != nullptr) + parsed_arguments.emplace_back(argv[i]); + } + } + } + + namespace v2 { + macos_parser::macos_parser() { + const int argc = *_NSGetArgc(); + if (char **argv = *_NSGetArgv(); argc > 0 && argv != nullptr && argv[0] != nullptr) { + set_program_name(argv[0]); + for (int i = 1; i < argc; ++i) { + if (argv[i] != nullptr) + ref_parsed_args().emplace_back(argv[i]); + } + } + } + } // namespace v2 +} // namespace argument_parser + +#endif \ No newline at end of file