groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / libs / libgroff / string.cpp
CommitLineData
92d0a6a6 1// -*- C++ -*-
4d3e9548 2/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002, 2009
92d0a6a6
JR
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
5
6This file is part of groff.
7
8groff is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
4d3e9548
JL
10Software Foundation, either version 3 of the License, or
11(at your option) any later version.
92d0a6a6
JR
12
13groff is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
4d3e9548
JL
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
92d0a6a6
JR
20
21#include "lib.h"
22
23#include "stringclass.h"
24
25static char *salloc(int len, int *sizep);
26static void sfree(char *ptr, int size);
27static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
28static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
29
30static 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
40static void sfree(char *ptr, int)
41{
42 a_delete ptr;
43}
44
45static 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
60static 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
80string::string() : ptr(0), len(0), sz(0)
81{
82}
83
84string::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
92string::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
106string::string(char c) : len(1)
107{
108 ptr = salloc(1, &sz);
109 *ptr = c;
110}
111
112string::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
119string::~string()
120{
121 sfree(ptr, sz);
122}
123
124string &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
133string &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
150string &string::operator=(char c)
151{
152 ptr = sfree_alloc(ptr, sz, 1, &sz);
153 len = 1;
154 *ptr = c;
155 return *this;
156}
157
158void 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
169void string::grow1()
170{
171 ptr = srealloc(ptr, sz, len, len + 1, &sz);
172}
173
174string &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
187string &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
199void 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
210string::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
230int 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
237int 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
244int 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
251int 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
258void 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
266void string::clear()
267{
268 len = 0;
269}
270
271int 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
279char *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
297void 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;
4d3e9548 311 char *tmp = new char[sz];
92d0a6a6
JR
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
326void 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
334string as_string(int i)
335{
336 static char buf[INT_DIGITS + 2];
337 sprintf(buf, "%d", i);
338 return string(buf);
339}
340