1// -*- C++ -*-
2/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
3     Written by James Clark (jjc@jclark.com)
4
5This file is part of groff.
6
7groff is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12groff is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License along
18with groff; see the file COPYING.  If not, write to the Free Software
19Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include <string.h>
22#include <stdio.h>
23#include <assert.h>
24
25// Ensure that the first declaration of functions that are later
26// declared as inline declares them as inline.
27
28class string;
29
30inline string operator+(const string &, const string &);
31inline string operator+(const string &, const char *);
32inline string operator+(const char *, const string &);
33inline string operator+(const string &, char);
34inline string operator+(char, const string &);
35inline int operator==(const string &, const string &);
36inline int operator!=(const string &, const string &);
37
38class string {
39public:
40  string();
41  string(const string &);
42  string(const char *);
43  string(const char *, int);
44  string(char);
45
46  ~string();
47
48  string &operator=(const string &);
49  string &operator=(const char *);
50  string &operator=(char);
51
52  string &operator+=(const string &);
53  string &operator+=(const char *);
54  string &operator+=(char);
55  void append(const char *, int);
56
57  int length() const;
58  int empty() const;
59  int operator*() const;
60
61  string substring(int i, int n) const;
62
63  char &operator[](int);
64  char operator[](int) const;
65
66  void set_length(int i);
67  const char *contents() const;
68  int search(char) const;
69  char *extract() const;
70  void remove_spaces();
71  void clear();
72  void move(string &);
73
74  friend string operator+(const string &, const string &);
75  friend string operator+(const string &, const char *);
76  friend string operator+(const char *, const string &);
77  friend string operator+(const string &, char);
78  friend string operator+(char, const string &);
79
80  friend int operator==(const string &, const string &);
81  friend int operator!=(const string &, const string &);
82  friend int operator<=(const string &, const string &);
83  friend int operator<(const string &, const string &);
84  friend int operator>=(const string &, const string &);
85  friend int operator>(const string &, const string &);
86
87private:
88  char *ptr;
89  int len;
90  int sz;
91
92  string(const char *, int, const char *, int);	// for use by operator+
93  void grow1();
94};
95
96
97inline char &string::operator[](int i)
98{
99  assert(i >= 0 && i < len);
100  return ptr[i];
101}
102
103inline char string::operator[](int i) const
104{
105  assert(i >= 0 && i < len);
106  return ptr[i];
107}
108
109inline int string::length() const
110{
111  return len;
112}
113
114inline int string::empty() const
115{
116  return len == 0;
117}
118
119inline int string::operator*() const
120{
121  return len;
122}
123
124inline const char *string::contents() const
125{
126  return ptr;
127}
128
129inline string operator+(const string &s1, const string &s2)
130{
131  return string(s1.ptr, s1.len, s2.ptr, s2.len);
132}
133
134inline string operator+(const string &s1, const char *s2)
135{
136#ifdef __GNUG__
137  if (s2 == 0)
138    return s1;
139  else
140    return string(s1.ptr, s1.len, s2, strlen(s2));
141#else
142  return s2 == 0 ? s1 : string(s1.ptr, s1.len, s2, strlen(s2));
143#endif
144}
145
146inline string operator+(const char *s1, const string &s2)
147{
148#ifdef __GNUG__
149  if (s1 == 0)
150    return s2;
151  else
152    return string(s1, strlen(s1), s2.ptr, s2.len);
153#else
154  return s1 == 0 ? s2 : string(s1, strlen(s1), s2.ptr, s2.len);
155#endif
156}
157
158inline string operator+(const string &s, char c)
159{
160  return string(s.ptr, s.len, &c, 1);
161}
162
163inline string operator+(char c, const string &s)
164{
165  return string(&c, 1, s.ptr, s.len);
166}
167
168inline int operator==(const string &s1, const string &s2)
169{
170  return (s1.len == s2.len
171	  && (s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) == 0));
172}
173
174inline int operator!=(const string &s1, const string &s2)
175{
176  return (s1.len != s2.len
177	  || (s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) != 0));
178}
179
180inline string string::substring(int i, int n) const
181{
182  assert(i >= 0 && i + n <= len);
183  return string(ptr + i, n);
184}
185
186inline string &string::operator+=(char c)
187{
188  if (len >= sz)
189    grow1();
190  ptr[len++] = c;
191  return *this;
192}
193
194void put_string(const string &, FILE *);
195
196string as_string(int);
197