diff options
author | Viet T. Nguyen <vietjtnguyen@gmail.com> | 2017-04-25 23:38:10 -0700 |
---|---|---|
committer | Viet T. Nguyen <vietjtnguyen@gmail.com> | 2017-04-25 23:38:10 -0700 |
commit | 03d43873705715441a95fdec34f0c42fdff45c63 (patch) | |
tree | a493a8d427cd0a2045fe5c7cde707c0ded348022 | |
parent | 7d0ab78ad3d5a4a649508430fbd529138ffa1667 (diff) |
Added argagg::fmt_string()
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | examples/joinargs.cpp | 17 | ||||
-rw-r--r-- | include/argagg/argagg.hpp | 80 | ||||
-rw-r--r-- | test/test.cpp | 25 |
4 files changed, 125 insertions, 2 deletions
@@ -1,3 +1,8 @@ +0.4.3 +----- + +- Added argagg::fmt_string() to format a string using the fmt program + 0.4.2 ----- diff --git a/examples/joinargs.cpp b/examples/joinargs.cpp index c45a693..4e74575 100644 --- a/examples/joinargs.cpp +++ b/examples/joinargs.cpp @@ -46,6 +46,15 @@ int main( "verbose", {"-v", "--verbose"}, "increases verbosity", 0}, { + "lorem-ipsum", {"--lorem-ipsum"}, + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim " + "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + "aliquip ex ea commodo consequat. Duis aute irure dolor in " + "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla " + "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " + "culpa qui officia deserunt mollit anim id est laborum.", 0}, + { "sep", {"-s", "--sep"}, "separator (default ',')", 1}, { @@ -67,16 +76,20 @@ int main( try { args = argparser.parse(argc, argv); } catch (const std::exception& e) { - cerr << usage.str() << argparser << endl + ostringstream help; + help << usage.str() << argparser << endl << "Encountered exception while parsing arguments: " << e.what() << endl; + cerr << argagg::fmt_string(help.str()) << endl;; return EXIT_FAILURE; } // If the help flag was specified then spit out the usage and help text and // exit. if (args["help"]) { - cerr << usage.str() << argparser; + ostringstream help; + help << usage.str() << argparser; + cerr << argagg::fmt_string(help.str()) << endl;; return EXIT_SUCCESS; } diff --git a/include/argagg/argagg.hpp b/include/argagg/argagg.hpp index 083730a..18b0b33 100644 --- a/include/argagg/argagg.hpp +++ b/include/argagg/argagg.hpp @@ -31,6 +31,11 @@ #ifndef ARGAGG_ARGAGG_ARGAGG_HPP #define ARGAGG_ARGAGG_ARGAGG_HPP +#ifdef __unix__ +#include <stdio.h> +#include <unistd.h> +#endif + #include <algorithm> #include <array> #include <cstdlib> @@ -587,6 +592,26 @@ struct parser { }; +#ifdef __unix__ + + +/** + * @brief + * Processes the provided string using the fmt util and returns the resulting + * output as a string. Not the most efficient (in time or space) but gets the + * job done. + * + * @note + * This is only defined if the <tt>__unix__</tt> preprocessor definition + * exists since it relies on the POSIX API for forking, executing a process, + * and reading/writing to/from file descriptors. + */ +std::string fmt_string(const std::string& s); + + +#endif + + } // namespace argagg @@ -1392,6 +1417,61 @@ namespace convert { } +#ifdef __unix__ + +inline +std::string fmt_string(const std::string& s) +{ + constexpr int read_end = 0; + constexpr int write_end = 1; + + // TODO (vnguyen): This function overall needs to handle possible error + // returns from the various syscalls. + + int read_pipe[2]; + int write_pipe[2]; + pipe(read_pipe); + pipe(write_pipe); + + auto parent_pid = fork(); + bool is_fmt_proc = (parent_pid == 0); + if (is_fmt_proc) { + dup2(write_pipe[read_end], STDIN_FILENO); + dup2(read_pipe[write_end], STDOUT_FILENO); + close(write_pipe[read_end]); + close(write_pipe[write_end]); + close(read_pipe[read_end]); + close(read_pipe[write_end]); + const char* argv[] = {"fmt", NULL}; + execvp(const_cast<char*>(argv[0]), const_cast<char**>(argv)); + } + + close(write_pipe[read_end]); + close(read_pipe[write_end]); + auto fmt_write_fd = write_pipe[write_end]; + write(fmt_write_fd, s.c_str(), s.length()); + close(fmt_write_fd); + + auto fmt_read_fd = read_pipe[read_end]; + std::ostringstream os; + char buf[64]; + while (true) { + auto read_count = read( + fmt_read_fd, reinterpret_cast<void*>(buf), sizeof(buf)); + if (read_count <= 0) { + break; + } + os.write(buf, static_cast<std::streamsize>(read_count)); + } + close(fmt_read_fd); + + return os.str(); +} + + +#endif + + } // namespace argagg diff --git a/test/test.cpp b/test/test.cpp index cff7ba9..c9bfd4e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -927,3 +927,28 @@ TEST_CASE("write options help") // Just checking for no exceptions for now. std::cout << parser; } + + +#ifdef __unix__ +TEST_CASE("fmt_string") +{ + std::string test( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " + "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " + "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " + "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " + "mollit anim id est laborum."); + std::string test_formatted = argagg::fmt_string(test); + std::string expected_output( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n" + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim\n" + "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\n" + "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate\n" + "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n" + "cupidatat non proident, sunt in culpa qui officia deserunt mollit anim\n" + "id est laborum.\n"); + CHECK(test_formatted == expected_output); +} +#endif |