// Partial listing of SPString
// header
class SPString
{
private:
  // variable length string mechanism
  VarString pstr;
    
public:
  // forward declare
  class substring;
    
  // ....
  SPString(const substring& sb) : pstr(sb.pt, sb.len){}
  SPString& operator=(const substring& sb);

  operator const char*() const{return pstr;}
  const char operator[](int n) const{ return pstr[n]; }

  int length(void) const{ return pstr.length(); }

  substring substr(int offset, int len= -1);
  substring substr(const Range& r){ return substr(r.start(), r.length());}
        
  SPStringList split(const char *pat= "[ \t\n]+", int limit= -1);
    
  int operator<(const SPString& s) const
  { return (strcmp(pstr, s) < 0); }
  // ditto for > <= >= == !=

  int operator>(const char *s) const
  { return (strcmp(pstr, s) > 0); }
  // ditto for < <= >= == !=

  friend int operator==(const char *s, const SPString& sp)
  { return (strcmp(s, sp.pstr) == 0); }
  // ditto for > <= >= < !=

  friend substring;

private:
  void insert(int pos, int len, const char *pt, int nlen);

  class substring
  {
  public:
    int pos, len;
    SPString& str;
    char *pt;

    substring(SPString& os, int p, int l) : str(os)
    {
      if(p > os.length()) p= os.length();
      if((p+l) > os.length()) l= os.length() - p;
      pos= p; len= l;
      if(p == os.length()) pt= 0; // append to end of string
      else pt= &os.pstr[p];
    }

    void operator=(const SPString& s)
    {
       if(&str == &s){ // potentially overlapping
         VarString tmp(s);
         str.insert(pos, len, tmp, strlen(tmp));
        }else str.insert(pos, len, s, s.length());
    }
        
    void operator=(const substring& s)
    {
      if(&str == &s.str){ // potentially overlapping
        VarString tmp(s.pt, s.len);
        str.insert(pos, len, tmp, strlen(tmp));
      }else str.insert(pos, len, s.pt, s.len);
    }

    void operator=(const char *s)
    {
      str.insert(pos, len, s, strlen(s));
    }
  };
};

