Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / groff / src / libs / libgroff / string.cc
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
3    Free Software Foundation, Inc.
4      Written by James Clark (jjc@jclark.com)
5
6 This file is part of groff.
7
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING.  If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "lib.h"
23
24 #include "stringclass.h"
25
26 static char *salloc(int len, int *sizep);
27 static void sfree(char *ptr, int size);
28 static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
29 static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
30
31 static char *salloc(int len, int *sizep)
32 {
33   if (len == 0) {
34     *sizep = 0;
35     return 0;
36   }
37   else
38     return new char[*sizep = len*2];
39 }
40
41 static void sfree(char *ptr, int)
42 {
43   a_delete ptr;
44 }
45
46 static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep)
47 {
48   if (oldsz >= len) {
49     *sizep = oldsz;
50     return ptr;
51   }
52   a_delete ptr;
53   if (len == 0) {
54     *sizep = 0;
55     return 0;
56   }
57   else
58     return new char[*sizep = len*2];
59 }
60
61 static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep)
62 {
63   if (oldsz >= newlen) {
64     *sizep = oldsz;
65     return ptr;
66   }
67   if (newlen == 0) {
68     a_delete ptr;
69     *sizep = 0;
70     return 0;
71   }
72   else {
73     char *p = new char[*sizep = newlen*2];
74     if (oldlen < newlen && oldlen != 0)
75       memcpy(p, ptr, oldlen);
76     a_delete ptr;
77     return p;
78   }
79 }
80
81 string::string() : ptr(0), len(0), sz(0)
82 {
83 }
84
85 string::string(const char *p, int n) : len(n)
86 {
87   assert(n >= 0);
88   ptr = salloc(n, &sz);
89   if (n != 0)
90     memcpy(ptr, p, n);
91 }
92
93 string::string(const char *p)
94 {
95   if (p == 0) {
96     len = 0;
97     ptr = 0;
98     sz = 0;
99   }
100   else {
101     len = strlen(p);
102     ptr = salloc(len, &sz);
103     memcpy(ptr, p, len);
104   }
105 }
106
107 string::string(char c) : len(1)
108 {
109   ptr = salloc(1, &sz);
110   *ptr = c;
111 }
112
113 string::string(const string &s) : len(s.len)
114 {
115   ptr = salloc(len, &sz);
116   if (len != 0)
117     memcpy(ptr, s.ptr, len);
118 }
119   
120 string::~string()
121 {
122   sfree(ptr, sz);
123 }
124
125 string &string::operator=(const string &s)
126 {
127   ptr = sfree_alloc(ptr, sz, s.len, &sz);
128   len = s.len;
129   if (len != 0)
130     memcpy(ptr, s.ptr, len);
131   return *this;
132 }
133
134 string &string::operator=(const char *p)
135 {
136   if (p == 0) {
137     sfree(ptr, len);
138     len = 0;
139     ptr = 0;
140     sz = 0;
141   }
142   else {
143     int slen = strlen(p);
144     ptr = sfree_alloc(ptr, sz, slen, &sz);
145     len = slen;
146     memcpy(ptr, p, len);
147   }
148   return *this;
149 }
150
151 string &string::operator=(char c)
152 {
153   ptr = sfree_alloc(ptr, sz, 1, &sz);
154   len = 1;
155   *ptr = c;
156   return *this;
157 }
158
159 void string::move(string &s)
160 {
161   sfree(ptr, sz);
162   ptr = s.ptr;
163   len = s.len;
164   sz = s.sz;
165   s.ptr = 0;
166   s.len = 0;
167   s.sz = 0;
168 }
169
170 void string::grow1()
171 {
172   ptr = srealloc(ptr, sz, len, len + 1, &sz);
173 }
174
175 string &string::operator+=(const char *p)
176 {
177   if (p != 0) {
178     int n = strlen(p);
179     int newlen = len + n;
180     if (newlen > sz)
181       ptr = srealloc(ptr, sz, len, newlen, &sz);
182     memcpy(ptr + len, p, n);
183     len = newlen;
184   }
185   return *this;
186 }
187
188 string &string::operator+=(const string &s)
189 {
190   if (s.len != 0) {
191     int newlen = len + s.len;
192     if (newlen > sz)
193       ptr = srealloc(ptr, sz, len, newlen, &sz);
194     memcpy(ptr + len, s.ptr, s.len);
195     len = newlen;
196   }
197   return *this;
198 }
199
200 void string::append(const char *p, int n)
201 {
202   if (n > 0) {
203     int newlen = len + n;
204     if (newlen > sz)
205       ptr = srealloc(ptr, sz, len, newlen, &sz);
206     memcpy(ptr + len, p, n);
207     len = newlen;
208   }
209 }
210
211 string::string(const char *s1, int n1, const char *s2, int n2)
212 {
213   assert(n1 >= 0 && n2 >= 0);
214   len = n1 + n2;
215   if (len == 0) {
216     sz = 0;
217     ptr = 0;
218   }
219   else {
220     ptr = salloc(len, &sz);
221     if (n1 == 0)
222       memcpy(ptr, s2, n2);
223     else {
224       memcpy(ptr, s1, n1);
225       if (n2 != 0)
226         memcpy(ptr + n1, s2, n2);
227     }
228   }
229 }
230
231 int operator<=(const string &s1, const string &s2)
232 {
233   return (s1.len <= s2.len
234           ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
235           : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
236 }
237
238 int operator<(const string &s1, const string &s2)
239 {
240   return (s1.len < s2.len
241           ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
242           : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
243 }
244
245 int operator>=(const string &s1, const string &s2)
246 {
247   return (s1.len >= s2.len
248           ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
249           : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
250 }
251
252 int operator>(const string &s1, const string &s2)
253 {
254   return (s1.len > s2.len
255           ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
256           : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
257 }
258
259 void string::set_length(int i)
260 {
261   assert(i >= 0);
262   if (i > sz)
263     ptr = srealloc(ptr, sz, len, i, &sz);
264   len = i;
265 }
266
267 void string::clear()
268 {
269   len = 0;
270 }
271
272 int string::search(char c) const
273 {
274   char *p = ptr ? (char *)memchr(ptr, c, len) : NULL;
275   return p ? p - ptr : -1;
276 }
277
278 // we silently strip nuls
279
280 char *string::extract() const
281 {
282   char *p = ptr;
283   int n = len;
284   int nnuls = 0;
285   int i;
286   for (i = 0; i < n; i++)
287     if (p[i] == '\0')
288       nnuls++;
289   char *q = new char[n + 1 - nnuls];
290   char *r = q;
291   for (i = 0; i < n; i++)
292     if (p[i] != '\0')
293       *r++ = p[i];
294   *r = '\0';
295   return q;
296 }
297
298 void string::remove_spaces()
299 {
300   int l = len - 1;
301   while (l >= 0 && ptr[l] == ' ')
302     l--;
303   char *p = ptr;
304   if (l > 0)
305     while (*p == ' ') {
306       p++;
307       l--;
308     }
309   if (len - 1 != l) {
310     if (l >= 0) {
311       len = l + 1;
312       char *tmp = new char[len];
313       memcpy(tmp, p, len);
314       a_delete ptr;
315       ptr = tmp;
316     }
317     else {
318       len = 0;
319       if (ptr) {
320         a_delete ptr;
321         ptr = 0;
322       }
323     }
324   }
325 }
326
327 void put_string(const string &s, FILE *fp)
328 {
329   int len = s.length();
330   const char *ptr = s.contents();
331   for (int i = 0; i < len; i++)
332     putc(ptr[i], fp);
333 }
334
335 string as_string(int i)
336 {
337   static char buf[INT_DIGITS + 2];
338   sprintf(buf, "%d", i);
339   return string(buf);
340 }
341