From patchwork Sat Apr 4 00:44:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 3379 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 97F16605D1 for ; Sat, 4 Apr 2020 02:44:52 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DWb1CjQ8"; dkim-atps=neutral Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0C5E972E; Sat, 4 Apr 2020 02:44:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1585961092; bh=GJot6HF1SG9eiADRdo2WwxIhwXYKPWyxLEI7qzHNHyk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DWb1CjQ8qGHe7a3jrBPdRhp9DrlJq6zJMwStqoWbs1iG05eyd/704TOkJCPFfFPt6 cODMq0+l8evj+q/cWMVXXrHN62/sHrsyjQH7ku5T+pFYmOTYjYfblfrSVudsm2MElc MAbOGDLAC1ZTRNbrQiZh/IYbMbMVwFaiYHLmusTE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Martijn Braam , Benjamin GAIGNARD , Andrey Konovalov Date: Sat, 4 Apr 2020 03:44:29 +0300 Message-Id: <20200404004438.17992-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200404004438.17992-1-laurent.pinchart@ideasonboard.com> References: <20200404004438.17992-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 02/11] libcamera: utils: Add string join function X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Apr 2020 00:44:52 -0000 Add a utils::join() function to join elements of a container into a string, with a separator and an optional conversion function if the elements are not implicitly convertible to std::string. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi --- Changes since v3: - Add a test for the conversion function --- src/libcamera/include/utils.h | 44 +++++++++++++++++++++++++++++++++++ src/libcamera/utils.cpp | 16 +++++++++++++ test/utils.cpp | 20 +++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h index cfa620f24581..242eeded9d50 100644 --- a/src/libcamera/include/utils.h +++ b/src/libcamera/include/utils.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,49 @@ inline _hex hex(uint64_t value, unsigned int width) size_t strlcpy(char *dst, const char *src, size_t size); +#ifndef __DOXYGEN__ +template +std::string join(const Container &items, const std::string &sep, UnaryOp op) +{ + std::ostringstream ss; + bool first = true; + + for (typename Container::const_iterator it = std::begin(items); + it != std::end(items); ++it) { + if (!first) + ss << sep; + else + first = false; + + ss << op(*it); + } + + return ss.str(); +} + +template +std::string join(const Container &items, const std::string &sep) +{ + std::ostringstream ss; + bool first = true; + + for (typename Container::const_iterator it = std::begin(items); + it != std::end(items); ++it) { + if (!first) + ss << sep; + else + first = false; + + ss << *it; + } + + return ss.str(); +} +#else +template +std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr); +#endif + namespace details { class StringSplitter diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp index 58ee7cc19c8c..97f9b632e45b 100644 --- a/src/libcamera/utils.cpp +++ b/src/libcamera/utils.cpp @@ -297,6 +297,22 @@ details::StringSplitter::iterator details::StringSplitter::end() const return iterator(this, std::string::npos); } +/** + * \fn template \ + * std::string utils::join(const Container &items, const std::string &sep, UnaryOp op) + * \brief Join elements of a container in a string with a separator + * \param[in] items The container + * \param[in] sep The separator to add between elements + * \param[in] op A function that converts individual elements to strings + * + * This function joins all elements in the \a items container into a string and + * returns it. The \a sep separator is added between elements. If the container + * elements are not implicitly convertible to std::string, the \a op function + * shall be provided to perform conversion of elements to std::string. + * + * \return A string that concatenates all elements in the container + */ + /** * \fn split(const std::string &str, const std::string &delim) * \brief Split a string based on a delimiter diff --git a/test/utils.cpp b/test/utils.cpp index 58816f153066..55ce9365a53e 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "test.h" #include "utils.h" @@ -99,7 +101,7 @@ protected: return TestFail; } - /* utils::split() test. */ + /* utils::join() and utils::split() test. */ std::vector elements = { "/bin", "/usr/bin", @@ -111,6 +113,11 @@ protected: for (const auto &element : elements) path += (path.empty() ? "" : ":") + element; + if (path != utils::join(elements, ":")) { + cerr << "utils::join() test failed" << endl; + return TestFail; + } + std::vector dirs; for (const auto &dir : utils::split(path, ":")) @@ -121,6 +128,17 @@ protected: return TestFail; } + /* utils::join() with conversion function test. */ + std::vector sizes = { { 0, 0 }, { 100, 100 } }; + s = utils::join(sizes, "/", [](const Size &size) { + return size.toString(); + }); + + if (s != "0x0/100x100") { + cerr << "utils::join() with conversion test failed" << endl; + return TestFail; + } + /* utils::dirname() tests. */ if (TestPass != testDirname()) return TestFail;