text: // file      : xsd/cxx/ro-string.hxx
  // copyright : Copyright (c) 2005-2017 Code Synthesis Tools CC
  // license   : GNU GPL v2 + exceptions; see accompanying LICENSE file
  
  #ifndef XSD_CXX_RO_STRING_HXX
  #define XSD_CXX_RO_STRING_HXX
  
  #include <string>
  #include <cstddef> // std::size_t
  #include <ostream>
  
  namespace xsd
  {
    namespace cxx
    {
      // Read-only string class template.
      //
      template <typename C>
      class ro_string
      {
      public:
        typedef std::char_traits<C> traits_type;
        typedef std::size_t	    size_type;
  
        static const size_type npos = ~(size_type (0));
  
      public:
        ro_string ()
            : data_ (0), size_ (0)
        {
        }
  
        ro_string (const C* s)
            : data_ (s), size_ (traits_type::length (s))
        {
        }
  
        ro_string (const C* s, size_type size)
            : data_ (s), size_ (size)
        {
        }
  
        ro_string (const std::basic_string<C>& s)
            : data_ (s.data ()), size_ (s.size ())
        {
        }
  
        operator std::basic_string<C> () const
        {
          return std::basic_string<C> (data (), size ());
        }
  
      private:
        ro_string (const ro_string&);
  
        ro_string&
        operator= (const ro_string&);
  
      public:
        // The returned string is not necessarily terminated  with '\0'.
        // If size() returns 0, the returned pointer may be 0.
        //
        const C*
        data () const
        {
          return data_;
        }
  
        size_type
        size () const
        {
          return size_;
        }
  
        size_type
        length () const
        {
          return size ();
        }
  
      public:
        bool
        empty () const
        {
          return size () == 0;
        }
  
        const C&
        operator[] (size_type pos) const
        {
          return data ()[pos];
        }
  
      public:
        void
        assign (const C* s)
        {
          data_ = s;
          size_ = traits_type::length (s);
        }
  
        void
        assign (const C* s, size_type size)
        {
          data_ = s;
          size_ = size;
        }
  
        void
        assign (const std::basic_string<C>& s)
        {
          data_ = s.c_str ();
          size_ = s.size ();
        }
  
      public:
        int
        compare (const ro_string& str) const
        {
          return compare (str.data (), str.size ());
        }
  
        int
        compare (const std::basic_string<C>& str) const
        {
          return compare (str.c_str (), str.size ());
        }
  
        int
        compare (const C* str) const
        {
          return compare (str, traits_type::length (str));
        }
  
        int
        compare (const C* str, size_type n) const
        {
          size_type s1 (size ());
          size_type s (s1 < n ? s1 : n);
  
          int r (s != 0 ? traits_type::compare (data (), str, s) : 0);
  
          if (!r && s1 != n)
            r = s1 < n ? -1 : 1;
  
          return r;
        }
  
      public:
        size_type
        find (C c, size_type pos = 0) const;
  
      private:
        const C* data_;
        size_type size_;
      };
  
      // operator==
      //
      template <typename C>
      inline bool
      operator== (const ro_string<C>& a, const ro_string<C>& b)
      {
        return a.compare (b) == 0;
      }
  
      template <typename C>
      inline bool
      operator== (const ro_string<C>& a, const std::basic_string<C>& b)
      {
        return a.compare (b) == 0;
      }
  
      template <typename C>
      inline bool
      operator== (const std::basic_string<C>& a, const ro_string<C>& b)
      {
        return b.compare (a) == 0;
      }
  
      template <typename C>
      inline bool
      operator== (const ro_string<C>& a, const C* b)
      {
        return a.compare (b) == 0;
      }
  
      template <typename C>
      inline bool
      operator== (const C* a, const ro_string<C>& b)
      {
        return b.compare (a) == 0;
      }
  
      // operator!=
      //
      template <typename C>
      inline bool
      operator!= (const ro_string<C>& a, const ro_string<C>& b)
      {
        return a.compare (b) != 0;
      }
  
      template <typename C>
      inline bool
      operator!= (const ro_string<C>& a, const std::basic_string<C>& b)
      {
        return a.compare (b) != 0;
      }
  
      template <typename C>
      inline bool
      operator!= (const std::basic_string<C>& a, const ro_string<C>& b)
      {
        return b.compare (a) != 0;
      }
  
      template <typename C>
      inline bool
      operator!= (const ro_string<C>& a, const C* b)
      {
        return a.compare (b) != 0;
      }
  
      template <typename C>
      inline bool
      operator!= (const C* a, const ro_string<C>& b)
      {
        return b.compare (a) != 0;
      }
  
      // operator<
      //
      template <typename C>
      inline bool
      operator< (const ro_string<C>& l, const ro_string<C>& r)
      {
        return l.compare (r) < 0;
      }
  
      template <typename C>
      inline bool
      operator< (const ro_string<C>& l, const std::basic_string<C>& r)
      {
        return l.compare (r) < 0;
      }
  
      template <typename C>
      inline bool
      operator< (const std::basic_string<C>& l, const ro_string<C>& r)
      {
        return r.compare (l) > 0;
      }
  
      template <typename C>
      inline bool
      operator< (const ro_string<C>& l, const C* r)
      {
        return l.compare (r) < 0;
      }
  
      template <typename C>
      inline bool
      operator< (const C* l, const ro_string<C>& r)
      {
        return r.compare (l) > 0;
      }
  
  
      // operator>
      //
      template <typename C>
      inline bool
      operator> (const ro_string<C>& l, const ro_string<C>& r)
      {
        return l.compare (r) > 0;
      }
  
      template <typename C>
      inline bool
      operator> (const ro_string<C>& l, const std::basic_string<C>& r)
      {
        return l.compare (r) > 0;
      }
  
      template <typename C>
      inline bool
      operator> (const std::basic_string<C>& l, const ro_string<C>& r)
      {
        return r.compare (l) < 0;
      }
  
      template <typename C>
      inline bool
      operator> (const ro_string<C>& l, const C* r)
      {
        return l.compare (r) > 0;
      }
  
      template <typename C>
      inline bool
      operator> (const C* l, const ro_string<C>& r)
      {
        return r.compare (l) < 0;
      }
  
      // operator<=
      //
      template <typename C>
      inline bool
      operator<= (const ro_string<C>& l, const ro_string<C>& r)
      {
        return l.compare (r) <= 0;
      }
  
      template <typename C>
      inline bool
      operator<= (const ro_string<C>& l, const std::basic_string<C>& r)
      {
        return l.compare (r) <= 0;
      }
  
      template <typename C>
      inline bool
      operator<= (const std::basic_string<C>& l, const ro_string<C>& r)
      {
        return r.compare (l) >= 0;
      }
  
      template <typename C>
      inline bool
      operator<= (const ro_string<C>& l, const C* r)
      {
        return l.compare (r) <= 0;
      }
  
      template <typename C>
      inline bool
      operator<= (const C* l, const ro_string<C>& r)
      {
        return r.compare (l) >= 0;
      }
  
  
      // operator>=
      //
      template <typename C>
      inline bool
      operator>= (const ro_string<C>& l, const ro_string<C>& r)
      {
        return l.compare (r) >= 0;
      }
  
      template <typename C>
      inline bool
      operator>= (const ro_string<C>& l, const std::basic_string<C>& r)
      {
        return l.compare (r) >= 0;
      }
  
      template <typename C>
      inline bool
      operator>= (const std::basic_string<C>& l, const ro_string<C>& r)
      {
        return r.compare (l) <= 0;
      }
  
      template <typename C>
      inline bool
      operator>= (const ro_string<C>& l, const C* r)
      {
        return l.compare (r) >= 0;
      }
  
      template <typename C>
      inline bool
      operator>= (const C* l, const ro_string<C>& r)
      {
        return r.compare (l) <= 0;
      }
  
      // operator<<
      //
      template<typename C>
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, const ro_string<C>& str)
      {
        if (str.size () != 0)
          os.write (str.data (), static_cast<std::streamsize> (str.size ()));
  
        return os;
      }
  
      // operator+=
      //
      template<typename C>
      std::basic_string<C>&
      operator+= (std::basic_string<C>& l, const ro_string<C>& r)
      {
        l.append (r.data (), r.size ());
        return l;
      }
  
      // Trim leading and trailing XML whitespaces. Return the new
      // string size.
      //
      template <typename C>
      typename ro_string<C>::size_type
      trim_left (ro_string<C>&);
  
      template <typename C>
      typename ro_string<C>::size_type
      trim_right (ro_string<C>&);
  
      template <typename C>
      typename ro_string<C>::size_type
      trim (ro_string<C>&);
  
      // Trim leading and trailing XML whitespaces.
      //
      template<typename C>
      std::basic_string<C>
      trim (const std::basic_string<C>&);
    }
  }
  
  #include <xsd/cxx/ro-string.txx>
  
  #endif  // XSD_CXX_RO_STRING_HXX
  