[{"id":3707,"web_url":"https://patchwork.libcamera.org/comment/3707/","msgid":"<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>","date":"2020-02-13T13:24:27","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Laurent,\n\nOn 13/02/2020 13:09, Kieran Bingham wrote:\n> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> Add a utils::split() function that splits a string for the purpose of\n> iterating over substrings. It returns an object of unspecified type that\n> can be used in range-based for loops.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nThis is really helpful, thanks\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> ---\n>  Documentation/Doxyfile.in     |  1 +\n>  src/libcamera/include/utils.h | 34 +++++++++++++++++++\n>  src/libcamera/utils.cpp       | 62 +++++++++++++++++++++++++++++++++++\n>  3 files changed, 97 insertions(+)\n> \n> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> index 1c46b04b3f7e..beeaf6d3cf48 100644\n> --- a/Documentation/Doxyfile.in\n> +++ b/Documentation/Doxyfile.in\n> @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>                           libcamera::BoundMethodStatic \\\n>                           libcamera::SignalBase \\\n>                           libcamera::*::Private \\\n> +                         libcamera::*::details::* \\\n>                           std::*\n>  \n>  # The EXAMPLE_PATH tag can be used to specify one or more files or directories\n> diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h\n> index e467eb21c518..080ea6614de0 100644\n> --- a/src/libcamera/include/utils.h\n> +++ b/src/libcamera/include/utils.h\n> @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n>  \n>  size_t strlcpy(char *dst, const char *src, size_t size);\n>  \n> +namespace details {\n> +\n> +class StringSplitter\n> +{\n> +public:\n> +\tStringSplitter(const std::string &str, const std::string &delim);\n> +\n> +\tclass iterator\n> +\t{\n> +\tpublic:\n> +\t\titerator(const StringSplitter *ss, std::string::size_type pos);\n> +\n> +\t\titerator &operator++();\n> +\t\tstd::string operator*() const;\n> +\t\tbool operator!=(const iterator &other) const;\n> +\n> +\tprivate:\n> +\t\tconst StringSplitter *ss_;\n> +\t\tstd::string::size_type pos_;\n> +\t\tstd::string::size_type next_;\n> +\t};\n> +\n> +\titerator begin() const;\n> +\titerator end() const;\n> +\n> +private:\n> +\tstd::string str_;\n> +\tstd::string delim_;\n> +};\n> +\n> +} /* namespace details */\n> +\n> +details::StringSplitter split(const std::string &str, const std::string &delim);\n> +\n>  } /* namespace utils */\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp\n> index 4beffdab5eb6..fe027c0b009c 100644\n> --- a/src/libcamera/utils.cpp\n> +++ b/src/libcamera/utils.cpp\n> @@ -199,6 +199,68 @@ size_t strlcpy(char *dst, const char *src, size_t size)\n>  \treturn strlen(src);\n>  }\n>  \n> +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim)\n> +\t: str_(str), delim_(delim)\n> +{\n> +}\n> +\n> +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos)\n> +\t: ss_(ss), pos_(pos)\n> +{\n> +\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> +}\n> +\n> +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++()\n> +{\n> +\tpos_ = next_;\n> +\tif (pos_ != std::string::npos) {\n> +\t\tpos_ += ss_->delim_.length();\n> +\t\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> +\t}\n> +\n> +\treturn *this;\n> +}\n> +\n> +std::string details::StringSplitter::iterator::operator*() const\n> +{\n> +\tstd::string::size_type count;\n> +\tcount = next_ != std::string::npos ? next_ - pos_ : next_;\n> +\treturn ss_->str_.substr(pos_, count);\n> +}\n> +\n> +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const\n> +{\n> +\treturn pos_ != other.pos_;\n> +}\n> +\n> +details::StringSplitter::iterator details::StringSplitter::begin() const\n> +{\n> +\treturn iterator(this, 0);\n> +}\n> +\n> +details::StringSplitter::iterator details::StringSplitter::end() const\n> +{\n> +\treturn iterator(this, std::string::npos);\n> +}\n> +\n> +/**\n> + * \\fn split(const std::string &str, const std::string &delim)\n> + * \\brief Split a string based on a delimiter\n> + * \\param[in] str The string to split\n> + * \\param[in] delim The delimiter string\n> + *\n> + * This function splits the string \\a str into substrings based on the\n> + * delimiter \\a delim. It returns an object of unspecified type that can be\n> + * used in a range-based for loop and yields the substrings in sequence.\n> + *\n> + * \\return An object that can be used in a range-based for loop to iterate over\n> + * the substrings\n> + */\n> +details::StringSplitter split(const std::string &str, const std::string &delim)\n> +{\n> +\treturn details::StringSplitter(str, delim);\n> +}\n> +\n>  } /* namespace utils */\n>  \n>  } /* namespace libcamera */\n>","headers":{"Return-Path":"<kieran.bingham@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BFF6C6195F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Feb 2020 14:24:30 +0100 (CET)","from [192.168.0.20]\n\t(cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 40AEB504;\n\tThu, 13 Feb 2020 14:24:30 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581600270;\n\tbh=uYTi/7I9yMBcIgu4Rq3CI9Yy89/ZI66dezxQiFfnTE0=;\n\th=Subject:From:To:References:Date:In-Reply-To:From;\n\tb=UV6vpILpDUVOFfMJtjTSirZDwDel7xbdpvRn5dAeqi8ehw/ZCXR2DG/bVN+X/bLxL\n\tbLel02Cu1jzjUXY7JqRRg9QHXqkecAZ27fm0aqoYlBJnKrJVrXDerWPvJbe+VI/Qo+\n\tTjmRwGYsRjwgLgF3TRgAbXzVRuHjh6sNMT0veuTU=","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"libcamera devel <libcamera-devel@lists.libcamera.org>","References":"<20200213130908.23638-1-kieran.bingham@ideasonboard.com>\n\t<20200213130908.23638-2-kieran.bingham@ideasonboard.com>","Openpgp":"preference=signencrypt","Autocrypt":"addr=kieran.bingham@ideasonboard.com; keydata=\n\t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\n\tWZw01QYHU/GUV/zHJSFk","Organization":"Ideas on Board","Message-ID":"<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>","Date":"Thu, 13 Feb 2020 13:24:27 +0000","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101\n\tThunderbird/60.9.1","MIME-Version":"1.0","In-Reply-To":"<20200213130908.23638-2-kieran.bingham@ideasonboard.com>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 13 Feb 2020 13:24:31 -0000"}},{"id":3711,"web_url":"https://patchwork.libcamera.org/comment/3711/","msgid":"<20200213133604.GF4833@pendragon.ideasonboard.com>","date":"2020-02-13T13:36:04","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Thu, Feb 13, 2020 at 01:24:27PM +0000, Kieran Bingham wrote:\n> On 13/02/2020 13:09, Kieran Bingham wrote:\n> > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > \n> > Add a utils::split() function that splits a string for the purpose of\n> > iterating over substrings. It returns an object of unspecified type that\n> > can be used in range-based for loops.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> This is really helpful, thanks\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> > ---\n> >  Documentation/Doxyfile.in     |  1 +\n> >  src/libcamera/include/utils.h | 34 +++++++++++++++++++\n> >  src/libcamera/utils.cpp       | 62 +++++++++++++++++++++++++++++++++++\n> >  3 files changed, 97 insertions(+)\n> > \n> > diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> > index 1c46b04b3f7e..beeaf6d3cf48 100644\n> > --- a/Documentation/Doxyfile.in\n> > +++ b/Documentation/Doxyfile.in\n> > @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n> >                           libcamera::BoundMethodStatic \\\n> >                           libcamera::SignalBase \\\n> >                           libcamera::*::Private \\\n> > +                         libcamera::*::details::* \\\n> >                           std::*\n> >  \n> >  # The EXAMPLE_PATH tag can be used to specify one or more files or directories\n> > diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h\n> > index e467eb21c518..080ea6614de0 100644\n> > --- a/src/libcamera/include/utils.h\n> > +++ b/src/libcamera/include/utils.h\n> > @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n> >  \n> >  size_t strlcpy(char *dst, const char *src, size_t size);\n> >  \n> > +namespace details {\n> > +\n> > +class StringSplitter\n> > +{\n> > +public:\n> > +\tStringSplitter(const std::string &str, const std::string &delim);\n> > +\n> > +\tclass iterator\n> > +\t{\n> > +\tpublic:\n> > +\t\titerator(const StringSplitter *ss, std::string::size_type pos);\n> > +\n> > +\t\titerator &operator++();\n> > +\t\tstd::string operator*() const;\n> > +\t\tbool operator!=(const iterator &other) const;\n> > +\n> > +\tprivate:\n> > +\t\tconst StringSplitter *ss_;\n> > +\t\tstd::string::size_type pos_;\n> > +\t\tstd::string::size_type next_;\n> > +\t};\n> > +\n> > +\titerator begin() const;\n> > +\titerator end() const;\n> > +\n> > +private:\n> > +\tstd::string str_;\n> > +\tstd::string delim_;\n\nNote that I would really like if we could store references to str and\ndelim here, but my attempt to do so resulted in problems, I believe due\nto the values passed to the StringSplitter constructor being\ntemporaries. I don't know if there's a good way to solve that.\n\n> > +};\n> > +\n> > +} /* namespace details */\n> > +\n> > +details::StringSplitter split(const std::string &str, const std::string &delim);\n> > +\n> >  } /* namespace utils */\n> >  \n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp\n> > index 4beffdab5eb6..fe027c0b009c 100644\n> > --- a/src/libcamera/utils.cpp\n> > +++ b/src/libcamera/utils.cpp\n> > @@ -199,6 +199,68 @@ size_t strlcpy(char *dst, const char *src, size_t size)\n> >  \treturn strlen(src);\n> >  }\n> >  \n> > +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim)\n> > +\t: str_(str), delim_(delim)\n> > +{\n> > +}\n> > +\n> > +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos)\n> > +\t: ss_(ss), pos_(pos)\n> > +{\n> > +\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> > +}\n> > +\n> > +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++()\n> > +{\n> > +\tpos_ = next_;\n> > +\tif (pos_ != std::string::npos) {\n> > +\t\tpos_ += ss_->delim_.length();\n> > +\t\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> > +\t}\n> > +\n> > +\treturn *this;\n> > +}\n> > +\n> > +std::string details::StringSplitter::iterator::operator*() const\n> > +{\n> > +\tstd::string::size_type count;\n> > +\tcount = next_ != std::string::npos ? next_ - pos_ : next_;\n> > +\treturn ss_->str_.substr(pos_, count);\n> > +}\n> > +\n> > +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const\n> > +{\n> > +\treturn pos_ != other.pos_;\n> > +}\n> > +\n> > +details::StringSplitter::iterator details::StringSplitter::begin() const\n> > +{\n> > +\treturn iterator(this, 0);\n> > +}\n> > +\n> > +details::StringSplitter::iterator details::StringSplitter::end() const\n> > +{\n> > +\treturn iterator(this, std::string::npos);\n> > +}\n> > +\n> > +/**\n> > + * \\fn split(const std::string &str, const std::string &delim)\n> > + * \\brief Split a string based on a delimiter\n> > + * \\param[in] str The string to split\n> > + * \\param[in] delim The delimiter string\n> > + *\n> > + * This function splits the string \\a str into substrings based on the\n> > + * delimiter \\a delim. It returns an object of unspecified type that can be\n> > + * used in a range-based for loop and yields the substrings in sequence.\n> > + *\n> > + * \\return An object that can be used in a range-based for loop to iterate over\n> > + * the substrings\n> > + */\n> > +details::StringSplitter split(const std::string &str, const std::string &delim)\n> > +{\n> > +\treturn details::StringSplitter(str, delim);\n> > +}\n> > +\n> >  } /* namespace utils */\n> >  \n> >  } /* namespace libcamera */","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 89F1D6195F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Feb 2020 14:36:21 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DFE98504;\n\tThu, 13 Feb 2020 14:36:20 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581600981;\n\tbh=8Sfl+BJq2/ZELNVNEa2VeT3bEpIv/Fyx9YGdj+C0e2Q=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=DQBb9ox/hwUy/XOv4PBGYrbzVKQdg2kJQvYOzDNx12kNJyGhyVFn5NsnXHmBwqduq\n\tBFjMHBjE9gh4eTYlgGWqfkMHJK/0H1KdhVEO+lYQmmm/Ur+HXjNwBDGVvwcHIzdg9R\n\tWVU+NwdtAqRHefIc+xA75MoM0bhKBkh2inuKCROI=","Date":"Thu, 13 Feb 2020 15:36:04 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Message-ID":"<20200213133604.GF4833@pendragon.ideasonboard.com>","References":"<20200213130908.23638-1-kieran.bingham@ideasonboard.com>\n\t<20200213130908.23638-2-kieran.bingham@ideasonboard.com>\n\t<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 13 Feb 2020 13:36:21 -0000"}},{"id":3727,"web_url":"https://patchwork.libcamera.org/comment/3727/","msgid":"<4e627d36-5668-5c3a-912d-82806532d175@ideasonboard.com>","date":"2020-02-13T16:10:10","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Laurent,\n\nOn 13/02/2020 13:36, Laurent Pinchart wrote:\n> Hi Kieran,\n> \n> On Thu, Feb 13, 2020 at 01:24:27PM +0000, Kieran Bingham wrote:\n>> On 13/02/2020 13:09, Kieran Bingham wrote:\n>>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>>>\n>>> Add a utils::split() function that splits a string for the purpose of\n>>> iterating over substrings. It returns an object of unspecified type that\n>>> can be used in range-based for loops.\n>>>\n>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>>\n>> This is really helpful, thanks\n>>\n>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>>\n>>> ---\n>>>  Documentation/Doxyfile.in     |  1 +\n>>>  src/libcamera/include/utils.h | 34 +++++++++++++++++++\n>>>  src/libcamera/utils.cpp       | 62 +++++++++++++++++++++++++++++++++++\n>>>  3 files changed, 97 insertions(+)\n>>>\n>>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n>>> index 1c46b04b3f7e..beeaf6d3cf48 100644\n>>> --- a/Documentation/Doxyfile.in\n>>> +++ b/Documentation/Doxyfile.in\n>>> @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>>>                           libcamera::BoundMethodStatic \\\n>>>                           libcamera::SignalBase \\\n>>>                           libcamera::*::Private \\\n>>> +                         libcamera::*::details::* \\\n>>>                           std::*\n>>>  \n>>>  # The EXAMPLE_PATH tag can be used to specify one or more files or directories\n>>> diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h\n>>> index e467eb21c518..080ea6614de0 100644\n>>> --- a/src/libcamera/include/utils.h\n>>> +++ b/src/libcamera/include/utils.h\n>>> @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n>>>  \n>>>  size_t strlcpy(char *dst, const char *src, size_t size);\n>>>  \n>>> +namespace details {\n>>> +\n>>> +class StringSplitter\n>>> +{\n>>> +public:\n>>> +\tStringSplitter(const std::string &str, const std::string &delim);\n>>> +\n>>> +\tclass iterator\n>>> +\t{\n>>> +\tpublic:\n>>> +\t\titerator(const StringSplitter *ss, std::string::size_type pos);\n>>> +\n>>> +\t\titerator &operator++();\n>>> +\t\tstd::string operator*() const;\n>>> +\t\tbool operator!=(const iterator &other) const;\n>>> +\n>>> +\tprivate:\n>>> +\t\tconst StringSplitter *ss_;\n>>> +\t\tstd::string::size_type pos_;\n>>> +\t\tstd::string::size_type next_;\n>>> +\t};\n>>> +\n>>> +\titerator begin() const;\n>>> +\titerator end() const;\n>>> +\n>>> +private:\n>>> +\tstd::string str_;\n>>> +\tstd::string delim_;\n> \n> Note that I would really like if we could store references to str and\n> delim here, but my attempt to do so resulted in problems, I believe due\n> to the values passed to the StringSplitter constructor being\n> temporaries. I don't know if there's a good way to solve that.\n\nThis isn't used in any hot-path, so I'm not worried for now.\n\nIf it comes up in the future it can be investigated then.\n\nWould you like to add a todo: ? or not worth it?\n\n\n>>> +};\n>>> +\n>>> +} /* namespace details */\n>>> +\n>>> +details::StringSplitter split(const std::string &str, const std::string &delim);\n>>> +\n>>>  } /* namespace utils */\n>>>  \n>>>  } /* namespace libcamera */\n>>> diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp\n>>> index 4beffdab5eb6..fe027c0b009c 100644\n>>> --- a/src/libcamera/utils.cpp\n>>> +++ b/src/libcamera/utils.cpp\n>>> @@ -199,6 +199,68 @@ size_t strlcpy(char *dst, const char *src, size_t size)\n>>>  \treturn strlen(src);\n>>>  }\n>>>  \n>>> +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim)\n>>> +\t: str_(str), delim_(delim)\n>>> +{\n>>> +}\n>>> +\n>>> +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos)\n>>> +\t: ss_(ss), pos_(pos)\n>>> +{\n>>> +\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n>>> +}\n>>> +\n>>> +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++()\n>>> +{\n>>> +\tpos_ = next_;\n>>> +\tif (pos_ != std::string::npos) {\n>>> +\t\tpos_ += ss_->delim_.length();\n>>> +\t\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n>>> +\t}\n>>> +\n>>> +\treturn *this;\n>>> +}\n>>> +\n>>> +std::string details::StringSplitter::iterator::operator*() const\n>>> +{\n>>> +\tstd::string::size_type count;\n>>> +\tcount = next_ != std::string::npos ? next_ - pos_ : next_;\n>>> +\treturn ss_->str_.substr(pos_, count);\n>>> +}\n>>> +\n>>> +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const\n>>> +{\n>>> +\treturn pos_ != other.pos_;\n>>> +}\n>>> +\n>>> +details::StringSplitter::iterator details::StringSplitter::begin() const\n>>> +{\n>>> +\treturn iterator(this, 0);\n>>> +}\n>>> +\n>>> +details::StringSplitter::iterator details::StringSplitter::end() const\n>>> +{\n>>> +\treturn iterator(this, std::string::npos);\n>>> +}\n>>> +\n>>> +/**\n>>> + * \\fn split(const std::string &str, const std::string &delim)\n>>> + * \\brief Split a string based on a delimiter\n>>> + * \\param[in] str The string to split\n>>> + * \\param[in] delim The delimiter string\n>>> + *\n>>> + * This function splits the string \\a str into substrings based on the\n>>> + * delimiter \\a delim. It returns an object of unspecified type that can be\n>>> + * used in a range-based for loop and yields the substrings in sequence.\n>>> + *\n>>> + * \\return An object that can be used in a range-based for loop to iterate over\n>>> + * the substrings\n>>> + */\n>>> +details::StringSplitter split(const std::string &str, const std::string &delim)\n>>> +{\n>>> +\treturn details::StringSplitter(str, delim);\n>>> +}\n>>> +\n>>>  } /* namespace utils */\n>>>  \n>>>  } /* namespace libcamera */\n>","headers":{"Return-Path":"<kieran.bingham@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E125D619E7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Feb 2020 17:10:13 +0100 (CET)","from [192.168.0.20]\n\t(cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 79F2D9D3;\n\tThu, 13 Feb 2020 17:10:13 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581610213;\n\tbh=5V3A+8oiuspXE1JwWXHAeinQSC+mIs2SDnAlOvP/mnE=;\n\th=Reply-To:Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=Y7rGh8gk/zOQ0YD3zAfJica2kVUWl+1b6OocLOosZXS1CtNVYWjjGGNuOPtGbqG5S\n\tiDaFefPeub4Qqdk6s+e7eRkbDA2RWtVyVnFnnHHoPyoY/k6YbVQPS3bcjF+sz7GQUJ\n\tfxQBhUMddu/UaIv0X5VNCzy0bJicZlUnNFj/J+MA=","Reply-To":"kieran.bingham@ideasonboard.com","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","References":"<20200213130908.23638-1-kieran.bingham@ideasonboard.com>\n\t<20200213130908.23638-2-kieran.bingham@ideasonboard.com>\n\t<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>\n\t<20200213133604.GF4833@pendragon.ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Openpgp":"preference=signencrypt","Autocrypt":"addr=kieran.bingham@ideasonboard.com; keydata=\n\t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\n\tWZw01QYHU/GUV/zHJSFk","Organization":"Ideas on Board","Message-ID":"<4e627d36-5668-5c3a-912d-82806532d175@ideasonboard.com>","Date":"Thu, 13 Feb 2020 16:10:10 +0000","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101\n\tThunderbird/60.9.1","MIME-Version":"1.0","In-Reply-To":"<20200213133604.GF4833@pendragon.ideasonboard.com>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 13 Feb 2020 16:10:14 -0000"}},{"id":3731,"web_url":"https://patchwork.libcamera.org/comment/3731/","msgid":"<20200213162457.GB29760@pendragon.ideasonboard.com>","date":"2020-02-13T16:24:57","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Kieran,\n\nOn Thu, Feb 13, 2020 at 04:10:10PM +0000, Kieran Bingham wrote:\n> On 13/02/2020 13:36, Laurent Pinchart wrote:\n> > On Thu, Feb 13, 2020 at 01:24:27PM +0000, Kieran Bingham wrote:\n> >> On 13/02/2020 13:09, Kieran Bingham wrote:\n> >>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>>\n> >>> Add a utils::split() function that splits a string for the purpose of\n> >>> iterating over substrings. It returns an object of unspecified type that\n> >>> can be used in range-based for loops.\n> >>>\n> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>\n> >> This is really helpful, thanks\n> >>\n> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> >>\n> >>> ---\n> >>>  Documentation/Doxyfile.in     |  1 +\n> >>>  src/libcamera/include/utils.h | 34 +++++++++++++++++++\n> >>>  src/libcamera/utils.cpp       | 62 +++++++++++++++++++++++++++++++++++\n> >>>  3 files changed, 97 insertions(+)\n> >>>\n> >>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n> >>> index 1c46b04b3f7e..beeaf6d3cf48 100644\n> >>> --- a/Documentation/Doxyfile.in\n> >>> +++ b/Documentation/Doxyfile.in\n> >>> @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n> >>>                           libcamera::BoundMethodStatic \\\n> >>>                           libcamera::SignalBase \\\n> >>>                           libcamera::*::Private \\\n> >>> +                         libcamera::*::details::* \\\n> >>>                           std::*\n> >>>  \n> >>>  # The EXAMPLE_PATH tag can be used to specify one or more files or directories\n> >>> diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h\n> >>> index e467eb21c518..080ea6614de0 100644\n> >>> --- a/src/libcamera/include/utils.h\n> >>> +++ b/src/libcamera/include/utils.h\n> >>> @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n> >>>  \n> >>>  size_t strlcpy(char *dst, const char *src, size_t size);\n> >>>  \n> >>> +namespace details {\n> >>> +\n> >>> +class StringSplitter\n> >>> +{\n> >>> +public:\n> >>> +\tStringSplitter(const std::string &str, const std::string &delim);\n> >>> +\n> >>> +\tclass iterator\n> >>> +\t{\n> >>> +\tpublic:\n> >>> +\t\titerator(const StringSplitter *ss, std::string::size_type pos);\n> >>> +\n> >>> +\t\titerator &operator++();\n> >>> +\t\tstd::string operator*() const;\n> >>> +\t\tbool operator!=(const iterator &other) const;\n> >>> +\n> >>> +\tprivate:\n> >>> +\t\tconst StringSplitter *ss_;\n> >>> +\t\tstd::string::size_type pos_;\n> >>> +\t\tstd::string::size_type next_;\n> >>> +\t};\n> >>> +\n> >>> +\titerator begin() const;\n> >>> +\titerator end() const;\n> >>> +\n> >>> +private:\n> >>> +\tstd::string str_;\n> >>> +\tstd::string delim_;\n> > \n> > Note that I would really like if we could store references to str and\n> > delim here, but my attempt to do so resulted in problems, I believe due\n> > to the values passed to the StringSplitter constructor being\n> > temporaries. I don't know if there's a good way to solve that.\n> \n> This isn't used in any hot-path, so I'm not worried for now.\n> \n> If it comes up in the future it can be investigated then.\n> \n> Would you like to add a todo: ? or not worth it?\n\nIt's always good to keep todos in mind :-) Please see below.\n\n> >>> +};\n> >>> +\n> >>> +} /* namespace details */\n> >>> +\n> >>> +details::StringSplitter split(const std::string &str, const std::string &delim);\n> >>> +\n> >>>  } /* namespace utils */\n> >>>  \n> >>>  } /* namespace libcamera */\n> >>> diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp\n> >>> index 4beffdab5eb6..fe027c0b009c 100644\n> >>> --- a/src/libcamera/utils.cpp\n> >>> +++ b/src/libcamera/utils.cpp\n> >>> @@ -199,6 +199,68 @@ size_t strlcpy(char *dst, const char *src, size_t size)\n> >>>  \treturn strlen(src);\n> >>>  }\n> >>>  \n> >>> +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim)\n> >>> +\t: str_(str), delim_(delim)\n> >>> +{\n> >>> +}\n> >>> +\n> >>> +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos)\n> >>> +\t: ss_(ss), pos_(pos)\n> >>> +{\n> >>> +\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> >>> +}\n> >>> +\n> >>> +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++()\n> >>> +{\n> >>> +\tpos_ = next_;\n> >>> +\tif (pos_ != std::string::npos) {\n> >>> +\t\tpos_ += ss_->delim_.length();\n> >>> +\t\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n> >>> +\t}\n> >>> +\n> >>> +\treturn *this;\n> >>> +}\n> >>> +\n> >>> +std::string details::StringSplitter::iterator::operator*() const\n> >>> +{\n> >>> +\tstd::string::size_type count;\n> >>> +\tcount = next_ != std::string::npos ? next_ - pos_ : next_;\n> >>> +\treturn ss_->str_.substr(pos_, count);\n> >>> +}\n> >>> +\n> >>> +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const\n> >>> +{\n> >>> +\treturn pos_ != other.pos_;\n> >>> +}\n> >>> +\n> >>> +details::StringSplitter::iterator details::StringSplitter::begin() const\n> >>> +{\n> >>> +\treturn iterator(this, 0);\n> >>> +}\n> >>> +\n> >>> +details::StringSplitter::iterator details::StringSplitter::end() const\n> >>> +{\n> >>> +\treturn iterator(this, std::string::npos);\n> >>> +}\n> >>> +\n> >>> +/**\n> >>> + * \\fn split(const std::string &str, const std::string &delim)\n> >>> + * \\brief Split a string based on a delimiter\n> >>> + * \\param[in] str The string to split\n> >>> + * \\param[in] delim The delimiter string\n> >>> + *\n> >>> + * This function splits the string \\a str into substrings based on the\n> >>> + * delimiter \\a delim. It returns an object of unspecified type that can be\n> >>> + * used in a range-based for loop and yields the substrings in sequence.\n> >>> + *\n> >>> + * \\return An object that can be used in a range-based for loop to iterate over\n> >>> + * the substrings\n> >>> + */\n> >>> +details::StringSplitter split(const std::string &str, const std::string &delim)\n> >>> +{\n\n\t/** \\todo Try to avoid copies of str and delim */\n\n> >>> +\treturn details::StringSplitter(str, delim);\n> >>> +}\n> >>> +\n> >>>  } /* namespace utils */\n> >>>  \n> >>>  } /* namespace libcamera */","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 71B816196C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Feb 2020 17:25:14 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D1B6C504;\n\tThu, 13 Feb 2020 17:25:13 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581611114;\n\tbh=DXcQv2CouegpcdjeQku8gXjVRh42A+t/sp6jRQB/fOE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=ndXVpfTVQ4d8p+0QmA08FsUa7rfO34akjoPVDc0oH42NJBdZjEK2GkTjSuToUN4vC\n\tpg4NhmU+4cPqomQ32zhNTQxnribRhsF7GxQqS0lVOZAAocS7E44zTyxL5UwS/WbecV\n\tEaD4WgvPfflGSfb/osCOaRSJCHHBa8SOFxCOmZSg=","Date":"Thu, 13 Feb 2020 18:24:57 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Message-ID":"<20200213162457.GB29760@pendragon.ideasonboard.com>","References":"<20200213130908.23638-1-kieran.bingham@ideasonboard.com>\n\t<20200213130908.23638-2-kieran.bingham@ideasonboard.com>\n\t<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>\n\t<20200213133604.GF4833@pendragon.ideasonboard.com>\n\t<4e627d36-5668-5c3a-912d-82806532d175@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<4e627d36-5668-5c3a-912d-82806532d175@ideasonboard.com>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 13 Feb 2020 16:25:14 -0000"}},{"id":3734,"web_url":"https://patchwork.libcamera.org/comment/3734/","msgid":"<a91fb347-7f2d-496b-9111-5619f19c2b7b@ideasonboard.com>","date":"2020-02-13T16:32:02","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Laurent,\n\nOn 13/02/2020 16:24, Laurent Pinchart wrote:\n> Hi Kieran,\n> \n> On Thu, Feb 13, 2020 at 04:10:10PM +0000, Kieran Bingham wrote:\n>> On 13/02/2020 13:36, Laurent Pinchart wrote:\n>>> On Thu, Feb 13, 2020 at 01:24:27PM +0000, Kieran Bingham wrote:\n>>>> On 13/02/2020 13:09, Kieran Bingham wrote:\n>>>>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>>>>>\n>>>>> Add a utils::split() function that splits a string for the purpose of\n>>>>> iterating over substrings. It returns an object of unspecified type that\n>>>>> can be used in range-based for loops.\n>>>>>\n>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>>>>\n>>>> This is really helpful, thanks\n>>>>\n>>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>>>>\n>>>>> ---\n>>>>>  Documentation/Doxyfile.in     |  1 +\n>>>>>  src/libcamera/include/utils.h | 34 +++++++++++++++++++\n>>>>>  src/libcamera/utils.cpp       | 62 +++++++++++++++++++++++++++++++++++\n>>>>>  3 files changed, 97 insertions(+)\n>>>>>\n>>>>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in\n>>>>> index 1c46b04b3f7e..beeaf6d3cf48 100644\n>>>>> --- a/Documentation/Doxyfile.in\n>>>>> +++ b/Documentation/Doxyfile.in\n>>>>> @@ -880,6 +880,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \\\n>>>>>                           libcamera::BoundMethodStatic \\\n>>>>>                           libcamera::SignalBase \\\n>>>>>                           libcamera::*::Private \\\n>>>>> +                         libcamera::*::details::* \\\n>>>>>                           std::*\n>>>>>  \n>>>>>  # The EXAMPLE_PATH tag can be used to specify one or more files or directories\n>>>>> diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h\n>>>>> index e467eb21c518..080ea6614de0 100644\n>>>>> --- a/src/libcamera/include/utils.h\n>>>>> +++ b/src/libcamera/include/utils.h\n>>>>> @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n>>>>>  \n>>>>>  size_t strlcpy(char *dst, const char *src, size_t size);\n>>>>>  \n>>>>> +namespace details {\n>>>>> +\n>>>>> +class StringSplitter\n>>>>> +{\n>>>>> +public:\n>>>>> +\tStringSplitter(const std::string &str, const std::string &delim);\n>>>>> +\n>>>>> +\tclass iterator\n>>>>> +\t{\n>>>>> +\tpublic:\n>>>>> +\t\titerator(const StringSplitter *ss, std::string::size_type pos);\n>>>>> +\n>>>>> +\t\titerator &operator++();\n>>>>> +\t\tstd::string operator*() const;\n>>>>> +\t\tbool operator!=(const iterator &other) const;\n>>>>> +\n>>>>> +\tprivate:\n>>>>> +\t\tconst StringSplitter *ss_;\n>>>>> +\t\tstd::string::size_type pos_;\n>>>>> +\t\tstd::string::size_type next_;\n>>>>> +\t};\n>>>>> +\n>>>>> +\titerator begin() const;\n>>>>> +\titerator end() const;\n>>>>> +\n>>>>> +private:\n>>>>> +\tstd::string str_;\n>>>>> +\tstd::string delim_;\n>>>\n>>> Note that I would really like if we could store references to str and\n>>> delim here, but my attempt to do so resulted in problems, I believe due\n>>> to the values passed to the StringSplitter constructor being\n>>> temporaries. I don't know if there's a good way to solve that.\n>>\n>> This isn't used in any hot-path, so I'm not worried for now.\n>>\n>> If it comes up in the future it can be investigated then.\n>>\n>> Would you like to add a todo: ? or not worth it?\n> \n> It's always good to keep todos in mind :-) Please see below.\n> \n>>>>> +};\n>>>>> +\n>>>>> +} /* namespace details */\n>>>>> +\n>>>>> +details::StringSplitter split(const std::string &str, const std::string &delim);\n>>>>> +\n>>>>>  } /* namespace utils */\n>>>>>  \n>>>>>  } /* namespace libcamera */\n>>>>> diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp\n>>>>> index 4beffdab5eb6..fe027c0b009c 100644\n>>>>> --- a/src/libcamera/utils.cpp\n>>>>> +++ b/src/libcamera/utils.cpp\n>>>>> @@ -199,6 +199,68 @@ size_t strlcpy(char *dst, const char *src, size_t size)\n>>>>>  \treturn strlen(src);\n>>>>>  }\n>>>>>  \n>>>>> +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim)\n>>>>> +\t: str_(str), delim_(delim)\n>>>>> +{\n>>>>> +}\n>>>>> +\n>>>>> +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos)\n>>>>> +\t: ss_(ss), pos_(pos)\n>>>>> +{\n>>>>> +\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n>>>>> +}\n>>>>> +\n>>>>> +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++()\n>>>>> +{\n>>>>> +\tpos_ = next_;\n>>>>> +\tif (pos_ != std::string::npos) {\n>>>>> +\t\tpos_ += ss_->delim_.length();\n>>>>> +\t\tnext_ = ss_->str_.find(ss_->delim_, pos_);\n>>>>> +\t}\n>>>>> +\n>>>>> +\treturn *this;\n>>>>> +}\n>>>>> +\n>>>>> +std::string details::StringSplitter::iterator::operator*() const\n>>>>> +{\n>>>>> +\tstd::string::size_type count;\n>>>>> +\tcount = next_ != std::string::npos ? next_ - pos_ : next_;\n>>>>> +\treturn ss_->str_.substr(pos_, count);\n>>>>> +}\n>>>>> +\n>>>>> +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const\n>>>>> +{\n>>>>> +\treturn pos_ != other.pos_;\n>>>>> +}\n>>>>> +\n>>>>> +details::StringSplitter::iterator details::StringSplitter::begin() const\n>>>>> +{\n>>>>> +\treturn iterator(this, 0);\n>>>>> +}\n>>>>> +\n>>>>> +details::StringSplitter::iterator details::StringSplitter::end() const\n>>>>> +{\n>>>>> +\treturn iterator(this, std::string::npos);\n>>>>> +}\n>>>>> +\n>>>>> +/**\n>>>>> + * \\fn split(const std::string &str, const std::string &delim)\n>>>>> + * \\brief Split a string based on a delimiter\n>>>>> + * \\param[in] str The string to split\n>>>>> + * \\param[in] delim The delimiter string\n>>>>> + *\n>>>>> + * This function splits the string \\a str into substrings based on the\n>>>>> + * delimiter \\a delim. It returns an object of unspecified type that can be\n>>>>> + * used in a range-based for loop and yields the substrings in sequence.\n>>>>> + *\n>>>>> + * \\return An object that can be used in a range-based for loop to iterate over\n>>>>> + * the substrings\n>>>>> + */\n>>>>> +details::StringSplitter split(const std::string &str, const std::string &delim)\n>>>>> +{\n> \n> \t/** \\todo Try to avoid copies of str and delim */\n> \n\nI'll add this and push the series.\n\nThanks.\n\n--\nKB\n\n>>>>> +\treturn details::StringSplitter(str, delim);\n>>>>> +}\n>>>>> +\n>>>>>  } /* namespace utils */\n>>>>>  \n>>>>>  } /* namespace libcamera */\n>","headers":{"Return-Path":"<kieran.bingham@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CEACC6196C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 13 Feb 2020 17:32:06 +0100 (CET)","from [192.168.0.20]\n\t(cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 44475504;\n\tThu, 13 Feb 2020 17:32:06 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581611526;\n\tbh=6D+N52t5Ecv2wnOJdTpKA64DDpMz+Ab8qyHzxm+u5dM=;\n\th=Reply-To:Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=H4+qhi5ve9mfLaBJ9jOylz/VT/T7IuMowxeqqBUJjKeVjDl/H8+2jZChoGy8yW8Pz\n\ttwkBTtUtAdqRyRr579+z5omoEBH88LeXjztxVUw5yDGlS32V+E0TctaeUK/GbjYOwl\n\tl1gFqS1WrRSXTVfd1lZqOsAjrjI6bnyDdkoi5Y4k=","Reply-To":"kieran.bingham@ideasonboard.com","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","References":"<20200213130908.23638-1-kieran.bingham@ideasonboard.com>\n\t<20200213130908.23638-2-kieran.bingham@ideasonboard.com>\n\t<2a9b329e-da40-9b88-0b18-e34f76f454b5@ideasonboard.com>\n\t<20200213133604.GF4833@pendragon.ideasonboard.com>\n\t<4e627d36-5668-5c3a-912d-82806532d175@ideasonboard.com>\n\t<20200213162457.GB29760@pendragon.ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Openpgp":"preference=signencrypt","Autocrypt":"addr=kieran.bingham@ideasonboard.com; keydata=\n\t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\n\tWZw01QYHU/GUV/zHJSFk","Organization":"Ideas on Board","Message-ID":"<a91fb347-7f2d-496b-9111-5619f19c2b7b@ideasonboard.com>","Date":"Thu, 13 Feb 2020 16:32:02 +0000","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101\n\tThunderbird/60.9.1","MIME-Version":"1.0","In-Reply-To":"<20200213162457.GB29760@pendragon.ideasonboard.com>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: utils: Add string\n\tsplitter utility function","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 13 Feb 2020 16:32:07 -0000"}}]