/* * This source code is released into the public domain. */ #ifndef LFJAIL_ARGV_HH #define LFJAIL_ARGV_HH #include #include #include #include namespace lfjail { /* * argv: stores a null-terminated array of nul-terminated C strings. * argv::data() is suitable for passing to ::execv(). * * Create an argv using argv::from_range(), which takes a range of * string-like objects. */ struct argv { /* * Create a new argv from a range. */ static auto from_range(std::ranges::range auto &&args) -> argv { auto ret = argv{}; for (auto &&arg : args) ret._add_arg(std::string_view(arg)); ret._args.push_back(nullptr); return ret; } template static auto from_args(std::initializer_list &&args) { return from_range(std::move(args)); } argv(argv &&) noexcept = default; auto operator=(this argv &, argv &&other) -> argv& = default; // Not copyable. TODO: for completeness, it probably should be. argv(argv const &) = delete; auto operator=(this argv &, argv const &other) -> argv& = delete; ~argv(); // Access the stored arguments. auto data(this argv const &self) -> char const * const * { return self._args.data(); } auto data(this argv &self) -> char * const * { return self._args.data(); } auto size(this argv const &self) { return self._args.size(); } // Range access auto begin(this argv const &self) { return self._args.begin(); } auto end(this argv const &self) { return self._args.end(); } private: // Use the from_range() factory method to create new instances. argv() = default; // The argument pointers, including the null terminator. std::vector _args; // Add a new argument to the array. auto _add_arg(this argv &self, std::string_view arg) -> void; }; } // namespace lf #endif // !LFJAIL_ARGV_HH