LCOV - code coverage report
Current view: top level - snapdev - reverse_cstring.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 19 19 100.0 %
Date: 2022-02-13 10:56:14 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snapdev
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : #pragma once
      20             : 
      21             : /** \file
      22             :  * \brief Iterator to search a string in reverse.
      23             :  *
      24             :  * This implementation is used to search characters starting the
      25             :  * search from the end of the string. However, the iterator looks
      26             :  * like it is used in a normal way which better matches certain
      27             :  * function which would not otherwise accept rbegin() and rend().
      28             :  */
      29             : 
      30             : // C++ lib
      31             : //
      32             : #include <iterator>
      33             : 
      34             : namespace snapdev
      35             : {
      36             : 
      37             : /** \brief Iterate a standard C string in reverse.
      38             :  *
      39             :  * This function lets you iterate a standard C string, such as "12345",
      40             :  * in reverse order. The begin() and end() functions return a reverse
      41             :  * iterator (watch out!) We do not offer a rbegin() and rend() since
      42             :  * in most cases, using the string pointers as is would have to exact
      43             :  * same effect.
      44             :  *
      45             :  * \note
      46             :  * There may already be something in STL to be able to do that without
      47             :  * a specific implementation, if so I have not found it yet. This
      48             :  * class satisfy various needs such as finding the last character
      49             :  * that do not match a set of characters:
      50             :  *
      51             :  * \code
      52             :  *   std::string match(":,/");
      53             :  *   reverse_cstring rstr(start, start + strlen(start));
      54             :  *   auto last = std::find_if_not(
      55             :  *                      rstr.begin(),
      56             :  *                      rstr.end(),
      57             :  *                      [](char const c)
      58             :  *                      {
      59             :  *                          return match.find(c) != std::string::npos;
      60             :  *                      });
      61             :  *   // last.get() == "first character found in 'match' at the end part of string"
      62             :  *   // for example, in "/,:test:,/" would return a pointer on the last ':'
      63             :  * \endcode
      64             :  *
      65             :  * \warning
      66             :  * This function uses the specified start and end pointer of a C string
      67             :  * that must be valid as long as these iterators are used.
      68             :  *
      69             :  * \tparam T  The type of string container.
      70             :  */
      71             : template <typename T>
      72             : class reverse_cstring
      73             : {
      74             : public:
      75             : 
      76             :     /** \brief Reverse C-string iterator.
      77             :      *
      78             :      * This iterator allows us to go through a C-string (i.e. a `char *`
      79             :      * pointer to a null terminated string) in reverse (i.e. from the
      80             :      * end to the start.)
      81             :      *
      82             :      * This is a very efficient iterator that allows us to avoid a full
      83             :      * copy of the string in an std::string. At this time, it is primarily
      84             :      * used to trim the end of strings.
      85             :      */
      86             :     class iterator
      87             :         : public std::iterator<std::random_access_iterator_tag, T>
      88             :     {
      89             :     public:
      90             :         // Iterator traits
      91             :         //
      92             :         typedef std::ptrdiff_t      difference_type;
      93             :         typedef T                   value_type;
      94             :         typedef T *                 pointer;
      95             :         typedef T &                 reference;
      96             : 
      97             :         // ForwardIterator
      98             :         //
      99          70 :         reference operator * ()
     100             :         {
     101          70 :             return i_[-1];
     102             :         }
     103             : 
     104             :         value_type operator * () const
     105             :         {
     106             :             return i_[-1];
     107             :         }
     108             : 
     109             :         iterator operator ++ (int)
     110             :         {
     111             :             iterator const copy(*this);
     112             :             --i_;
     113             :             return copy;
     114             :         }
     115             : 
     116          39 :         iterator & operator ++ ()
     117             :         {
     118          39 :             --i_;
     119          39 :             return *this;
     120             :         }
     121             : 
     122             :         // BidirectionalIterator
     123             :         //
     124             :         iterator operator -- (int)
     125             :         {
     126             :             iterator const copy(*this);
     127             :             ++i_;
     128             :             return copy;
     129             :         }
     130             : 
     131             :         iterator & operator -- ()
     132             :         {
     133             :             ++i_;
     134             :             return *this;
     135             :         }
     136             : 
     137             :         // RandomAccessIterator
     138             :         //
     139             :         iterator & operator += (int n)
     140             :         {
     141             :             i_ -= n;
     142             :             return *this;
     143             :         }
     144             : 
     145             :         iterator operator + (int n) const
     146             :         {
     147             :             return iterator(i_ - n);
     148             :         }
     149             : 
     150             :         friend iterator operator + (int n, iterator & rhs)
     151             :         {
     152             :             return iterator(rhs.i_ - n);
     153             :         }
     154             : 
     155             :         iterator & operator -= (int n)
     156             :         {
     157             :             i_ += n;
     158             :             return *this;
     159             :         }
     160             : 
     161             :         iterator operator - (int n) const
     162             :         {
     163             :             return iterator(i_ + n);
     164             :         }
     165             : 
     166             :         friend iterator operator - (int n, iterator & rhs)
     167             :         {
     168             :             return iterator(rhs.i_ + n);
     169             :         }
     170             : 
     171          35 :         difference_type operator - (iterator const & rhs) const
     172             :         {
     173          35 :             return rhs.i_ - i_;
     174             :         }
     175             : 
     176             :         reference operator [] (int idx)
     177             :         {
     178             :             return i_[-idx - 1];
     179             :         }
     180             : 
     181             :         value_type operator [] (int idx) const
     182             :         {
     183             :             return i_[-idx - 1];
     184             :         }
     185             : 
     186             :         bool operator < (iterator const & rhs) const
     187             :         {
     188             :             return i_ > rhs.i_;
     189             :         }
     190             : 
     191             :         bool operator > (iterator const & rhs) const
     192             :         {
     193             :             return i_ < rhs.i_;
     194             :         }
     195             : 
     196             :         bool operator <= (iterator const & rhs) const
     197             :         {
     198             :             return i_ >= rhs.i_;
     199             :         }
     200             : 
     201             :         bool operator >= (iterator const & rhs) const
     202             :         {
     203             :             return i_ <= rhs.i_;
     204             :         }
     205             : 
     206             :         // Other
     207             :         //
     208             :         bool operator == (iterator const & rhs) const
     209             :         {
     210             :             return i_ == rhs.i_;
     211             :         }
     212             : 
     213             :         bool operator != (iterator const & rhs) const
     214             :         {
     215             :             return i_ != rhs.i_;
     216             :         }
     217             : 
     218          31 :         T * get() const
     219             :         {
     220          31 :             return i_;
     221             :         }
     222             : 
     223             :      private:
     224             :          friend class reverse_cstring;
     225             : 
     226          62 :          iterator(T * it)
     227          62 :              : i_(it)
     228             :          {
     229          62 :          }
     230             : 
     231             :          T *    i_;
     232             :     };
     233             : 
     234          31 :     reverse_cstring(T * start, T * end)
     235             :         : s_(start)
     236          31 :         , e_(end)
     237             :     {
     238          31 :     }
     239             : 
     240          31 :     iterator begin() const
     241             :     {
     242          31 :         return iterator(e_);
     243             :     }
     244             : 
     245          31 :     iterator end() const
     246             :     {
     247          31 :         return iterator(s_);
     248             :     }
     249             : 
     250             :     std::size_t size() const
     251             :     {
     252             :         return e_ - s_;
     253             :     }
     254             : 
     255             : private:
     256             :     T *       s_;
     257             :     T *       e_;
     258             : };
     259             : 
     260             : 
     261             : 
     262             : /** \fn reverse_cstring::reverse_cstring(T * start, T * end)
     263             :  * \brief Initialize the reverse string with a start and end pointers.
     264             :  *
     265             :  * This constructor initializes a reverse string. You can then retrieve
     266             :  * the `begin()` and `end()` iterators to walk the string. Remember that
     267             :  * you will be walking the string going backward using what looks like
     268             :  * a usual forward iterator.
     269             :  *
     270             :  * The start is the smaller pointer. So if you have a C-string, you want
     271             :  * to create a reverse cstring with:
     272             :  *
     273             :  * \code
     274             :  *     char const * str("a C-string");
     275             :  *     reverse_cstring(str, str + strlen(str));
     276             :  * \endcode
     277             :  *
     278             :  * Of course, it is not mandatory to pass the entire string to this
     279             :  * constructor. However, we do not make a copy of the string. We use
     280             :  * your bare pointers as is. You must make sure that this string
     281             :  * remains available for the whole time you want to use the
     282             :  * reverse_cstring.
     283             :  *
     284             :  * \param[in] start  The start of the string.
     285             :  * \param[in] end  The end of the string.
     286             :  */
     287             : 
     288             : /** \fn reverse_cstring::begin() const
     289             :  * \brief Create an iterator at the beginning of the C-string.
     290             :  *
     291             :  * This function creates an iterator at the beginning of the reversed string.
     292             :  *
     293             :  * \note
     294             :  * The begin() actually uses the end pointer as passed to the constructor.
     295             :  *
     296             :  * \return A reverse_cstring iterator to the beginning of the string.
     297             :  */
     298             : 
     299             : /** \fn reverse_cstring::end() const
     300             :  * \brief Create an iterator at the end of the C-string.
     301             :  *
     302             :  * This function creates an iterator at the end of the reverse string.
     303             :  *
     304             :  * \note
     305             :  * The end() actually uses the begin pointer as passed to the constructor.
     306             :  *
     307             :  * \return A reverse_cstring iterator to the end of the string.
     308             :  */
     309             : 
     310             : /** \fn reverse_cstring::size() const
     311             :  * \brief Return the total size of the reverse C-string.
     312             :  *
     313             :  * The size of the string calculated as the end pointer minus the start
     314             :  * pointer.
     315             :  *
     316             :  * \return The size of the reverse C-string.
     317             :  */
     318             : 
     319             : /** \var reverse_cstring::s_
     320             :  * \brief The start of the string.
     321             :  *
     322             :  * This variable member points to the start of the string. This is the
     323             :  * pointer used to represent the end() iterator.
     324             :  */
     325             : 
     326             : /** \var reverse_cstring::e_
     327             :  * \brief The end of the string.
     328             :  *
     329             :  * This variable member points to the end of the string. Usually the
     330             :  * last character + 1. This is the pointer used to represent the
     331             :  * begin() iterator.
     332             :  */
     333             : 
     334             : 
     335             : 
     336             : 
     337             : 
     338             : 
     339             : 
     340             : 
     341             : 
     342             : /** \typedef reverse_cstring::iterator::difference_type
     343             :  * \brief Type used to calculate the difference between iterators.
     344             :  *
     345             :  * This type is expected to fit a pointer and to be signed.
     346             :  */
     347             : 
     348             : 
     349             : /** \typedef reverse_cstring::iterator::value_type
     350             :  * \brief Type of each item in the string.
     351             :  *
     352             :  * This type represents the type of characters in the string.
     353             :  */
     354             : 
     355             : 
     356             : /** \typedef reverse_cstring::iterator::pointer
     357             :  * \brief Direct pointer to the string characters.
     358             :  *
     359             :  * This type represents a direct pointer (not a smart pointer) to the
     360             :  * string data.
     361             :  *
     362             :  * It is expected that the person using this template will make sure
     363             :  * that the string remains available for the whole duration.
     364             :  */
     365             : 
     366             : 
     367             : /** \typedef reverse_cstring::iterator::reference
     368             :  * \brief Reference to the string characters.
     369             :  *
     370             :  * This type represents a reference to the string character type.
     371             :  */
     372             : 
     373             : /** \fn reverse_cstring::iterator::operator * ()
     374             :  * \brief Retrieve a reference to the character at the current position.
     375             :  *
     376             :  * This function returns a reference to the string character at the
     377             :  * current location. It can be used to modify the character.
     378             :  *
     379             :  * \return A reference to the current character.
     380             :  */
     381             : 
     382             : /** \fn reverse_cstring::iterator::operator * () const
     383             :  * \brief Retrieve the character at the current position.
     384             :  *
     385             :  * This function returns a copy of the character at the current position.
     386             :  *
     387             :  * \return A copy of the current character.
     388             :  */
     389             : 
     390             : /** \fn reverse_cstring::iterator::operator ++ (int)
     391             :  * \brief Run a post increment.
     392             :  *
     393             :  * This function makes a copy of the current position, then it increments
     394             :  * it. Since we are the "reverse string" the position is actually
     395             :  * decremented.
     396             :  *
     397             :  * \return A reference to this iterator.
     398             :  */
     399             : 
     400             : /** \fn reverse_cstring::iterator::operator ++ ()
     401             :  * \brief Run a pre-increment.
     402             :  *
     403             :  * This function increments the position and then returns a reference to
     404             :  * the iterator. Since we are the "reverse string" the position is actually
     405             :  * decremented.
     406             :  *
     407             :  * \return A reference to this iterator.
     408             :  */
     409             : 
     410             : /** \fn reverse_cstring::iterator::operator -- (int)
     411             :  * \brief Run a post decrement.
     412             :  *
     413             :  * This function makes a copy of the current position, then it decrements
     414             :  * it. Since we are the "reverse string" the position is actually
     415             :  * incremented.
     416             :  *
     417             :  * \return A reference to this iterator.
     418             :  */
     419             : 
     420             : /** \fn reverse_cstring::iterator::operator -- ()
     421             :  * \brief Run a pre-decrement.
     422             :  *
     423             :  * This function decrements the position and then returns a reference to
     424             :  * the iterator. Since we are the "reverse string" the position is actually
     425             :  * incremented.
     426             :  *
     427             :  * \return A reference to this iterator.
     428             :  */
     429             : 
     430             : /** \fn reverse_cstring::iterator::operator += (int n) const
     431             :  * \brief Add an offset to the position of this iterator and returns the copy.
     432             :  *
     433             :  * This function increments the position by n and then returns a
     434             :  * reference. Since we are the "reverse string" the position is
     435             :  * actually decrementing the position.
     436             :  *
     437             :  * \param[in] n  The number to add.
     438             :  *
     439             :  * \return A reference to this iterator.
     440             :  */
     441             : 
     442             : /** \fn reverse_cstring::iterator::operator + (int n) const
     443             :  * \brief Add an offset to the position of this iterator and returns the copy.
     444             :  *
     445             :  * This function increments the position by n and then returns the copy to
     446             :  * the iterator. Since we are the "reverse string" the position is actually
     447             :  * decrementing the position.
     448             :  *
     449             :  * \param[in] n  The number to add.
     450             :  *
     451             :  * \return A new iterator.
     452             :  */
     453             : 
     454             : /** \fn reverse_cstring::iterator::operator + (int n, iterator & rhs)
     455             :  * \brief Add an offset to the position of this iterator and returns the copy.
     456             :  *
     457             :  * This function increments the position by n and then returns the copy to
     458             :  * the iterator. Since we are the "reverse string" the position is actually
     459             :  * decrementing the position.
     460             :  *
     461             :  * \param[in] n  The number to add.
     462             :  * \param[in] rhs  The right hand side iterator.
     463             :  *
     464             :  * \return A new iterator.
     465             :  */
     466             : 
     467             : /** \fn reverse_cstring::iterator::operator -= (int n) const
     468             :  * \brief Subtract an offset from the position of this iterator and returns the copy.
     469             :  *
     470             :  * This function decrements the position by n and then returns a
     471             :  * reference. Since we are the "reverse string" the position is
     472             :  * actually incrementing the position.
     473             :  *
     474             :  * \param[in] n  The number to subtract.
     475             :  *
     476             :  * \return A reference to this iterator.
     477             :  */
     478             : 
     479             : /** \fn reverse_cstring::iterator::operator - (int n) const
     480             :  * \brief Subtract an offset from the position of this iterator and returns the copy.
     481             :  *
     482             :  * This function decrements the position by n and then returns the copy to
     483             :  * the iterator. Since we are the "reverse string" the position is actually
     484             :  * incrementing the position.
     485             :  *
     486             :  * \param[in] n  The number to subtract.
     487             :  *
     488             :  * \return A new iterator.
     489             :  */
     490             : 
     491             : /** \fn reverse_cstring::iterator::operator - (int n, iterator & rhs)
     492             :  * \brief Subtract an offset from the position of this iterator and returns the copy.
     493             :  *
     494             :  * This function decrements the position by n and then returns the copy to
     495             :  * the iterator. Since we are the "reverse string" the position is actually
     496             :  * incrementing the position.
     497             :  *
     498             :  * \param[in] n  The number to add.
     499             :  * \param[in] rhs  The right hand side.
     500             :  *
     501             :  * \return A new iterator.
     502             :  */
     503             : 
     504             : /** \fn reverse_cstring::iterator::operator - (iterator const & rhs) const
     505             :  * \brief Compare the difference between two iterators.
     506             :  *
     507             :  * This function calculates the difference between two iterators.
     508             :  *
     509             :  * \param[in] rhs  The right hand side.
     510             :  *
     511             :  * \return A new iterator.
     512             :  */
     513             : 
     514             : /** \fn reverse_cstring::iterator::operator [] (int idx)
     515             :  * \brief Get a reference to the character at the current position.
     516             :  *
     517             :  * This function gets a reference to the character at the current position.
     518             :  * It can be used to read or write the character.
     519             :  *
     520             :  * \param[in] idx  The index of the character to retrieve.
     521             :  *
     522             :  * \return A reference to the index character.
     523             :  */
     524             : 
     525             : /** \fn reverse_cstring::iterator::operator [] (int idx) const
     526             :  * \brief Get a copy of the character at the current position.
     527             :  *
     528             :  * This function returns a copy of the character at the current position.
     529             :  *
     530             :  * \param[in] idx  The index of the character to retrieve.
     531             :  *
     532             :  * \return A of the character at the \p idx position.
     533             :  */
     534             : 
     535             : /** \fn reverse_cstring::iterator::operator < (iterator const & rhs) const
     536             :  * \brief Compare two iterators.
     537             :  *
     538             :  * This function returns true if the left hand side iterator is at an
     539             :  * earlier position than the right hand side.
     540             :  *
     541             :  * \param[in] rhs  The right hand side.
     542             :  *
     543             :  * \return true if this is less than right hand side.
     544             :  */
     545             : 
     546             : /** \fn reverse_cstring::iterator::operator > (iterator const & rhs) const
     547             :  * \brief Compare two iterators.
     548             :  *
     549             :  * This function returns true if the left hand side iterator is at a
     550             :  * later position than the right hand side.
     551             :  *
     552             :  * \param[in] rhs  The right hand side.
     553             :  *
     554             :  * \return true if this is more than right hand side.
     555             :  */
     556             : 
     557             : /** \fn reverse_cstring::iterator::operator <= (iterator const & rhs) const
     558             :  * \brief Compare two iterators.
     559             :  *
     560             :  * This function returns true if the left hand side iterator is at an
     561             :  * earlier or equal position than the right hand side.
     562             :  *
     563             :  * \param[in] rhs  The right hand side.
     564             :  *
     565             :  * \return true if this is less or equal than right hand side.
     566             :  */
     567             : 
     568             : /** \fn reverse_cstring::iterator::operator >= (iterator const & rhs) const
     569             :  * \brief Compare two iterators.
     570             :  *
     571             :  * This function returns true if the left hand side iterator is at a
     572             :  * later or equal position than the right hand side.
     573             :  *
     574             :  * \param[in] rhs  The right hand side.
     575             :  *
     576             :  * \return true if this is larger or equal than right hand side.
     577             :  */
     578             : 
     579             : /** \fn reverse_cstring::iterator::operator == (iterator const & rhs) const
     580             :  * \brief Compare two iterators.
     581             :  *
     582             :  * This function returns true if the left hand side iterator is at
     583             :  * the same position than the right hand side.
     584             :  *
     585             :  * \param[in] rhs  The right hand side.
     586             :  *
     587             :  * \return true if this is equal the right hand side.
     588             :  */
     589             : 
     590             : /** \fn reverse_cstring::iterator::operator != (iterator const & rhs) const
     591             :  * \brief Compare two iterators.
     592             :  *
     593             :  * This function returns true if the left hand side iterator is not at
     594             :  * the same position than the right hand side.
     595             :  *
     596             :  * \param[in] rhs  The right hand side.
     597             :  *
     598             :  * \return true if this is not equal the right hand side.
     599             :  */
     600             : 
     601             : /** \fn reverse_cstring::iterator::get() const
     602             :  * \brief Get the current position, which is a pointer to a character.
     603             :  *
     604             :  * This function returns the current iterator position. This is a
     605             :  * pointer right after a character in the string. If you want to 
     606             :  * retrieve the character, may sure to use `pointer[-1]`.
     607             :  *
     608             :  * \return The pointer to the string at the current iterator location.
     609             :  */
     610             : 
     611             : /** \fn reverse_cstring::iterator::iterator(T * it)
     612             :  * \brief Initialize the iterator.
     613             :  *
     614             :  * This function initialize the iterator with the specified pointer.
     615             :  *
     616             :  * \param[in] it  The string pointer the iterator likes to use.
     617             :  */
     618             : 
     619             : /** \var reverse_cstring::iterator::i_
     620             :  * \brief The position in the iterator.
     621             :  *
     622             :  * This variable member is a pointer to the character in the string
     623             :  * this iterator points to. The character is actually at `i_[-1]`
     624             :  * since we are in reverse.
     625             :  */
     626             : 
     627             : 
     628             : 
     629             : 
     630             : 
     631             : } // namespace snapdev
     632             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13