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