[libcamera-devel] [PATCH 1/3] libcamera: utils: Add string splitter utility function
Kieran Bingham
kieran.bingham at ideasonboard.com
Thu Feb 13 17:32:02 CET 2020
Hi Laurent,
On 13/02/2020 16:24, Laurent Pinchart wrote:
> Hi Kieran,
>
> On Thu, Feb 13, 2020 at 04:10:10PM +0000, Kieran Bingham wrote:
>> On 13/02/2020 13:36, Laurent Pinchart wrote:
>>> On Thu, Feb 13, 2020 at 01:24:27PM +0000, Kieran Bingham wrote:
>>>> On 13/02/2020 13:09, Kieran Bingham wrote:
>>>>> From: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>>>>>
>>>>> 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 <laurent.pinchart at ideasonboard.com>
>>>>
>>>> This is really helpful, thanks
>>>>
>>>> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>>>>
>>>>> ---
>>>>> Documentation/Doxyfile.in | 1 +
>>>>> src/libcamera/include/utils.h | 34 +++++++++++++++++++
>>>>> src/libcamera/utils.cpp | 62 +++++++++++++++++++++++++++++++++++
>>>>> 3 files changed, 97 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
>>>>> index 1c46b04b3f7e..beeaf6d3cf48 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 e467eb21c518..080ea6614de0 100644
>>>>> --- a/src/libcamera/include/utils.h
>>>>> +++ b/src/libcamera/include/utils.h
>>>>> @@ -108,6 +108,40 @@ inline _hex hex<uint64_t>(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_;
>>>
>>> Note that I would really like if we could store references to str and
>>> delim here, but my attempt to do so resulted in problems, I believe due
>>> to the values passed to the StringSplitter constructor being
>>> temporaries. I don't know if there's a good way to solve that.
>>
>> This isn't used in any hot-path, so I'm not worried for now.
>>
>> If it comes up in the future it can be investigated then.
>>
>> Would you like to add a todo: ? or not worth it?
>
> It's always good to keep todos in mind :-) Please see below.
>
>>>>> +};
>>>>> +
>>>>> +} /* 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 4beffdab5eb6..fe027c0b009c 100644
>>>>> --- a/src/libcamera/utils.cpp
>>>>> +++ b/src/libcamera/utils.cpp
>>>>> @@ -199,6 +199,68 @@ 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 */
>
I'll add this and push the series.
Thanks.
--
KB
>>>>> + return details::StringSplitter(str, delim);
>>>>> +}
>>>>> +
>>>>> } /* namespace utils */
>>>>>
>>>>> } /* namespace libcamera */
>
--
Regards
--
Kieran
More information about the libcamera-devel
mailing list