175584Sru// -*- C++ -*-
2104862Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
375584Sru     Written by James Clark (jjc@jclark.com)
475584Sru
575584SruThis file is part of groff.
675584Sru
775584Srugroff is free software; you can redistribute it and/or modify it under
875584Sruthe terms of the GNU General Public License as published by the Free
975584SruSoftware Foundation; either version 2, or (at your option) any later
1075584Sruversion.
1175584Sru
1275584Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
1375584SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
1475584SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1575584Srufor more details.
1675584Sru
1775584SruYou should have received a copy of the GNU General Public License along
1875584Sruwith groff; see the file COPYING.  If not, write to the Free Software
19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
2075584Sru
2175584Sru#include <string.h>
2275584Sru#include <stdio.h>
2375584Sru#include <assert.h>
2475584Sru
2575584Sru// Ensure that the first declaration of functions that are later
2675584Sru// declared as inline declares them as inline.
2775584Sru
2875584Sruclass string;
2975584Sru
3075584Sruinline string operator+(const string &, const string &);
3175584Sruinline string operator+(const string &, const char *);
3275584Sruinline string operator+(const char *, const string &);
3375584Sruinline string operator+(const string &, char);
3475584Sruinline string operator+(char, const string &);
3575584Sruinline int operator==(const string &, const string &);
3675584Sruinline int operator!=(const string &, const string &);
3775584Sru
3875584Sruclass string {
3975584Srupublic:
4075584Sru  string();
4175584Sru  string(const string &);
4275584Sru  string(const char *);
4375584Sru  string(const char *, int);
4475584Sru  string(char);
4575584Sru
4675584Sru  ~string();
4775584Sru
4875584Sru  string &operator=(const string &);
4975584Sru  string &operator=(const char *);
5075584Sru  string &operator=(char);
5175584Sru
5275584Sru  string &operator+=(const string &);
5375584Sru  string &operator+=(const char *);
5475584Sru  string &operator+=(char);
5575584Sru  void append(const char *, int);
5675584Sru
5775584Sru  int length() const;
5875584Sru  int empty() const;
5975584Sru  int operator*() const;
6075584Sru
6175584Sru  string substring(int i, int n) const;
6275584Sru
6375584Sru  char &operator[](int);
6475584Sru  char operator[](int) const;
6575584Sru
6675584Sru  void set_length(int i);
6775584Sru  const char *contents() const;
6875584Sru  int search(char) const;
6975584Sru  char *extract() const;
70104862Sru  void remove_spaces();
7175584Sru  void clear();
7275584Sru  void move(string &);
7375584Sru
7475584Sru  friend string operator+(const string &, const string &);
7575584Sru  friend string operator+(const string &, const char *);
7675584Sru  friend string operator+(const char *, const string &);
7775584Sru  friend string operator+(const string &, char);
7875584Sru  friend string operator+(char, const string &);
7975584Sru
8075584Sru  friend int operator==(const string &, const string &);
8175584Sru  friend int operator!=(const string &, const string &);
8275584Sru  friend int operator<=(const string &, const string &);
8375584Sru  friend int operator<(const string &, const string &);
8475584Sru  friend int operator>=(const string &, const string &);
8575584Sru  friend int operator>(const string &, const string &);
8675584Sru
8775584Sruprivate:
8875584Sru  char *ptr;
8975584Sru  int len;
9075584Sru  int sz;
9175584Sru
9275584Sru  string(const char *, int, const char *, int);	// for use by operator+
9375584Sru  void grow1();
9475584Sru};
9575584Sru
9675584Sru
9775584Sruinline char &string::operator[](int i)
9875584Sru{
9975584Sru  assert(i >= 0 && i < len);
10075584Sru  return ptr[i];
10175584Sru}
10275584Sru
10375584Sruinline char string::operator[](int i) const
10475584Sru{
10575584Sru  assert(i >= 0 && i < len);
10675584Sru  return ptr[i];
10775584Sru}
10875584Sru
10975584Sruinline int string::length() const
11075584Sru{
11175584Sru  return len;
11275584Sru}
11375584Sru
11475584Sruinline int string::empty() const
11575584Sru{
11675584Sru  return len == 0;
11775584Sru}
11875584Sru
11975584Sruinline int string::operator*() const
12075584Sru{
12175584Sru  return len;
12275584Sru}
12375584Sru
12475584Sruinline const char *string::contents() const
12575584Sru{
126104862Sru  return ptr;
12775584Sru}
12875584Sru
12975584Sruinline string operator+(const string &s1, const string &s2)
13075584Sru{
13175584Sru  return string(s1.ptr, s1.len, s2.ptr, s2.len);
13275584Sru}
13375584Sru
13475584Sruinline string operator+(const string &s1, const char *s2)
13575584Sru{
13675584Sru#ifdef __GNUG__
13775584Sru  if (s2 == 0)
13875584Sru    return s1;
13975584Sru  else
14075584Sru    return string(s1.ptr, s1.len, s2, strlen(s2));
14175584Sru#else
14275584Sru  return s2 == 0 ? s1 : string(s1.ptr, s1.len, s2, strlen(s2));
14375584Sru#endif
14475584Sru}
14575584Sru
14675584Sruinline string operator+(const char *s1, const string &s2)
14775584Sru{
14875584Sru#ifdef __GNUG__
14975584Sru  if (s1 == 0)
15075584Sru    return s2;
15175584Sru  else
15275584Sru    return string(s1, strlen(s1), s2.ptr, s2.len);
15375584Sru#else
15475584Sru  return s1 == 0 ? s2 : string(s1, strlen(s1), s2.ptr, s2.len);
15575584Sru#endif
15675584Sru}
15775584Sru
15875584Sruinline string operator+(const string &s, char c)
15975584Sru{
16075584Sru  return string(s.ptr, s.len, &c, 1);
16175584Sru}
16275584Sru
16375584Sruinline string operator+(char c, const string &s)
16475584Sru{
16575584Sru  return string(&c, 1, s.ptr, s.len);
16675584Sru}
16775584Sru
16875584Sruinline int operator==(const string &s1, const string &s2)
16975584Sru{
17075584Sru  return (s1.len == s2.len
17175584Sru	  && (s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) == 0));
17275584Sru}
17375584Sru
17475584Sruinline int operator!=(const string &s1, const string &s2)
17575584Sru{
17675584Sru  return (s1.len != s2.len
17775584Sru	  || (s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) != 0));
17875584Sru}
17975584Sru
18075584Sruinline string string::substring(int i, int n) const
18175584Sru{
18275584Sru  assert(i >= 0 && i + n <= len);
18375584Sru  return string(ptr + i, n);
18475584Sru}
18575584Sru
18675584Sruinline string &string::operator+=(char c)
18775584Sru{
18875584Sru  if (len >= sz)
18975584Sru    grow1();
19075584Sru  ptr[len++] = c;
19175584Sru  return *this;
19275584Sru}
19375584Sru
19475584Sruvoid put_string(const string &, FILE *);
19575584Sru
19675584Srustring as_string(int);
197