From ab4c1b8a8b67fd9ffc89c804efa260584530897d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 28 Jul 2024 16:23:13 +0200 Subject: Factor out and generalize/extend to_stream_quoted(string) --- libbuild2/script/script.cxx | 45 ++------------------------------------------ libbuild2/utility.cxx | 46 ++++++++++++++++++++++++++++++++++++++++++++- libbuild2/utility.hxx | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 44 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/script/script.cxx b/libbuild2/script/script.cxx index b53fc23..ee2c9aa 100644 --- a/libbuild2/script/script.cxx +++ b/libbuild2/script/script.cxx @@ -237,56 +237,15 @@ namespace build2 } } - // Quote a string unconditionally, assuming it contains some special - // characters. - // - // If the quote character is present in the string then it is double - // quoted rather than single quoted. In this case the following characters - // are escaped: - // - // \" - // - static void - to_stream_quoted (ostream& o, const char* s) - { - if (strchr (s, '\'') != nullptr) - { - o << '"'; - - for (; *s != '\0'; ++s) - { - // Escape characters special inside double quotes. - // - if (strchr ("\\\"", *s) != nullptr) - o << '\\'; - - o << *s; - } - - o << '"'; - } - else - o << '\'' << s << '\''; - } - - static inline void - to_stream_quoted (ostream& o, const string& s) - { - to_stream_quoted (o, s.c_str ()); - } - // Quote if empty or contains spaces or any of the command line special // characters. // - static void + static inline void to_stream_q (ostream& o, const string& s) { // NOTE: update dump(line) if adding any new special character. // - if (s.empty () || s.find_first_of (" |&<>=\\\"'") != string::npos) - to_stream_quoted (o, s); - else - o << s; + to_stream_quoted (o, s, " |&<>=\\\"'"); } void diff --git a/libbuild2/utility.cxx b/libbuild2/utility.cxx index 1135851..ae7c9b0 100644 --- a/libbuild2/utility.cxx +++ b/libbuild2/utility.cxx @@ -16,7 +16,7 @@ #endif #include // ENOENT -#include // strlen(), str[n]cmp() +#include // strlen(), str[n]cmp(), strchr() #include // cerr #include @@ -1011,4 +1011,48 @@ namespace build2 return r; } + + void + to_stream_quoted (ostream& o, const char* s) + { + if (strchr (s, '\'') != nullptr) + { + o << '"'; + + for (; *s != '\0'; ++s) + { + // Escape characters special inside double quotes. + // + if (strchr ("\\\"", *s) != nullptr) + o << '\\'; + + o << *s; + } + + o << '"'; + } + else + o << '\'' << s << '\''; + } + + void + to_stream_quoted (ostream& o, const string& s, const char* special, bool e) + { + if ((e && s.empty ()) || s.find_first_of (special) != string::npos) + to_stream_quoted (o, s); + else + o << s; + } + + void + to_stream_quoted (ostream& o, const strings& ss, const char* special) + { + for (auto b (ss.begin ()), i (b), e (ss.end ()); i != e; ++i) + { + if (i != b) + o << ' '; + + to_stream_quoted (o, *i, special); + } + } } diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx index 151b409..f4fd7bc 100644 --- a/libbuild2/utility.hxx +++ b/libbuild2/utility.hxx @@ -1114,6 +1114,39 @@ namespace build2 // optional parse_number (const string&, uint64_t max = UINT64_MAX); + + + // Write a string to a stream, single or double-quoting it unconditionally. + // + // If no quote characters are present in the string, then it is single- + // quoted. Otherwise, it is double quoted and the `\"` characters (backslach + // and double quote) inside the string are escaped. + // + LIBBUILD2_SYMEXPORT void + to_stream_quoted (ostream&, const char*); + + inline void + to_stream_quoted (ostream& o, const string& s) + { + to_stream_quoted (o, s.c_str ()); + } + + // As above but only quote the string if it contains any of the specified + // special characters (which should include backslash as well as single and + // double quotes) or is empty (unless empty is false). + // + LIBBUILD2_SYMEXPORT void + to_stream_quoted (ostream&, const string&, + const char* special, bool empty = true); + + // Write a vector of strings to a stream separating elements with a space + // and quoting each element if it is empty or contains any of the specified + // special characters (which should include space and backslash as well as + // single and double quotes; this is also the default which is suitable for + // displaying command line options, etc). + // + LIBBUILD2_SYMEXPORT void + to_stream_quoted (ostream&, const strings&, const char* special = " \\\"'"); } #include -- cgit v1.1