PageRenderTime 40ms CodeModel.GetById 8ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/groff/src/libs/libgroff/string.cpp

https://bitbucket.org/freebsd/freebsd-head/
C++ | 341 lines | 285 code | 35 blank | 21 comment | 76 complexity | cd07afc6e403811011f70767f23cab00 MD5 | raw file
  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
  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
 10Software Foundation; either version 2, or (at your option) any later
 11version.
 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
 18You should have received a copy of the GNU General Public License along
 19with groff; see the file COPYING.  If not, write to the Free Software
 20Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
 21
 22#include "lib.h"
 23
 24#include "stringclass.h"
 25
 26static char *salloc(int len, int *sizep);
 27static void sfree(char *ptr, int size);
 28static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
 29static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
 30
 31static 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
 41static void sfree(char *ptr, int)
 42{
 43  a_delete ptr;
 44}
 45
 46static 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
 61static 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
 81string::string() : ptr(0), len(0), sz(0)
 82{
 83}
 84
 85string::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
 93string::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
107string::string(char c) : len(1)
108{
109  ptr = salloc(1, &sz);
110  *ptr = c;
111}
112
113string::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  
120string::~string()
121{
122  sfree(ptr, sz);
123}
124
125string &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
134string &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
151string &string::operator=(char c)
152{
153  ptr = sfree_alloc(ptr, sz, 1, &sz);
154  len = 1;
155  *ptr = c;
156  return *this;
157}
158
159void 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
170void string::grow1()
171{
172  ptr = srealloc(ptr, sz, len, len + 1, &sz);
173}
174
175string &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
188string &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
200void 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
211string::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
231int 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
238int 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
245int 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
252int 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
259void 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
267void string::clear()
268{
269  len = 0;
270}
271
272int 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
280char *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
298void 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
327void 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
335string as_string(int i)
336{
337  static char buf[INT_DIGITS + 2];
338  sprintf(buf, "%d", i);
339  return string(buf);
340}
341