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 342