You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2018/01/22 19:03:10 UTC

[trafficserver] branch master updated: TextView: Add suffix methods, update comments.

This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new d3056c4  TextView: Add suffix methods, update comments.
d3056c4 is described below

commit d3056c4486fc7e8c5cc4f71f4bdbe55ab04d7c75
Author: Alan M. Carroll <am...@apache.org>
AuthorDate: Fri Jan 19 17:10:00 2018 -0600

    TextView: Add suffix methods, update comments.
---
 lib/ts/TextView.h                  | 175 +++++++++++++++++++++++++++++++------
 lib/ts/unit-tests/test_TextView.cc |  37 +++++++-
 2 files changed, 186 insertions(+), 26 deletions(-)

diff --git a/lib/ts/TextView.h b/lib/ts/TextView.h
index 398ce82..79ca4be 100644
--- a/lib/ts/TextView.h
+++ b/lib/ts/TextView.h
@@ -255,24 +255,38 @@ public:
   */
   template <typename F> self_type &trim_if(F const &pred);
 
-  /** Get the initial segment of the view before @a p.
+  /** Get the prefix of size @a n.
 
-      The byte at @a p is not included. If @a p is not in the view an empty view
-      is returned.
+      If @a n is greater than the size the entire view is returned.
 
-      @return A buffer that contains all data before @a p.
+      @return A view of the prefix.
   */
-  //  self_type prefix(const char *p) const;
-
-  /// Get the prefix of size @a n.
   self_type prefix(size_t n) const;
   /// Convenience overload to avoid ambiguity for literal numbers.
   self_type prefix(int n) const;
-  /// Get the prefix delimited by the character 'c'.
+  /** Get the prefix delimited by the first occurence of the character @a c.
+
+      If @a c is not found the entire view is returned.
+      The delimiter character is not included in the returned view.
+
+      @return A view of the prefix.
+  */
   self_type prefix(char c) const;
-  /// Get the prefix delimited by any character in @a delimiters .
+  /** Get the prefix delimited by the first occurence of a character in @a delimiters.
+
+      If no such character is found the entire view is returned.
+      The delimiter character is not included in the returned view.
+
+      @return A view of the prefix.
+  */
   self_type prefix(super_type const &delimiters) const;
-  /// Get the prefix delimited by the first character for which @a pred is @c true.
+  /** Get the prefix delimited by the first character for which @a pred is @c true.
+
+      If no such character is found the entire view is returned
+      The delimiter character is not included in the returned view.
+
+      @return A view of the prefix.
+  */
   template <typename F> self_type prefix_if(F const &pred) const;
 
   /** Split a prefix from the view on the character at offset @a n.
@@ -284,8 +298,11 @@ public:
 
       This is convenient when tokenizing.
 
-      @note If @a n is larger than the size of the view no change is made and an empty buffer is
-      returned. Therefore this method can be safely called with the return value of calling @c find.
+      If @a n is larger than the size of the view no change is made and an empty buffer is
+      returned. Therefore this method is most useful when checking for the presence of the delimiter
+      is desirable, as the result of @c find methods can be passed directly to this method.
+
+      @note This method and its overloads always remove the delimiter character.
 
       @code
         void f(TextView& text) {
@@ -293,7 +310,8 @@ public:
           if (token) { // ... process token }
       @endcode
 
-      @return A buffer containing data up to but not including the byte at offset @a n.
+      @return The prefix bounded at offset @a n or an empty view if @a n is more than the view
+      size.
 
       @see take_prefix_at
   */
@@ -305,21 +323,29 @@ public:
   self_type split_prefix_at(char c);
   /// Convenience overload, split on delimiter set.
   self_type split_prefix_at(super_type const &delimiters);
-  /// Convenience overload, split on delimiter set.
-  //  self_type split_prefix_at(const char *delimiters);
   /// Convenience overload, split on predicate.
   template <typename F> self_type split_prefix_if(F const &pred);
 
