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

zwoop pushed a commit to branch 7.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit d2b760c3c0918175dbf0b3511d35b9d92a95a5d9
Author: Jason Kenny <dragon...@live.com>
AuthorDate: Wed Aug 30 13:38:21 2017 -0500

    Add basic_string_view
    
    add some unit testing based on Catch
---
 lib/ts/Makefile.am                |   16 +-
 lib/ts/string_view.h              | 1216 +++++++++++++++++++++++++++++++++++++
 lib/ts/unit-tests/main.cpp        |   25 +
 lib/ts/unit-tests/string_view.cpp |  523 ++++++++++++++++
 tests/{ => include}/catch.hpp     |    0
 5 files changed, 1777 insertions(+), 3 deletions(-)

diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am
index 41ed45d..2e09e15 100644
--- a/lib/ts/Makefile.am
+++ b/lib/ts/Makefile.am
@@ -23,16 +23,16 @@ library_includedir=$(includedir)/ts
 library_include_HEADERS = apidefs.h
 
 noinst_PROGRAMS = mkdfa CompileParseRules
-check_PROGRAMS = test_tsutil test_arena test_atomic test_freelist 
test_geometry test_List test_Map test_Vec test_X509HostnameValidator 
test_MemView
+check_PROGRAMS = test_tsutil test_arena test_atomic test_freelist 
test_geometry test_List test_Map test_Vec test_X509HostnameValidator 
test_MemView test_tslib
 
 TESTS_ENVIRONMENT = LSAN_OPTIONS=suppressions=suppression.txt
 
 TESTS = $(check_PROGRAMS)
 
-AM_CPPFLAGS += -I$(abs_top_srcdir)/lib
-
 lib_LTLIBRARIES = libtsutil.la
 
+AM_CPPFLAGS += -I$(abs_top_srcdir)/lib 
+
 libtsutil_la_LDFLAGS = -no-undefined -version-info @TS_LIBTOOL_VERSION@
 libtsutil_la_LIBADD = \
   @HWLOC_LIBS@ \
@@ -190,6 +190,7 @@ libtsutil_la_SOURCES = \
   lockfile.cc \
   signals.cc \
   signals.h \
+  string_view.h \
   X509HostnameValidator.cc \
   X509HostnameValidator.h
 
@@ -239,6 +240,15 @@ test_tsutil_SOURCES = \
        test_Regex.cc \
        tests.cc
 
+test_tslib_CPPFLAGS = $(AM_CPPFLAGS)\
+       -I$(abs_top_srcdir)/tests/include
+
+# add you catch based test file here for tslib
+test_tslib_LDADD = libtsutil.la
+test_tslib_SOURCES = \
+       unit-tests/main.cpp \
+       unit-tests/string_view.cpp
+
 CompileParseRules_SOURCES = CompileParseRules.cc
 
 clean-local:
