summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViet T. Nguyen <vietjtnguyen@gmail.com>2017-04-25 23:38:10 -0700
committerViet T. Nguyen <vietjtnguyen@gmail.com>2017-04-25 23:38:10 -0700
commit03d43873705715441a95fdec34f0c42fdff45c63 (patch)
treea493a8d427cd0a2045fe5c7cde707c0ded348022
parent7d0ab78ad3d5a4a649508430fbd529138ffa1667 (diff)
Added argagg::fmt_string()
-rw-r--r--CHANGELOG5
-rw-r--r--examples/joinargs.cpp17
-rw-r--r--include/argagg/argagg.hpp80
-rw-r--r--test/test.cpp25
4 files changed, 125 insertions, 2 deletions
diff --git a/CHANGELOG b/CHANGELOG
index bde08f8..a7ab035 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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