From 31a05b70aa4bf792aa7396b3c4a1a40a0e701f3c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 6 Feb 2020 21:10:15 +0200 Subject: libcamera: utils: Add string splitter utility function Add a utils::split() function that splits a string for the purpose of iterating over substrings. It returns an object of unspecified type that can be used in range-based for loops. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Kieran Bingham --- Documentation/Doxyfile.in | 1 + src/libcamera/include/utils.h | 34 +++++++++++++++++++++++ src/libcamera/utils.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 1c46b04b..beeaf6d3 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS = libcamera::BoundMethodArgs \ libcamera::BoundMethodStatic \ libcamera::SignalBase \ libcamera::*::Private \ + libcamera::*::details::* \ std::* # The EXAMPLE_PATH tag can be used to specify one or more files or directories diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h index e467eb21..080ea661 100644 --- a/src/libcamera/include/utils.h +++ b/src/libcamera/include/utils.h @@ -108,6 +108,40 @@ inline _hex hex(uint64_t value, unsigned int width) size_t strlcpy(char *dst, const char *src, size_t size); +namespace details { + +class StringSplitter +{ +public: + StringSplitter(const std::string &str, const std::string &delim); + + class iterator + { + public: + iterator(const StringSplitter *ss, std::string::size_type pos); + + iterator &operator++(); + std::string operator*() const; + bool operator!=(const iterator &other) const; + + private: + const StringSplitter *ss_; + std::string::size_type pos_; + std::string::size_type next_; + }; + + iterator begin() const; + iterator end() const; + +private: + std::string str_; + std::string delim_; +}; + +} /* namespace details */ + +details::StringSplitter split(const std::string &str, const std::string &delim); + } /* namespace utils */ } /* namespace libcamera */ diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp index 4beffdab..94bbb883 100644 --- a/src/libcamera/utils.cpp +++ b/src/libcamera/utils.cpp @@ -199,6 +199,69 @@ size_t strlcpy(char *dst, const char *src, size_t size) return strlen(src); } +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim) + : str_(str), delim_(delim) +{ +} + +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos) + : ss_(ss), pos_(pos) +{ + next_ = ss_->str_.find(ss_->delim_, pos_); +} + +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++() +{ + pos_ = next_; + if (pos_ != std::string::npos) { + pos_ += ss_->delim_.length(); + next_ = ss_->str_.find(ss_->delim_, pos_); + } + + return *this; +} + +std::string details::StringSplitter::iterator::operator*() const +{ + std::string::size_type count; + count = next_ != std::string::npos ? next_ - pos_ : next_; + return ss_->str_.substr(pos_, count); +} + +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const +{ + return pos_ != other.pos_; +} + +details::StringSplitter::iterator details::StringSplitter::begin() const +{ + return iterator(this, 0); +} + +details::StringSplitter::iterator details::StringSplitter::end() const +{ + return iterator(this, std::string::npos); +} + +/** + * \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 + * \param[in] delim The delimiter string + * + * This function splits the string \a str into substrings based on the + * delimiter \a delim. It returns an object of unspecified type that can be + * used in a range-based for loop and yields the substrings in sequence. + * + * \return An object that can be used in a range-based for loop to iterate over + * the substrings + */ +details::StringSplitter split(const std::string &str, const std::string &delim) +{ + /** \todo Try to avoid copies of str and delim */ + return details::StringSplitter(str, delim); +} + } /* namespace utils */ } /* namespace libcamera */ -- cgit v1.2.1