summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/include/utils.h44
-rw-r--r--src/libcamera/utils.cpp16
-rw-r--r--test/utils.cpp20
3 files changed, 79 insertions, 1 deletions
diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h
index cfa620f2..242eeded 100644
--- a/src/libcamera/include/utils.h
+++ b/src/libcamera/include/utils.h
@@ -11,6 +11,7 @@
#include <chrono>
#include <memory>
#include <ostream>
+#include <sstream>
#include <string>
#include <string.h>
#include <sys/time.h>
@@ -109,6 +110,49 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
size_t strlcpy(char *dst, const char *src, size_t size);
+#ifndef __DOXYGEN__
+template<typename Container, typename UnaryOp>
+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<typename Container>
+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<typename Container, typename UnaryOp>
+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 58ee7cc1..97f9b632 100644
--- a/src/libcamera/utils.cpp
+++ b/src/libcamera/utils.cpp
@@ -298,6 +298,22 @@ details::StringSplitter::iterator details::StringSplitter::end() const
}
/**
+ * \fn template<typename Container, typename UnaryOp> \
+ * 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
* \param[in] str The string to split
diff --git a/test/utils.cpp b/test/utils.cpp
index 58816f15..55ce9365 100644
--- a/test/utils.cpp
+++ b/test/utils.cpp
@@ -10,6 +10,8 @@
#include <string>
#include <vector>
+#include <libcamera/geometry.h>
+
#include "test.h"
#include "utils.h"
@@ -99,7 +101,7 @@ protected:
return TestFail;
}
- /* utils::split() test. */
+ /* utils::join() and utils::split() test. */
std::vector<std::string> 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<std::string> dirs;
for (const auto &dir : utils::split(path, ":"))
@@ -121,6 +128,17 @@ protected:
return TestFail;
}
+ /* utils::join() with conversion function test. */
+ std::vector<Size> 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;