// const_string and null_char_iterator
// Copyright 1998 by Kevin Atkinson under the terms of the LGPL

#ifndef __const_string1_hh__
#define __const_string1_hh__

#include <iostream.h>
//#include <stdexcept>

//:
class null_char_iterator {
  friend bool operator== (const null_char_iterator &lhs,
			  const null_char_iterator &rhs);
  const char *_data;
public:
  null_char_iterator() : _data(0) {}                         //:
  null_char_iterator(const char *d) : _data(d) {}            //:
  const char & operator* () const {return *_data;}           //:
  null_char_iterator& operator++ () {++_data; return *this;} //:
  null_char_iterator operator++ (int) {return _data++;}      //:
};

//! with_class = null_char_iterator

//:
inline bool operator== (const null_char_iterator &lhs,
			const null_char_iterator &rhs) {
  if (!lhs._data) {
    if (!rhs._data) return false;
    else if (!*rhs._data) return true;
    else return false;
  } else if (!rhs._data) {
    if (!*lhs._data) return true;
    else return false;
  }
  return lhs._data == rhs._data;
}

//:
inline bool operator!= (const null_char_iterator &lhs,
			const null_char_iterator &rhs) {
  return !(lhs == rhs);
}

//: A special string that is created from a existing const char *
// It contains a small subset of the standard string class.  When an
// object is created only a link to the const char * is created.  The
// data is NOT copied.  thus the const char * needs to stick around
// for the life of the class.
class const_string {
private:
  const char *str_data; 
public:
  typedef const char   value_type;      //:
  typedef unsigned int size_type;       //:
  typedef          int difference_type; //:

  typedef const char&     const_reference; //:
  typedef const_reference reference;       //:
  typedef const char*     const_pointer;   //:
  typedef const_pointer   pointer;         //:

  typedef const char*    const_iterator;   //:
  typedef const_iterator iterator;         
  //: The same as const_iterator because the data can not be changed.

  typedef null_char_iterator null_const_iterator;//:
  typedef const_iterator     null_iterator;      //:
  
  const_string() : str_data("") {}                 //:
  const_string(const char *str) : str_data(str) {} //:
  const_string& operator= (const char *str)       //:
    {str_data = str; 
     return *this;}

  size_type size() const //: 
  { register int i = 0;
    while (str_data[i]) i++;
    return i;
  }
  
  bool empty() const //:
    {return !str_data[0];}

  void resize(size_type i) //:
    {if (i == 0) str_data="";}

  const_iterator      begin() const {return str_data;}          //:
  const_iterator      end()   const {return str_data + size();} //:

  null_const_iterator null_begin() const  //:
    {return null_char_iterator(str_data);}
  null_const_iterator null_end()   const  //:
    {return null_char_iterator();}

  size_type length() const {return size();}   //:
  size_type max_size() const {return size();} //:
  
  const_reference operator[](size_type pos) const {return str_data[pos];} //:
  const_reference at(size_type pos) const //: 
  {
    //if (pos >= size()) throw out_of_range("");
    return str_data[pos];
  }

  operator const char * () const {return str_data;} //:
  const char* c_str() const {return str_data;}      //:
  const char* data()  const {return str_data;}      //:
  
  int compare(const const_string& str) const //:
  {
    const char* str1 = str_data;
    const char* str2 = str.str_data;
    while (*str1 == *str2 && (*str1 || *str2)) {str1++; str2++;}
    return *str1-*str2;
  }
};


//! with_class = const_string

//:
inline ostream& operator << (ostream &o, const const_string &str) {
  return o << str.c_str();
}

//:
inline int compare (const const_string &lhs, const const_string &rhs) {
  return lhs.compare(rhs);
}

//:
inline int compare (const const_string &lhs, const char *rhs) {
  return lhs.compare(rhs);
}

//:
inline int compare (const char *lhs, const const_string &rhs) {
  return static_cast<const const_string>(lhs).compare(rhs);
}

#define CS_COMPARE(OP, LHS, RHS) \
  inline bool operator OP (const RHS lhs, const LHS rhs) \
   {return compare(lhs,rhs) OP 0;}

#define CS_COMPARES(OP) \
  CS_COMPARE(OP, const_string &, const_string &) \
  CS_COMPARE(OP, char *, const_string &) \
  CS_COMPARE(OP, const_string &, char *) \
  
CS_COMPARES(==)
CS_COMPARES(!=)
CS_COMPARES(<)
CS_COMPARES(<=)
CS_COMPARES(>)
CS_COMPARES(>=)

#undef CS_COMPARES
#undef CS_COMPARE

#endif

  
 
  
  
  