diff --git a/lib/ts/string_view.h b/lib/ts/string_view.h
new file mode 100644
index 0000000..ff902bf
--- /dev/null
+++ b/lib/ts/string_view.h
@@ -0,0 +1,1216 @@
+/** @file
+
+  This is an implemetation of the std::string_view class for us to use
+  with c++11 and 14 until we can use the c++ 17 standard. This has a few 
overloads
+  to deal with some ats objects to help with migration work
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#pragma once
+
+#include <cstddef>
+#include <type_traits>
+#include <iterator>
+#include <stdexcept>
+#include <algorithm>
+#include <utility>
+#include <string>
+#include <ostream>
+#include <ts/ink_memory.h>
+
+#if __cplusplus < 201402
+#define CONSTEXPR14 inline
+#else
+#define CONSTEXPR14 constexpr
+#endif
+
+namespace ts
+{
+// forward declare class for iterator friend relationship
+template <typename _Type, typename _CharTraits = std::char_traits<_Type>> 
class basic_string_view;
+
+/////////////////////
+// the iterator
+
+namespace _private_
+{
+  template <typename _CharTraits> class string_view_iterator
+  { // iterator for character buffer wrapper
+  public:
+    using iterator_category = std::random_access_iterator_tag;
+    using value_type        = typename _CharTraits::char_type;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = const value_type *;
+    using reference         = const value_type &;
+
+    constexpr string_view_iterator() noexcept = default;
+
+  private:
+    friend basic_string_view<value_type, _CharTraits>;
+
+    constexpr explicit string_view_iterator(const pointer rhs) noexcept : 
m_ptr(rhs) {}
+
+  public:
+    constexpr reference operator*() const noexcept
+    { // return designated object
+      return *m_ptr;
+    }
+
+    constexpr pointer operator->() const noexcept
+    { // return pointer to class object
+      return m_ptr;
+    }
+
+    CONSTEXPR14 string_view_iterator &operator++() noexcept
+    { // preincrement
+      ++m_ptr;
+      return *this;
+    }
+
+    CONSTEXPR14 string_view_iterator operator++(int)noexcept
+    { // postincrement
+      string_view_iterator tmp{*this};
+      ++*this;
+      return tmp;
+    }
+
+    CONSTEXPR14 string_view_iterator &operator--() noexcept
+    { // predecrement
+      --m_ptr;
+      return *this;
+    }
+
+    CONSTEXPR14 string_view_iterator operator--(int)noexcept
+    { // postdecrement
+      string_view_iterator tmp{*this};
+      --*this;
+      return tmp;
+    }
+
+    CONSTEXPR14 string_view_iterator &
+    operator+=(const difference_type offset) noexcept
+    { // increment by integer
+      m_ptr += offset;
+      return *this;
+    }
+
+    CONSTEXPR14 string_view_iterator
+    operator+(const difference_type offset) const noexcept
+    { // return this + integer
+      string_view_iterator tmp{*this};
+      tmp += offset;
+      return tmp;
+    }
+
+    CONSTEXPR14 string_view_iterator &
+    operator-=(const difference_type offset) noexcept
+    { // decrement by integer
+      m_ptr -= offset;
+      return *this;
+    }
+
+    CONSTEXPR14 string_view_iterator
+    operator-(const difference_type offset) const noexcept
+    { // return this - integer
+      string_view_iterator tmp{*this};
+      tmp -= offset;
+      return tmp;
+    }
+
+    constexpr difference_type
+    operator-(const string_view_iterator &rhs) const noexcept
+    { // return difference of iterators
+      return m_ptr - rhs.m_ptr;
+    }
+
+    constexpr reference operator[](const difference_type offset) const noexcept
+    { // subscript
+      return *(*this) + offset;
+    }
+
+    constexpr bool
+    operator==(const string_view_iterator &rhs) const noexcept
+    { // test for iterator equality
+      return m_ptr == rhs.m_ptr;
+    }
+
+    constexpr bool
+    operator!=(const string_view_iterator &rhs) const noexcept
+    { // test for iterator inequality
+      return !(*this == rhs);
+    }
+
+    constexpr bool
+    operator<(const string_view_iterator &rhs) const noexcept
+    { // test if this < rhs
+      return m_ptr < rhs.m_ptr;
+    }
+
+    constexpr bool
+    operator>(const string_view_iterator &rhs) const noexcept
+    { // test if this > rhs
+      return rhs < *this;
+    }
+
+    constexpr bool
+    operator<=(const string_view_iterator &rhs) const noexcept
+    { // test if this <= rhs
+      return !(rhs < *this);
+    }
+
+    constexpr bool
+    operator>=(const string_view_iterator &rhs) const noexcept
+    { // test if this >= rhs
+      return !(*this < rhs);
+    }
+
+  private:
+    pointer m_ptr = nullptr;
+  };
+}
+
+template <typename _CharTraits>
+CONSTEXPR14 _private_::string_view_iterator<_CharTraits>
+operator+(const typename 
_private_::string_view_iterator<_CharTraits>::difference_type offset,
+          _private_::string_view_iterator<_CharTraits> rhs) noexcept
+{ // return integer + _Right
+  rhs += offset;
+  return rhs;
+}
+
+/// the main class
+
+template <typename _Type, typename _CharTraits> class basic_string_view
+{ // wrapper for any kind of contiguous character buffer
+public:
+  // some standard junk to say hey.. you are messing up something important.. 
stop it
+  static_assert(std::is_same<_Type, typename _CharTraits::char_type>::value,
+                "Bad char_traits for basic_string_view; "
+                "N4606 21.4.2 [string.view.template] \"the type 
traits::char_type shall name the same type as charT.\"");
+
+  using traits_type            = _CharTraits;
+  using value_type             = _Type;
+  using pointer                = _Type *;
+  using const_pointer          = const _Type *;
+  using reference              = _Type &;
+  using const_reference        = const _Type &;
+  using const_iterator         = _private_::string_view_iterator<_CharTraits>;
+  using iterator               = const_iterator;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using reverse_iterator       = const_reverse_iterator;
+  using size_type              = std::size_t;
+  using difference_type        = ptrdiff_t;
+  using self_type              = basic_string_view<value_type, traits_type>;
+  static constexpr size_type npos{~0ULL};
+
+  constexpr basic_string_view() noexcept {}
+
+  constexpr basic_string_view(basic_string_view const &) noexcept = default;
+  CONSTEXPR14 basic_string_view &operator=(basic_string_view const &) noexcept 
= default;
+
+  /* implicit */
+  // Note that with constexpr enabled and modern g++ and clang ( icpc)
+  // there is a optmization to strlen and traits_type::length for
+  // literals in which the compiler will replace it with the size
+  // at compile time. With c++ 17 the constexpr guarrentee
+  // that the literal length is optimized out
+  constexpr basic_string_view(const_pointer rhs) noexcept : m_data(rhs), 
m_size(traits_type::length(rhs)) {}
+
+  constexpr basic_string_view(const_pointer rhs, const size_type length) 
noexcept // strengthened
+    : m_data(rhs), m_size(length)
+  {
+  }
+
+  // std::string constructor
+  constexpr basic_string_view(std::string const &rhs) noexcept : 
m_data(rhs.data()), m_size(rhs.size()) {}
+
+  // ats_scoped_str constructor
+  constexpr basic_string_view(ats_scoped_str const &rhs) noexcept : 
m_data(rhs.get()), m_size(traits_type::length(rhs.get())) {}
+
+  // For iterator on string_view we don't need to deal with const and 
non-const as different types
+  // they are all const iterators as the string values are immutable
+  // keep in mind that the string view is mutable in what it points to
+
+  constexpr const_iterator
+  begin() const noexcept
+  { // get the beginning of the range
+    return const_iterator(m_data);
+  }
+
+  constexpr const_iterator
+  end() const noexcept
+  { // get the end of the range
+    return const_iterator(m_data + m_size);
+  }
+
+  constexpr const_iterator
+  cbegin() const noexcept
+  { // get the beginning of the range
+    return begin();
+  }
+
+  constexpr const_iterator
+  cend() const noexcept
+  { // get the end of the range
+    return end();
+  }
+
+  constexpr const_reverse_iterator
+  rbegin() const noexcept
+  { // get the beginning of the reversed range
+    return const_reverse_iterator{end()};
+  }
+
+  constexpr const_reverse_iterator
+  rend() const noexcept
+  { // get the end of the reversed range
+    return const_reverse_iterator{begin()};
+  }
+
+  constexpr const_reverse_iterator
+  crbegin() const noexcept
+  { // get the beginning of the reversed range
+    return rbegin();
+  }
+
+  constexpr const_reverse_iterator
+  crend() const noexcept
+  { // get the end of the reversed range
+    return rend();
+  }
+
+  constexpr size_type
+  size() const noexcept
+  { // get the size of this basic_string_view
+    return m_size;
+  }
+
+  constexpr size_type
+  length() const noexcept
+  { // get the size of this basic_string_view
+    return m_size;
+  }
+
+  constexpr bool
+  empty() const noexcept
+  { // check whether this basic_string_view is empty
+    return m_size == 0;
+  }
+
+  constexpr const_pointer
+  data() const noexcept
+  { // get the base pointer of this basic_string_view
+    // std says data does not have to have a NULL terminator
+    return m_data;
+  }
+
+  constexpr size_type
+  max_size() const noexcept
+  {
+    // max size of byte we could make - 1 for npos divided my size of char
+    // to return the number of "character sized bytes" we can allocate
+    return (UINTPTR_MAX - 1) / sizeof(_Type);
+  }
+
+  CONSTEXPR14 const_reference operator[](const size_type index) const // 
strengthened
+  {
+// get character at offset
+// assume index is in range
+#ifdef _DEBUG
+    check_index_bound(index); // for debug
+#endif
+    return m_data[index];
+  }
+
+  CONSTEXPR14 const_reference
+  at(const size_type index) const
+  {                           // get the character at offset or throw if that 
is out of range
+    check_index_bound(index); // add bound check
+    return m_data[index];
+  }
+
+  constexpr const_reference front() const noexcept // strengthened
+  {
+    // std is undefined for empty string
+    return m_data[0];
+  }
+
+  constexpr const_reference
+  back() const
+  {
+    // std is undefined for empty string
+    return m_data[m_size - 1];
+  }
+
+  CONSTEXPR14 void remove_prefix(const size_type length) noexcept // 
strengthened
+  {                                                               // chop off 
the beginning
+    auto tmp = std::min(length, m_size);
+    m_data += tmp;
+    m_size -= tmp;
+  }
+
+  CONSTEXPR14 void remove_suffix(const size_type length) noexcept // 
strengthened
+  {                                                               // chop off 
the end
+    m_size -= std::min(length, m_size);
+  }
+
+  CONSTEXPR14 void
+  swap(basic_string_view &rhs) noexcept
+  {                                   // swap contents
+    const basic_string_view tmp{rhs}; // note: std::swap is not constexpr
+    rhs   = *this;
+    *this = tmp;
+  }
+
+  // possibly unsafe.. look for linux equal to a windows copy_s version if it 
exists
+  CONSTEXPR14 size_type
+  copy(_Type *const rhs, size_type length, const size_type offset = 0) const
+  {
+    check_offset_bound(offset);
+    length = std::min(length, m_size - offset);
+    traits_type::copy(rhs, m_data + offset, length);
+    return length;
+  }
+
+  CONSTEXPR14 basic_string_view
+  substr(const size_type offset = 0, size_type length = npos) const
+  {
+    check_offset_bound(offset);
+    length = std::min(length, m_size - offset);
+    return basic_string_view(m_data + offset, length);
+  }
+
+  // this is not a std function.. but is needed in some form for ==, != 
operators
+  // I could make this _equal to say don't call it.. but I won't
+  constexpr bool
+  _equal(const basic_string_view rhs) const noexcept
+  {
+    return m_size == rhs.m_size && traits_type::compare(m_data, rhs.m_data, 
m_size) == 0;
+  }
+
+  constexpr bool
+  _equal(std::string const &rhs) const noexcept
+  {
+    return m_size == rhs.size() && traits_type::compare(m_data, rhs.data(), 
m_size) == 0;
+  }
+
+  CONSTEXPR14 bool
+  _equal(value_type const *const rhs) const noexcept
+  {
+    self_type tmp(rhs);
+    return m_size == tmp.size() && traits_type::compare(m_data, tmp.data(), 
m_size) == 0;
+  }
+
+  //////////////////////////////////////////////
+  // Compare
+
+  CONSTEXPR14 int
+  compare(const basic_string_view rhs) const noexcept
+  {
+    const int result = traits_type::compare(m_data, rhs.m_data, 
std::min(m_size, rhs.size()));
+
+    if (result != 0) {
+      return result;
+    }
+
+    if (m_size < rhs.m_size) {
+      return -1;
+    }
+
+    if (m_size > rhs.m_size) {
+      return 1;
+    }
+
+    return 0;
+  }
+
+  constexpr int
+  compare(const size_type offset, const size_type length, const 
basic_string_view rhs) const
+  {
+    return substr(offset, length).compare(rhs);
+  }
+
+  constexpr int
+  compare(const size_type offset, const size_type length, const 
basic_string_view rhs, const size_type rhsoffsetset,
+          const size_type rhs_length) const
+  {
+    return substr(offset, length).compare(rhs.substr(rhsoffsetset, 
rhs_length));
+  }
+
+  constexpr int
+  compare(const _Type *const rhs) const
+  {
+    return compare(basic_string_view(rhs));
+  }
+
+  constexpr int
+  compare(const size_type offset, const size_type length, const _Type *const 
rhs) const
+  {
+    return substr(offset, length).compare(basic_string_view(rhs));
+  }
+
+  constexpr int
+  compare(const size_type offset, const size_type length, const _Type *const 
rhs, const size_type rhs_length) const
+  {
+    return substr(offset, length).compare(basic_string_view(rhs, rhs_length));
+  }
+
+  //////////////////////
+  // find -- string
+
+  CONSTEXPR14 size_type find(const _Type *const rhs, const size_type offset, 
const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    // do we have space to find the string given the offset
+    if (rhs_length > m_size || offset > m_size - rhs_length) {
+      // no match found
+      return npos;
+    }
+
+    if (rhs_length == 0) { // empty string always matches to offset
+      return offset;
+    }
+
+    // this is the point in which we can stop checking
+    const auto end_ptr = m_data + (m_size - rhs_length) + 1;
+    // start looking
+    for (auto curr = m_data + offset; curr < end_ptr; ++curr) {
+      // try to first char
+      curr = traits_type::find(curr, end_ptr - curr, *rhs);
+      if (!curr) { // didn't find first character; report failure
+        return npos;
+      }
+      // given we found it, see if it compares ( matches)
+      if (traits_type::compare(curr, rhs, rhs_length) == 0) { // found match
+        return curr - m_data;
+      }
+      // else try again till we run out of string space
+    }
+    // no match found
+    return npos;
+  }
+
+  constexpr size_type
+  find(const basic_string_view rhs, const size_type offset = 0) const noexcept
+  {
+    return find(rhs.m_data, offset, rhs.size());
+  }
+
+  constexpr size_type find(const _Type *const rhs, const size_type offset = 0) 
const noexcept // strengthened
+  {
+    return find(rhs, offset, traits_type::length(rhs));
+  }
+
+  // character form
+
+  CONSTEXPR14 size_type
+  find(const _Type c, const size_type offset = 0) const noexcept
+  {
+    if (offset < m_size) {
+      const auto found_at = traits_type::find(m_data + offset, m_size - 
offset, c);
+      if (found_at) {
+        return found_at - m_data;
+      }
+    }
+    // no match found
+    return npos;
+  }
+
+  /////////////////////////////
+  // rfind -- string
+
+  CONSTEXPR14 size_type rfind(const _Type *const rhs, const size_type offset, 
const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    if (rhs_length == 0) {
+      return std::min(offset, m_size); // empty string always matches
+    }
+
+    if (rhs_length <= m_size) {
+      // room for match, look for it
+      for (auto curr = m_data + std::min(offset, m_size - rhs_length);; 
--curr) {
+        // do we have a match
+        if (traits_type::eq(*curr, *rhs) && traits_type::compare(curr, rhs, 
rhs_length) == 0) {
+          // found a match
+          return curr - m_data;
+        }
+
+        // at beginning, no more chance for match?
+        if (curr == m_data) {
+          break;
+        }
+      }
+    }
+
+    return npos;
+  }
+
+  constexpr size_type rfind(const _Type *const rhs, const size_type offset = 
npos) const noexcept // strengthened
+  {
+    return rfind(rhs, offset, traits_type::length(rhs));
+  }
+
+  constexpr size_type
+  rfind(const basic_string_view rhs, const size_type offset = npos) const 
noexcept
+  {
+    return rfind(rhs.m_data, offset, rhs.m_size);
+  }
+
+  // character version
+
+  CONSTEXPR14 size_type
+  rfind(const _Type c, const size_type offset = npos) const noexcept
+  {
+    if (m_data != 0) {
+      for (auto curr = m_data + std::min(offset, m_size - 1);; --curr) {
+        if (traits_type::eq(*curr, c)) {
+          // found a match
+          return curr - m_data;
+        }
+
+        if (curr == m_data) {
+          // at beginning, no more chances for match
+          break;
+        }
+      }
+    }
+    // no match found
+    return npos;
+  }
+
+  //////////////////////////////////////
+  // find_first_of
+
+  CONSTEXPR14 size_type find_first_of(const _Type *const rhs, const size_type 
offset, const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    if (rhs_length != 0 && offset < m_size) {
+      const auto _End = m_data + m_size;
+      for (auto curr = m_data + offset; curr < _End; ++curr) {
+        if (traits_type::find(rhs, rhs_length, *curr)) {
+          // found a match
+          return curr - m_data;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  constexpr size_type find_first_of(const _Type *const rhs, const size_type 
offset = 0) const noexcept // strengthened
+  {
+    return find_first_of(rhs, offset, traits_type::length(rhs));
+  }
+
+  constexpr size_type
+  find_first_of(const basic_string_view rhs, const size_type offset = 0) const 
noexcept
+  {
+    return find_first_of(rhs.m_data, offset, rhs.m_size);
+  }
+
+  // character version
+
+  CONSTEXPR14 size_type
+  find_first_of(const _Type c, const size_type offset = 0) const noexcept
+  {
+    if (offset < m_size) {
+      const auto found_at = traits_type::find(m_data + offset, m_size - 
offset, c);
+      if (found_at) {
+        return found_at - m_data;
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  //////////////////////////////
+  // find_last_of
+
+  CONSTEXPR14 size_type find_last_of(const _Type *const rhs, const size_type 
offset, const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    if (rhs_length != 0 && m_size != 0) {
+      for (auto curr = m_data + std::min(offset, m_size - 1);; --curr) {
+        if (traits_type::find(rhs, rhs_length, *curr)) {
+          // found a match
+          return curr - m_data;
+        }
+
+        if (curr == m_data) {
+          // at beginning, no more chances for match
+          break;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  constexpr size_type find_last_of(const _Type *const rhs, const size_type 
offset = npos) const noexcept // strengthened
+  {
+    return find_last_of(rhs, offset, traits_type::length(rhs));
+  }
+
+  constexpr size_type
+  find_last_of(const basic_string_view rhs, const size_type offset = npos) 
const noexcept
+  {
+    return find_last_of(rhs.m_data, offset, rhs.m_size);
+  }
+
+  // character version
+
+  CONSTEXPR14 size_type
+  find_last_of(const _Type c, const size_type offset = npos) const noexcept
+  {
+    if (m_size != 0) { // room for match, look for it
+      for (auto curr = m_data + std::min(offset, m_size - 1);; --curr) {
+        if (traits_type::eq(*curr, c)) {
+          // found a match
+          return curr - m_data;
+        }
+
+        if (curr == m_data) {
+          // at beginning, no more chances for match
+          break;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  //////////////////////////////
+  // find_first_not_of
+
+  CONSTEXPR14 size_type find_first_not_of(const _Type *const rhs, const 
size_type offset, const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    if (offset < m_size) {
+      const auto _End = m_data + m_size;
+      for (auto curr = m_data + offset; curr < _End; ++curr) {
+        if (!traits_type::find(rhs, rhs_length, *curr)) {
+          // found a match
+          return curr - m_data;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  constexpr size_type find_first_not_of(const _Type *const rhs, const 
size_type offset = 0) const noexcept // strengthened
+  {
+    return find_first_not_of(rhs, offset, traits_type::length(rhs));
+  }
+
+  constexpr size_type
+  find_first_not_of(const basic_string_view rhs, const size_type offset = 0) 
const noexcept
+  {
+    return find_first_not_of(rhs.m_data, offset, rhs.m_size);
+  }
+
+  // character version
+
+  CONSTEXPR14 size_type
+  find_first_not_of(const _Type c, const size_type offset = 0) const noexcept
+  {
+    if (offset < m_size) {
+      const auto _End = m_data + m_size;
+      for (auto curr = m_data + offset; curr < _End; ++curr) {
+        if (!traits_type::eq(*curr, c)) {
+          // found a match
+          return curr - m_data;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  //////////////////////////////
+  // find_last_not_of
+
+  CONSTEXPR14 size_type find_last_not_of(const _Type *const rhs, const 
size_type offset, const size_type rhs_length) const
+    noexcept // strengthened
+  {
+    if (m_size != 0) {
+      for (auto curr = m_data + std::min(offset, m_size - 1);; --curr) {
+        if (!traits_type::find(rhs, rhs_length, *curr)) {
+          // found a match
+          return curr - m_data;
+        }
+
+        if (curr == m_data) {
+          // at beginning, no more chances for match
+          break;
+        }
+      }
+    }
+
+    // no match found
+    return npos;
+  }
+
+  constexpr size_type find_last_not_of(const _Type *const rhs, const size_type 
offset = npos) const noexcept // strengthened
+  {
+    return find_last_not_of(rhs, offset, traits_type::length(rhs));
+  }
+
+  constexpr size_type
+  find_last_not_of(const basic_string_view rhs, const size_type offset = npos) 
const noexcept
+  {
+    return find_last_not_of(rhs.m_data, offset, rhs.m_size);
+  }
+
+  // character version
+
+  CONSTEXPR14 size_type
+  find_last_not_of(const _Type c, const size_type offset = npos) const noexcept
+  {
+    if (m_size != 0) { // room for match, look for it
+      for (auto curr = m_data + std::min(offset, m_size - 1);; --curr) {
+        if (!traits_type::eq(*curr, c)) {
+          // found a match
+          return curr - m_data;
+        }
+
+        if (curr == m_data) {
+          // at beginning, no more chances for match
+          break;
+        }
+      }
+    }
+    // no match found
+    return npos;
+  }
+
+private:
+  CONSTEXPR14 void
+  check_offset_bound(size_type offset) const
+  {
+    // check that the offset is not greater than the size
+    if (offset > m_size) {
+      throw std::out_of_range("invalid string_view position");
+    }
+  }
+
+  CONSTEXPR14 void
+  check_index_bound(size_type index) const
+  {
+    // check that the offset is not greater than the size
+    if (index >= m_size) {
+      throw std::out_of_range("invalid string_view position");
+    }
+  }
+
+private:
+  const_pointer m_data = nullptr;
+  size_type m_size     = 0;
+};
+
+// operators for basic_string_view<>
+// this has a c++11 compat version and a c++14/17 version that uses 
enable_if_t and some newer stuff to reduce the code
+// Ideally we use the old version for c++11 compilers, newer version for c++14 
compiler. For c++17 we should not need this file
+// as we can use the builtin version then
+#if __cplusplus < 201402
+
+////////////////////////////
+// ==
+template <typename _Type, typename _Traits>
+inline bool
+operator==(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs._equal(rhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator==(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs._equal(lhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator==(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return lhs._equal(rhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator==(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) == 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator==(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) == 0;
+}
+////////////////////////////
+// !=
+template <typename _Type, typename _Traits>
+inline bool
+operator!=(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return !lhs._equal(rhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator!=(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return !rhs._equal(lhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator!=(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return !lhs._equal(rhs);
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator!=(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) != 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator!=(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) != 0;
+}
+////////////////////////////
+// <
+template <typename _Type, typename _Traits>
+inline bool
+operator<(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) < 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) < 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return lhs.compare(rhs) < 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) < 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) < 0;
+}
+////////////////////////////
+// >
+
+template <typename _Type, typename _Traits>
+inline bool
+operator>(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) > 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) > 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return lhs.compare(rhs) > 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) > 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) < 0;
+}
+
+////////////////////////////
+// <=
+template <typename _Type, typename _Traits>
+inline bool
+operator<=(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) <= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<=(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) <= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<=(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return lhs.compare(rhs) <= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<=(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) <= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator<=(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) <= 0;
+}
+////////////////////////////
+// >=
+template <typename _Type, typename _Traits>
+inline bool
+operator>=(basic_string_view<_Type, _Traits> const lhs, 
basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) >= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>=(std::string const &lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return lhs.compare(rhs) >= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>=(basic_string_view<_Type, _Traits> const lhs, std::string const &rhs)
+{
+  return lhs.compare(rhs) >= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>=(basic_string_view<_Type, _Traits> const lhs, char const *const rhs)
+{
+  return lhs.compare(rhs) >= 0;
+}
+template <typename _Type, typename _Traits>
+inline bool
+operator>=(char const *const lhs, basic_string_view<_Type, _Traits> const rhs)
+{
+  return rhs.compare(lhs) >= 0;
+}
+
+#else
+/////////////////////////////////////////////////
+// this form is more functional than the above case which only deals with 
char* and std::string
+// this form deal with convertable type correctly as is less code :)
+
+////////////////////////////
+// ==
+template <typename _Type, typename _Traits>
+constexpr bool
+operator==(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return lhs._equal(rhs);
+}
+
+// user conversion for stuff like std::string or char*, literals
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator==(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept(basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs))))
+{
+  return rhs._equal(std::forward<_OtherType>(lhs));
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator==(const basic_string_view<_Type, _Traits> lhs,
+           _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return lhs._equal(std::forward<_OtherType>(rhs));
+}
+
+///////////////////////////////
+// !=
+template <typename _Type, typename _Traits>
+constexpr bool
+operator!=(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return !lhs._equal(rhs);
+}
+
+// user conversion for stuff like std::string or char*, literals
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator!=(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept((basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs)))))
+{
+  return !rhs._equal(std::forward<_OtherType>(lhs));
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator!=(const basic_string_view<_Type, _Traits> lhs,
+           _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return !lhs._equal(std::forward<_OtherType>(rhs));
+}
+
+///////////////////////////////
+// <
+template <typename _Type, typename _Traits>
+constexpr bool
+operator<(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return lhs.compare(rhs) < 0;
+}
+
+// user conversion for stuff like std::string or char*, literals
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator<(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept((basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs)))))
+{ // less-than compare objects convertible to basic_string_view instances
+  return basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(lhs)).compare(rhs) < 0;
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator<(const basic_string_view<_Type, _Traits> lhs,
+          _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return lhs.compare(std::forward<_OtherType>(rhs)) < 0;
+}
+
+///////////////////////////////
+// >
+template <typename _Type, typename _Traits>
+constexpr bool
+operator>(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return lhs.compare(rhs) > 0;
+}
+// user conversion for stuff like std::string or char*, literals
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator>(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept((basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs)))))
+{
+  return basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(lhs)).compare(rhs) > 0;
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator>(const basic_string_view<_Type, _Traits> lhs,
+          _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return lhs.compare(std::forward<_OtherType>(rhs)) > 0;
+}
+
+///////////////////////////////
+// <=
+template <typename _Type, typename _Traits>
+constexpr bool
+operator<=(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return lhs.compare(rhs) <= 0;
+}
+// user conversion for stuff like std::string or char*, literals
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator<=(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept((basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs)))))
+{
+  return basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(lhs)).compare(rhs) <= 0;
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator<=(const basic_string_view<_Type, _Traits> lhs,
+           _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return lhs.compare(std::forward<_OtherType>(rhs)) <= 0;
+}
+
+///////////////////////////////
+// >=
+template <typename _Type, typename _Traits>
+constexpr bool
+operator>=(const basic_string_view<_Type, _Traits> lhs, const 
basic_string_view<_Type, _Traits> rhs) noexcept
+{
+  return lhs.compare(rhs) >= 0;
+}
+// user conversion for stuff like std::string or char*, literals
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator>=(_OtherType &&lhs, const basic_string_view<_Type, _Traits> rhs) 
noexcept(
+  noexcept((basic_string_view<_Type, _Traits>(std::forward<_OtherType>(lhs)))))
+{
+  return basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(lhs)).compare(rhs) >= 0;
+}
+
+template <typename _Type, typename _Traits, typename _OtherType,
+          typename = std::enable_if_t<std::is_convertible<_OtherType, 
basic_string_view<_Type, _Traits>>::value>>
+constexpr bool
+operator>=(const basic_string_view<_Type, _Traits> lhs,
+           _OtherType &&rhs) noexcept(noexcept((basic_string_view<_Type, 
_Traits>(std::forward<_OtherType>(rhs)))))
+{
+  return lhs.compare(std::forward<_OtherType>(rhs)) >= 0;
+}
+#endif
+// stream operator
+
+template <typename _Type, typename _Traits>
+inline std::basic_ostream<_Type, _Traits> &
+operator<<(std::basic_ostream<_Type, _Traits> &os, const 
basic_string_view<_Type, _Traits> lhs)
+{
+  return os.write(lhs.data(), lhs.size());
+}
+using string_view = basic_string_view<char>;
+
+} // namespace ts
diff --git a/lib/ts/unit-tests/main.cpp b/lib/ts/unit-tests/main.cpp
new file mode 100644
index 0000000..72537d2
--- /dev/null
+++ b/lib/ts/unit-tests/main.cpp
@@ -0,0 +1,25 @@
+/** @file
+    
+  This file used for catch based tests. It is the main() stub.
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#define CATCH_CONFIG_MAIN 
+#include "catch.hpp"
diff --git a/lib/ts/unit-tests/string_view.cpp 
b/lib/ts/unit-tests/string_view.cpp
new file mode 100644
index 0000000..a49c5a0
--- /dev/null
+++ b/lib/ts/unit-tests/string_view.cpp
@@ -0,0 +1,523 @@
+/** @file
+  Test file for basic_string_view class
+  @section license License
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include "catch.hpp"
+
+#ifndef _DEBUG
+#define _DEBUG
+#endif
+
+#include "string_view.h"
+#include <iostream>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+constexpr auto npos = ts::string_view::npos;
+
+// ======= test for string_view ========
+// test cases:
+//[constructor] [operator] [type] [access] [capacity] [modifier] [operation] 
[compare] [find]
+
+TEST_CASE("constructor calls", "[string_view] [constructor]")
+{
+  SECTION("Literal look for NULL")
+  {
+    ts::string_view sv("hello");
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.length() == 5);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv == "hello");
+  }
+
+  SECTION("operator =")
+  {
+    ts::string_view sv;
+    sv = "hello";
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.length() == 5);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv == "hello");
+  }
+
+  SECTION("Literal with NULL")
+  {
+    ts::string_view sv("hello\0world");
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.length() == 5);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv == "hello");
+  }
+
+  SECTION("Literal with NULL and size given")
+  {
+    ts::string_view sv("hello\0world", 11);
+    REQUIRE(sv.size() == 11);
+    REQUIRE(sv.length() == 11);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv[6] == 'w');
+    REQUIRE(sv == ts::string_view("hello\0world", 11));
+  }
+
+  SECTION("Literal length given")
+  {
+    ts::string_view sv("hello", 5);
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.length() == 5);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv == "hello");
+  }
+
+  SECTION("Literal length equal 0")
+  {
+    ts::string_view sv("hello", 0);
+    REQUIRE(sv.size() == 0);
+    REQUIRE(sv.length() == 0);
+    REQUIRE(sv.empty() == true);
+    REQUIRE(sv == "");
+  }
+
+  SECTION("constructor using std string")
+  {
+    string std_string = "hello";
+    ts::string_view sv(std_string);
+
+    REQUIRE(sv.size() == std_string.size());
+    REQUIRE(sv.size() == std_string.size());
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv == "hello");
+  }
+
+  SECTION("= operator")
+  {
+    string std_string = "hello";
+    ts::string_view sv = std_string;
+    char str1[10] = "hello";
+    ts::string_view sv2 = str1;
+    char const *str2 = "hello";
+    ts::string_view sv3 = str2;
+
+    REQUIRE(sv == "hello");
+    REQUIRE(sv2 == "hello");
+    REQUIRE(sv3 == "hello");
+  }
+}
+
+TEST_CASE("operators", "[string_view] [operator]")
+{
+  SECTION("==")
+ {
+    ts::string_view sv("hello");
+
+    char str1[10] = "hello";
+    char const *str2 = "hello";
+    string str3 = "hello";
+
+    REQUIRE(str2 == str3);
+    REQUIRE(str1 == str3);
+    
+    REQUIRE(sv == "hello");
+    REQUIRE(sv == str1);
+    REQUIRE(sv == str2);
+    REQUIRE(sv == str3);
+  }
+  SECTION("!=")
+  {
+    ts::string_view sv("hello");
+
+    char str1[10] = "hhhhhhhhh";
+    char const *str2 = "hella";
+    string str3 = "";
+
+    REQUIRE(str2 != str3);
+    REQUIRE(str1 != str3);
+
+    REQUIRE(sv != str1);
+    REQUIRE(sv != str2);
+    REQUIRE(sv != str3);
+  }
+  SECTION(">")
+  {
+    ts::string_view sv("hello");
+
+    char str1[10] = "a";
+    char const *str2 = "abcdefg";
+    string str3 = "";
+
+    REQUIRE(sv > str1);
+    REQUIRE(sv > str2);
+    REQUIRE(sv > str3);
+  }
+  SECTION("<")
+  {
+    ts::string_view sv("hello");
+
+    char str1[10] = "z";
+    char const *str2 = "zaaaaaa";
+    string str3 = "hellz";
+
+    REQUIRE(sv < str1);
+    REQUIRE(sv < str2);
+    REQUIRE(sv < str3);
+  }
+  SECTION(">=")
+  {
+    ts::string_view sv("hello");
+
+    char str1[10] = "hello";
+    char const *str2 = "abcdefg";
+    string str3 = "";
+
+    REQUIRE(sv >= str1);
+    REQUIRE(sv >= str2);
+    REQUIRE(sv >= str3);
+  }
+  SECTION("<=")
+  {
+    ts::string_view sv("hello");
+
+    char str1[10] = "hello";
+    char const *str2 = "zaaaaaa";
+    string str3 = "hellz";
+
+    REQUIRE(sv <= str1);
+    REQUIRE(sv <= str2);
+    REQUIRE(sv <= str3);
+  }
+}
+
+TEST_CASE("Pass in type checking", "[string_view] [type]")
+{
+  SECTION("char [] type")
+  {
+    char str[10] = "hello";
+    ts::string_view sv(str);
+    REQUIRE(sv == "hello");
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.empty() == false);
+
+    char str2[10] = {};
+    ts::string_view sv2(str2);
+    REQUIRE(sv2 == "");
+    REQUIRE(sv2.empty() == true);
+  }
+
+  SECTION("char * type")
+  {
+    char const *str = "hello";
+    ts::string_view sv(str);
+    REQUIRE(sv == "hello");
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.empty() == false);
+  }
+
+  SECTION("literal type")
+  {
+    ts::string_view sv("hello");
+    REQUIRE(sv == "hello");
+  }
+}
+
+TEST_CASE("Access & iterators", "[string_view] [access]")
+{
+  SECTION("iterators: begin, end, rbegin, rend")
+  {
+    ts::string_view sv("abcde");
+
+    REQUIRE(*sv.begin() == 'a');
+    REQUIRE(*sv.cbegin() == 'a');
+    REQUIRE(*sv.end() == '\0');
+    REQUIRE(*sv.cend() == '\0');
+    REQUIRE(*sv.rbegin() == 'e');
+    REQUIRE(*sv.crbegin() == 'e');
+    REQUIRE(*sv.rend() == '\0');
+    REQUIRE(*sv.crend() == '\0');
+
+    int n = 0;
+    for (auto it : sv)
+    {
+      REQUIRE(it == sv[n]);
+      n++;
+    }
+  }
+
+  SECTION("access: [], at, front, back, data")
+  {
+    ts::string_view sv("abcde");
+    REQUIRE(sv[0] == 'a');
+    REQUIRE(sv[4] == 'e');
+
+    REQUIRE(sv.at(0) == 'a');
+    REQUIRE(sv.at(4) == 'e');
+
+    REQUIRE(sv.front() == 'a');
+    REQUIRE(sv.back() == 'e');
+
+    REQUIRE(sv.data()[1] == 'b');
+  }
+
+  SECTION("exception case")
+  {
+    ts::string_view sv("abcde");
+
+    REQUIRE_THROWS_AS(sv.at(100), std::out_of_range);
+    REQUIRE_THROWS_AS(sv.at(-1), std::out_of_range);
+
+    REQUIRE_THROWS_AS(sv[100], std::out_of_range);
+    REQUIRE_THROWS_AS(sv[-1], std::out_of_range);
+  }
+}
+
+TEST_CASE("Capacity", "[string_view] [capacity]")
+{
+  SECTION("empty string")
+  {
+    ts::string_view sv;
+    REQUIRE(sv.size() == 0);
+    REQUIRE(sv.length() == 0);
+    REQUIRE(sv.empty() == true);
+    REQUIRE(sv.max_size() == 0xfffffffffffffffe);
+  }
+
+  SECTION("literal string")
+  {
+    ts::string_view sv("abcde");
+    REQUIRE(sv.size() == 5);
+    REQUIRE(sv.length() == 5);
+    REQUIRE(sv.empty() == false);
+    REQUIRE(sv.max_size() == 0xfffffffffffffffe);
+  }
+}
+
+TEST_CASE("Modifier", "[string_view] [modifier]")
+{
+  SECTION("remove prefix")
+  {
+    ts::string_view sv("abcde");
+
+    sv.remove_prefix(0);
+    REQUIRE(sv == "abcde");
+
+    sv.remove_prefix(3);
+    REQUIRE(sv == "de");
+
+    sv.remove_prefix(100);
+    REQUIRE(sv == "");
+  }
+
+  SECTION("remove suffix")
+  {
+    ts::string_view sv("abcde");
+
+    sv.remove_suffix(0);
+    REQUIRE(sv == "abcde");
+
+    sv.remove_suffix(3);
+    REQUIRE(sv == "ab");
+
+    sv.remove_suffix(100);
+    REQUIRE(sv == "");
+  }
+
+  SECTION("swap")
+  {
+    ts::string_view sv1("hello");
+    ts::string_view sv2("world");
+
+    sv1.swap(sv2);
+
+    REQUIRE(sv1 == "world");
+    REQUIRE(sv2 == "hello");
+  }
+}
+
+TEST_CASE("Operations", "[string_view] [operation]")
+{
+  SECTION("copy")
+  {
+    //weird copy
+
+    // char str[10];
+    // ts::string_view sv("hello");
+    // sv.copy(str, 6, 0);
+    // REQUIRE(str == "hello");
+  }
+  SECTION("substr")
+  {
+    ts::string_view sv("hello");
+    REQUIRE(sv.substr(0, 3) == "hel");
+    REQUIRE(sv.substr(1, 3) == "ell");
+    REQUIRE(sv.substr(0, 100) == "hello");
+  }
+  SECTION("exception case")
+  {
+    ts::string_view sv("hello");
+    REQUIRE_THROWS_AS(sv.substr(100, 0), std::out_of_range);
+    REQUIRE_THROWS_AS(sv.substr(-1, -1), std::out_of_range);
+  }
+}
+
+TEST_CASE("Compare", "[string_view] [compare]")
+{
+  SECTION("compare pass in char")
+  {
+    ts::string_view sv("hello");
+    REQUIRE(sv.compare("hello") == 0);
+    REQUIRE(sv.compare("hella") > 0);
+    REQUIRE(sv.compare("hellz") < 0);
+    REQUIRE(sv.compare("aaaaaaa") > 0);
+    REQUIRE(sv.compare("zzzzzzz") < 0);
+    REQUIRE(sv.compare("") > 0);
+
+    ts::string_view sv2("hello");
+    REQUIRE(sv2.compare(0, 3, "hel") == 0);
+    REQUIRE(sv2.compare(1, 3, "ello", 0, 3) == 0);
+
+    ts::string_view sv3("");
+    REQUIRE(sv3.compare("hello") < 0);
+  }
+
+  SECTION("compare pass in string view")
+  {
+    ts::string_view sv("hello");
+    ts::string_view sv_test1("hello");
+    ts::string_view sv_test2("aello");
+    ts::string_view sv_test3("zello");
+    REQUIRE(sv.compare(sv_test1) == 0);
+    REQUIRE(sv.compare(sv_test2) > 0);
+    REQUIRE(sv.compare(sv_test3) < 0);
+
+    ts::string_view sv2("hello");
+    ts::string_view sv_test4("hel");
+    ts::string_view sv_test5("ello");
+    REQUIRE(sv.compare(0, 3, sv_test4) == 0);
+    REQUIRE(sv.compare(1, 3, sv_test5, 0, 3) == 0);
+  }
+
+  SECTION("exception case")
+  {
+    ts::string_view sv("hello");
+    REQUIRE_THROWS_AS(sv.compare(100, 1, "hel"), std::out_of_range);
+    REQUIRE_THROWS_AS(sv.compare(100, 100, "hel"), std::out_of_range);
+    REQUIRE_THROWS_AS(sv.compare(-1, -1, "hel"), std::out_of_range);
+  }
+}
+
+TEST_CASE("Find", "[string_view] [find]")
+{
+  SECTION("find")
+  {
+    ts::string_view sv("abcdabcd");
+    ts::string_view svtest("bcd");
+
+    REQUIRE(sv.find("abcdabcd", 100, 10) == npos);
+
+    REQUIRE(sv.find('a') == 0);
+    REQUIRE(sv.find(svtest) == 1);
+    REQUIRE(sv.find(svtest, 2) == 5);
+
+    REQUIRE(sv.find("bcd") == 1);
+    REQUIRE(sv.find("bcd", 6) == npos);
+
+    REQUIRE(sv.find("bcdx", 0, 3) == 1);
+    REQUIRE(sv.find("bcdx", 0, 4) == npos);
+
+    ts::string_view sv2;
+    REQUIRE(sv2.find('a') == npos);
+  }
+
+  SECTION("rfind")
+  {
+    ts::string_view sv("abcdabcd");
+    ts::string_view svtest("bcd");
+    REQUIRE(sv.find('a') == 0);
+    REQUIRE(sv.rfind(svtest) == 5);
+
+    REQUIRE(sv.rfind("bcd") == 5);
+    REQUIRE(sv.rfind("bcd", 3) == 1);
+    REQUIRE(sv.rfind("bcd", 0) == npos);
+
+    REQUIRE(sv.rfind("bcdx", 3, 3) == 1);
+    REQUIRE(sv.rfind("bcdx", 3, 4) == npos);
+  }
+
+  SECTION("find_first_of")
+  {
+    ts::string_view sv("abcdefgabcdefg");
+    ts::string_view svtest("hijklma");
+
+    REQUIRE(sv.find_first_of('c') == 2);
+
+    REQUIRE(sv.find_first_of(svtest) == 0);
+    REQUIRE(sv.find_first_of("hijklmb") == 1);
+    REQUIRE(sv.find_first_of("hijklmn") == npos);
+    REQUIRE(sv.find_first_of("hijkla", 1) == 7);
+
+    REQUIRE(sv.find_first_of("hijkla", 1, 0) == npos);
+    REQUIRE(sv.find_first_of("hijkla", 1, 5) == npos);
+    REQUIRE(sv.find_first_of("hijkla", 1, 6) == 7);
+  }
+
+  SECTION("find_last_of")
+  {
+    ts::string_view sv("abcdefgabcdefg");
+    ts::string_view svtest("hijklma");
+
+    REQUIRE(sv.find_last_of('c') == 9);
+
+    REQUIRE(sv.find_last_of(svtest) == 7);
+    REQUIRE(sv.find_last_of("hijklmb") == 8);
+    REQUIRE(sv.find_last_of("hijklmn") == npos);
+
+    REQUIRE(sv.find_last_of("hijkla", 1, 0) == npos);
+    REQUIRE(sv.find_last_of("hijkla", 1, 5) == npos);
+    REQUIRE(sv.find_last_of("hijkla", 1, 6) == 0);
+  }
+  SECTION("find_first_not_of")
+  {
+    ts::string_view sv("abcdefg");
+    ts::string_view svtest("abcdxyz");
+
+    REQUIRE(sv.find_first_not_of('x') == 0);
+
+    REQUIRE(sv.find_first_not_of(svtest) == 4);
+    REQUIRE(sv.find_first_not_of("abcdxyz") == 4);
+    REQUIRE(sv.find_first_not_of("abcdefg") == npos);
+
+    REQUIRE(sv.find_first_not_of("abcdxyz", 1, 0) == 1);
+    REQUIRE(sv.find_first_not_of("abcdxyz", 1, 5) == 4);
+    REQUIRE(sv.find_first_not_of("aaaaaaaa", 1, 5) == 1);
+  }
+
+  SECTION("find_last_not_of")
+  {
+    ts::string_view sv("abcdefg");
+    ts::string_view svtest("abcdxyz");
+
+    REQUIRE(sv.find_last_not_of('x') == 6);
+
+    REQUIRE(sv.find_last_not_of(svtest) == 6);
+    REQUIRE(sv.find_last_not_of("abcdxyz") == 6);
+    REQUIRE(sv.find_last_not_of("abcdefg") == npos);
+
+    REQUIRE(sv.find_last_not_of("abcdxyz", 1, 0) == 1);
+    REQUIRE(sv.find_last_not_of("abcdxyz", 1, 5) == npos);
+    REQUIRE(sv.find_last_not_of("aaaaaaaa", 1, 5) == 1);
+  }
+}
diff --git a/tests/catch.hpp b/tests/include/catch.hpp
similarity index 100%
rename from tests/catch.hpp
rename to tests/include/catch.hpp

-- 
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <commits@trafficserver.apache.org>.

Reply via email to