-  /** Always take the prefix of the view on the character at offset @a n.
+  /** Split a prefix from the view on the character at offset @a n.
+
+      The view is split in to two parts and the byte at offset @a n is discarded. @a this retains
+      all data @b after offset @a n (equivalent to <tt>TextView::substr(n+1)</tt>). A new view
+      containing the initial bytes up to but not including the byte at offset @a n is returned,
+      (equivalent to <tt>TextView(0, n)</tt>).
+
+      This is convenient when tokenizing.
+
+      If @a n is larger than the view size then the entire view is removed and returned, leaving an
+      empty view. Therefore if @this is not empty, a non-empty view is always returned. This is desirable
+      if a non-empty return view is always wanted, regardless of whether a delimiter is present.
 
-      A prefix of @a this is removed from the view and returned. If @a n is larger than the view
-      size then the entire view is removed and returned, leaving an empty view.
+      @note This method and its overloads always remove the delimiter character.
 
       @code
       TextView text;
       while (text) {
         TextView token = text.take_prefix_at(text.find(delimiter));
-        // .. process token which will always be non-empty because text was not empty.
+        // token will always be non-empty because text was not empty.
       }
       @endcode
 
@@ -354,6 +380,24 @@ public:
   /// Get the prefix delimited by the first character for which @a pred is @c true.
   template <typename F> self_type suffix_if(F const &pred) const;
 
+  /** Split the view to get a suffix of size @a n.
+
+      The view is split in to two parts, a suffix of size @a n and a remainder which is the original
+      view less @a n + 1 characters at the end. That is, the character between the suffix and the
+      remainder is discarded. This is equivalent to <tt>TextView::suffix(this->size()-n)</tt> and
+      <tt>TextView::remove_suffix(this->size() - (n+1))</tt>.
+
+      If @a n is equal to or larger than the size of the view the entire view is removed as the
+      suffix.
+
+      @return The suffix of size @a n.
+
+      @see split_suffix_at
+  */
+  self_type split_suffix(size_t n);
+  /// Convenience overload for literal integers.
+  self_type split_suffix(int n);
+
   /** Split the view on the character at offset @a n.
 
       The view is split in to two parts and the byte at offset @a n is discarded. @a this retains
@@ -361,10 +405,14 @@ public:
       new view containing the trailing bytes after offset @a n is returned, (equivalent to
       <tt>TextView::suffix(n))</tt>).
 
-      @note If @a p does not refer to a byte in the view, an empty view is returned and @a this is
-      unchanged.
+      If @a n is larger than the size of the view no change is made and an empty buffer is
+      returned. Therefore this method is most useful when checking for the presence of the delimiter
+      is desirable, as the result of @c find methods can be passed directly to this method.
 
-      @return @a this.
+      @note This method and its overloads always remove the delimiter character.
+
+      @return The suffix bounded at offset @a n or an empty view if @a n is more than the view
+      size.
   */
   self_type split_suffix_at(size_t n);
 
@@ -377,6 +425,33 @@ public:
   /// Split the view on the last character for which @a pred is @c true.
   template <typename F> self_type split_suffix_if(F const &pred);
 
+  /** Split the view on the character at offset @a n.
+
+      The view is split in to two parts and the byte at offset @a n is discarded. @a this retains
+      all data @b before offset @a n (equivalent to <tt>TextView::prefix(this->size()-n-1)</tt>). A
+      new view containing the trailing bytes after offset @a n is returned, (equivalent to
+      <tt>TextView::suffix(n))</tt>).
+
+      If @a n is larger than the view size then the entire view is removed and returned, leaving an
+      empty view. Therefore if @this is not empty, a non-empty view is always returned. This is desirable
+      if a non-empty return view is always wanted, regardless of whether a delimiter is present.
+
+      @note This method and its overloads always remove the delimiter character.
+
+      @return The suffix bounded at offset @a n or the entire view if @a n is more than the view
+      size.
+  */
+  self_type take_suffix_at(size_t n);
+
+  /// Convenience overload for literal integers.
+  self_type take_suffix_at(int n);
+  /// Convenience overload for character.
+  self_type take_suffix_at(char c);
+  /// Convenience overload for delimiter set.
+  self_type take_suffix_at(super_type const &delimiters);
+  /// Split the view on the last character for which @a pred is @c true.
+  template <typename F> self_type take_suffix_if(F const &pred);
+
   /** Prefix check.
       @return @c true if @a this is a prefix of @a that.
   */
@@ -679,12 +754,29 @@ TextView::suffix_if(F const &pred) const
 }
 
 inline TextView
