From a49b85595804338b62ba5e37dee8458924a7be16 Mon Sep 17 00:00:00 2001 From: Ryan Cohen Date: Fri, 24 Nov 2023 12:02:47 -0500 Subject: [PATCH] Add interleaveComma function from LLVM Taken from https://github.com/llvm/llvm-project/blob/6b87d84ff45d03c244e7511fba9359776ce27977/llvm/include/llvm/ADT/STLExtras.h#L2134C18-L2134C18 --- src/STLExtras.h | 63 ++++++++++++++++++++++++++++++++++++++++++ src/cli/clioptions.cpp | 27 ++++++------------ 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/STLExtras.h b/src/STLExtras.h index f75705066..78a373099 100644 --- a/src/STLExtras.h +++ b/src/STLExtras.h @@ -417,6 +417,69 @@ auto find_if_not(R &&Range, UnaryPredicate P) { return std::find_if_not(adl_begin(Range), adl_end(Range), P); } +/// An STL-style algorithm similar to std::for_each that applies a second +/// functor between every pair of elements. +/// +/// This provides the control flow logic to, for example, print a +/// comma-separated list: +/// \code +/// interleave(names.begin(), names.end(), +/// [&](StringRef name) { os << name; }, +/// [&] { os << ", "; }); +/// \endcode +template ::value && + !std::is_constructible::value>> +inline void interleave(ForwardIterator begin, ForwardIterator end, + UnaryFunctor each_fn, NullaryFunctor between_fn) { + if (begin == end) + return; + each_fn(*begin); + ++begin; + for (; begin != end; ++begin) { + between_fn(); + each_fn(*begin); + } +} + +template ::value && + !std::is_constructible::value>> +inline void interleave(const Container &c, UnaryFunctor each_fn, + NullaryFunctor between_fn) { + interleave(c.begin(), c.end(), each_fn, between_fn); +} + +/// Overload of interleave for the common case of string separator. +template > +inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn, + const std::string_view &separator) { + interleave(c.begin(), c.end(), each_fn, [&] { os << separator; }); +} +template > +inline void interleave(const Container &c, StreamT &os, + const std::string_view &separator) { + interleave( + c, os, [&](const T &a) { os << a; }, separator); +} + +template > +inline void interleaveComma(const Container &c, StreamT &os, + UnaryFunctor each_fn) { + interleave(c, os, each_fn, ", "); +} +template > +inline void interleaveComma(const Container &c, StreamT &os) { + interleaveComma(c, os, [&](const T &a) { os << a; }); +} + } // namespace llvm #endif // LLVM_ADT_STLEXTRAS_H diff --git a/src/cli/clioptions.cpp b/src/cli/clioptions.cpp index 40e116420..8eeb4f0d3 100644 --- a/src/cli/clioptions.cpp +++ b/src/cli/clioptions.cpp @@ -5,7 +5,7 @@ #include #include -#include "isa/rv64isainfo.h" +#include "STLExtras.h" namespace Ripes { @@ -186,23 +186,14 @@ bool parseCLIOptions(QCommandLineParser &parser, QString &errorMessage, errorMessage = "Invalid register file type '" + regFile + "' specified (--reginit). Valid types for '" + parser.value("proc") + "' with extensions ["; - for (auto iter = options.isaExtensions.begin(); - iter != options.isaExtensions.end();) { - errorMessage += *iter; - ++iter; - if (iter != options.isaExtensions.end()) { - errorMessage += ", "; - } - } - errorMessage += "]: ["; - for (auto iter = fileNames.begin(); iter != fileNames.end();) { - errorMessage += *iter; - ++iter; - if (iter != fileNames.end()) { - errorMessage += ", "; - } - } - errorMessage += "]"; + std::stringstream extInfo; + std::string isaExtensions = + options.isaExtensions.join("").toStdString(); + llvm::interleaveComma(isaExtensions, extInfo); + extInfo << "]: ["; + llvm::interleaveComma(fileNames, extInfo); + extInfo << "]"; + errorMessage += extInfo.str(); return false; }