+TextView::split_suffix(size_t n)
+{
+  self_type zret;
+  n    = std::min(n, this->size());
+  zret = this->suffix(n);
+  this->remove_suffix(n + 1); // haha, saved by integer overflow!
+  return zret;
+}
+
+inline TextView
+TextView::split_suffix(int n)
+{
+  return this->split_suffix(static_cast<size_t>(n));
+}
+
+inline TextView
 TextView::split_suffix_at(size_t n)
 {
   self_type zret;
   if (n < this->size()) {
-    zret = this->suffix(n);
-    this->remove_suffix(n + 1);
+    n    = this->size() - n;
+    zret = this->suffix(n - 1);
+    this->remove_suffix(n);
   }
   return zret;
 }
@@ -698,7 +790,7 @@ TextView::split_suffix_at(int n)
 inline TextView
 TextView::split_suffix_at(char c)
 {
-  return this->split_suffix_at(this->find(c));
+  return this->split_suffix_at(this->rfind(c));
 }
 
 inline TextView
@@ -714,6 +806,39 @@ TextView::split_suffix_if(F const &pred)
   return this->split_suffix_at(this->rfind_if(pred));
 }
 
+inline TextView
+TextView::take_suffix_at(size_t n)
+{
+  self_type zret{*this};
+  *this = zret.split_prefix_at(n);
+  return zret;
+}
+
+inline TextView
+TextView::take_suffix_at(int n)
+{
+  return this->take_suffix_at(static_cast<size_t>(n));
+}
+
+inline TextView
+TextView::take_suffix_at(char c)
+{
+  return this->take_suffix_at(this->rfind(c));
+}
+
+inline TextView
+TextView::take_suffix_at(super_type const &delimiters)
+{
+  return this->take_suffix_at(this->rsearch(delimiters));
+}
+
+template <typename F>
+inline TextView
+TextView::take_suffix_if(F const &pred)
+{
+  return this->take_suffix_at(this->rfind_if(pred));
+}
+
 template <typename F>
 inline size_t
 TextView::find_if(F const &pred) const
diff --git a/lib/ts/unit-tests/test_TextView.cc b/lib/ts/unit-tests/test_TextView.cc
index c8e51c3..e8bdb02 100644
--- a/lib/ts/unit-tests/test_TextView.cc
+++ b/lib/ts/unit-tests/test_TextView.cc
@@ -56,8 +56,18 @@ TEST_CASE("TextView Trimming", "[libts][TextView]")
   REQUIRE("Evil Dave Rulz" == ts::TextView(tv).trim(" ."));
 }
 
+TEST_CASE("TextView Find", "[libts][TextView]")
+{
+  ts::TextView addr{"172.29.145.87:5050"};
+  REQUIRE(addr.find(':') == 13);
+  REQUIRE(addr.rfind(':') == 13);
+  REQUIRE(addr.find('.') == 3);
+  REQUIRE(addr.rfind('.') == 10);
+}
+
 TEST_CASE("TextView Affixes", "[libts][TextView]")
 {
+  ts::TextView s; // scratch.
   ts::TextView tv1("0123456789;01234567890");
   ts::TextView prefix{tv1.prefix(10)};
 
@@ -101,9 +111,34 @@ TEST_CASE("TextView Affixes", "[libts][TextView]")
   REQUIRE("956" == t);
 
   t = addr3;
-  ts::TextView s{t.suffix(':')};
+  ts::TextView sf{t.suffix(':')};
+  REQUIRE("5050" == sf);
+  REQUIRE(t == addr3);
+
+  t = addr3;
+  s = t.split_suffix_at(11);
+  REQUIRE("5050" == s);
+  REQUIRE("192.168.1.1" == t);
+
+  t = addr3;
+  s = t.split_suffix_at(':');
   REQUIRE("5050" == s);
+  REQUIRE("192.168.1.1" == t);
+
+  t = addr3;
+  s = t.split_suffix_at('Q');
+  REQUIRE(s.empty());
   REQUIRE(t == addr3);
+
+  t = addr3;
+  s = t.take_suffix_at(':');
+  REQUIRE("5050" == s);
+  REQUIRE("192.168.1.1" == t);
+
+  t = addr3;
+  s = t.take_suffix_at('Q');
+  REQUIRE(s == addr3);
+  REQUIRE(t.empty());
 }
 
 TEST_CASE("TextView Formatting", "[libts][TextView]")

-- 
To stop receiving notification emails like this one, please contact
amc@apache.org.