1114402Sru// -*- C++ -*- 2114402Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 3114402Sru Free Software Foundation, Inc. 4114402Sru Written by James Clark (jjc@jclark.com) 5114402Sru 6114402SruThis file is part of groff. 7114402Sru 8114402Srugroff is free software; you can redistribute it and/or modify it under 9114402Sruthe terms of the GNU General Public License as published by the Free 10114402SruSoftware Foundation; either version 2, or (at your option) any later 11114402Sruversion. 12114402Sru 13114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 14114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 15114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16114402Srufor more details. 17114402Sru 18114402SruYou should have received a copy of the GNU General Public License along 19114402Sruwith groff; see the file COPYING. If not, write to the Free Software 20151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 21114402Sru 22114402Sru#include "lib.h" 23114402Sru 24114402Sru#include "stringclass.h" 25114402Sru 26114402Srustatic char *salloc(int len, int *sizep); 27114402Srustatic void sfree(char *ptr, int size); 28114402Srustatic char *sfree_alloc(char *ptr, int size, int len, int *sizep); 29114402Srustatic char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep); 30114402Sru 31114402Srustatic char *salloc(int len, int *sizep) 32114402Sru{ 33114402Sru if (len == 0) { 34114402Sru *sizep = 0; 35114402Sru return 0; 36114402Sru } 37114402Sru else 38114402Sru return new char[*sizep = len*2]; 39114402Sru} 40114402Sru 41114402Srustatic void sfree(char *ptr, int) 42114402Sru{ 43114402Sru a_delete ptr; 44114402Sru} 45114402Sru 46114402Srustatic char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep) 47114402Sru{ 48114402Sru if (oldsz >= len) { 49114402Sru *sizep = oldsz; 50114402Sru return ptr; 51114402Sru } 52114402Sru a_delete ptr; 53114402Sru if (len == 0) { 54114402Sru *sizep = 0; 55114402Sru return 0; 56114402Sru } 57114402Sru else 58114402Sru return new char[*sizep = len*2]; 59114402Sru} 60114402Sru 61114402Srustatic char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep) 62114402Sru{ 63114402Sru if (oldsz >= newlen) { 64114402Sru *sizep = oldsz; 65114402Sru return ptr; 66114402Sru } 67114402Sru if (newlen == 0) { 68114402Sru a_delete ptr; 69114402Sru *sizep = 0; 70114402Sru return 0; 71114402Sru } 72114402Sru else { 73114402Sru char *p = new char[*sizep = newlen*2]; 74114402Sru if (oldlen < newlen && oldlen != 0) 75114402Sru memcpy(p, ptr, oldlen); 76114402Sru a_delete ptr; 77114402Sru return p; 78114402Sru } 79114402Sru} 80114402Sru 81114402Srustring::string() : ptr(0), len(0), sz(0) 82114402Sru{ 83114402Sru} 84114402Sru 85114402Srustring::string(const char *p, int n) : len(n) 86114402Sru{ 87114402Sru assert(n >= 0); 88114402Sru ptr = salloc(n, &sz); 89114402Sru if (n != 0) 90114402Sru memcpy(ptr, p, n); 91114402Sru} 92114402Sru 93114402Srustring::string(const char *p) 94114402Sru{ 95114402Sru if (p == 0) { 96114402Sru len = 0; 97114402Sru ptr = 0; 98114402Sru sz = 0; 99114402Sru } 100114402Sru else { 101114402Sru len = strlen(p); 102114402Sru ptr = salloc(len, &sz); 103114402Sru memcpy(ptr, p, len); 104114402Sru } 105114402Sru} 106114402Sru 107114402Srustring::string(char c) : len(1) 108114402Sru{ 109114402Sru ptr = salloc(1, &sz); 110114402Sru *ptr = c; 111114402Sru} 112114402Sru 113114402Srustring::string(const string &s) : len(s.len) 114114402Sru{ 115114402Sru ptr = salloc(len, &sz); 116114402Sru if (len != 0) 117114402Sru memcpy(ptr, s.ptr, len); 118114402Sru} 119114402Sru 120114402Srustring::~string() 121114402Sru{ 122114402Sru sfree(ptr, sz); 123114402Sru} 124114402Sru 125114402Srustring &string::operator=(const string &s) 126114402Sru{ 127114402Sru ptr = sfree_alloc(ptr, sz, s.len, &sz); 128114402Sru len = s.len; 129114402Sru if (len != 0) 130114402Sru memcpy(ptr, s.ptr, len); 131114402Sru return *this; 132114402Sru} 133114402Sru 134114402Srustring &string::operator=(const char *p) 135114402Sru{ 136114402Sru if (p == 0) { 137114402Sru sfree(ptr, len); 138114402Sru len = 0; 139114402Sru ptr = 0; 140114402Sru sz = 0; 141114402Sru } 142114402Sru else { 143114402Sru int slen = strlen(p); 144114402Sru ptr = sfree_alloc(ptr, sz, slen, &sz); 145114402Sru len = slen; 146114402Sru memcpy(ptr, p, len); 147114402Sru } 148114402Sru return *this; 149114402Sru} 150114402Sru 151114402Srustring &string::operator=(char c) 152114402Sru{ 153114402Sru ptr = sfree_alloc(ptr, sz, 1, &sz); 154114402Sru len = 1; 155114402Sru *ptr = c; 156114402Sru return *this; 157114402Sru} 158114402Sru 159114402Sruvoid string::move(string &s) 160114402Sru{ 161114402Sru sfree(ptr, sz); 162114402Sru ptr = s.ptr; 163114402Sru len = s.len; 164114402Sru sz = s.sz; 165114402Sru s.ptr = 0; 166114402Sru s.len = 0; 167114402Sru s.sz = 0; 168114402Sru} 169114402Sru 170114402Sruvoid string::grow1() 171114402Sru{ 172114402Sru ptr = srealloc(ptr, sz, len, len + 1, &sz); 173114402Sru} 174114402Sru 175114402Srustring &string::operator+=(const char *p) 176114402Sru{ 177114402Sru if (p != 0) { 178114402Sru int n = strlen(p); 179114402Sru int newlen = len + n; 180114402Sru if (newlen > sz) 181114402Sru ptr = srealloc(ptr, sz, len, newlen, &sz); 182114402Sru memcpy(ptr + len, p, n); 183114402Sru len = newlen; 184114402Sru } 185114402Sru return *this; 186114402Sru} 187114402Sru 188114402Srustring &string::operator+=(const string &s) 189114402Sru{ 190114402Sru if (s.len != 0) { 191114402Sru int newlen = len + s.len; 192114402Sru if (newlen > sz) 193114402Sru ptr = srealloc(ptr, sz, len, newlen, &sz); 194114402Sru memcpy(ptr + len, s.ptr, s.len); 195114402Sru len = newlen; 196114402Sru } 197114402Sru return *this; 198114402Sru} 199114402Sru 200114402Sruvoid string::append(const char *p, int n) 201114402Sru{ 202114402Sru if (n > 0) { 203114402Sru int newlen = len + n; 204114402Sru if (newlen > sz) 205114402Sru ptr = srealloc(ptr, sz, len, newlen, &sz); 206114402Sru memcpy(ptr + len, p, n); 207114402Sru len = newlen; 208114402Sru } 209114402Sru} 210114402Sru 211114402Srustring::string(const char *s1, int n1, const char *s2, int n2) 212114402Sru{ 213114402Sru assert(n1 >= 0 && n2 >= 0); 214114402Sru len = n1 + n2; 215114402Sru if (len == 0) { 216114402Sru sz = 0; 217114402Sru ptr = 0; 218114402Sru } 219114402Sru else { 220114402Sru ptr = salloc(len, &sz); 221114402Sru if (n1 == 0) 222114402Sru memcpy(ptr, s2, n2); 223114402Sru else { 224114402Sru memcpy(ptr, s1, n1); 225114402Sru if (n2 != 0) 226114402Sru memcpy(ptr + n1, s2, n2); 227114402Sru } 228114402Sru } 229114402Sru} 230114402Sru 231114402Sruint operator<=(const string &s1, const string &s2) 232114402Sru{ 233114402Sru return (s1.len <= s2.len 234114402Sru ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 235114402Sru : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); 236114402Sru} 237114402Sru 238114402Sruint operator<(const string &s1, const string &s2) 239114402Sru{ 240114402Sru return (s1.len < s2.len 241114402Sru ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 242114402Sru : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); 243114402Sru} 244114402Sru 245114402Sruint operator>=(const string &s1, const string &s2) 246114402Sru{ 247114402Sru return (s1.len >= s2.len 248114402Sru ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 249114402Sru : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); 250114402Sru} 251114402Sru 252114402Sruint operator>(const string &s1, const string &s2) 253114402Sru{ 254114402Sru return (s1.len > s2.len 255114402Sru ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 256114402Sru : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); 257114402Sru} 258114402Sru 259114402Sruvoid string::set_length(int i) 260114402Sru{ 261114402Sru assert(i >= 0); 262114402Sru if (i > sz) 263114402Sru ptr = srealloc(ptr, sz, len, i, &sz); 264114402Sru len = i; 265114402Sru} 266114402Sru 267114402Sruvoid string::clear() 268114402Sru{ 269114402Sru len = 0; 270114402Sru} 271114402Sru 272114402Sruint string::search(char c) const 273114402Sru{ 274114402Sru char *p = ptr ? (char *)memchr(ptr, c, len) : NULL; 275114402Sru return p ? p - ptr : -1; 276114402Sru} 277114402Sru 278114402Sru// we silently strip nuls 279114402Sru 280114402Sruchar *string::extract() const 281114402Sru{ 282114402Sru char *p = ptr; 283114402Sru int n = len; 284114402Sru int nnuls = 0; 285114402Sru int i; 286114402Sru for (i = 0; i < n; i++) 287114402Sru if (p[i] == '\0') 288114402Sru nnuls++; 289114402Sru char *q = new char[n + 1 - nnuls]; 290114402Sru char *r = q; 291114402Sru for (i = 0; i < n; i++) 292114402Sru if (p[i] != '\0') 293114402Sru *r++ = p[i]; 294114402Sru *r = '\0'; 295114402Sru return q; 296114402Sru} 297114402Sru 298114402Sruvoid string::remove_spaces() 299114402Sru{ 300114402Sru int l = len - 1; 301114402Sru while (l >= 0 && ptr[l] == ' ') 302114402Sru l--; 303114402Sru char *p = ptr; 304114402Sru if (l > 0) 305114402Sru while (*p == ' ') { 306114402Sru p++; 307114402Sru l--; 308114402Sru } 309114402Sru if (len - 1 != l) { 310114402Sru if (l >= 0) { 311114402Sru len = l + 1; 312114402Sru char *tmp = new char[len]; 313114402Sru memcpy(tmp, p, len); 314114402Sru a_delete ptr; 315114402Sru ptr = tmp; 316114402Sru } 317114402Sru else { 318114402Sru len = 0; 319114402Sru if (ptr) { 320114402Sru a_delete ptr; 321114402Sru ptr = 0; 322114402Sru } 323114402Sru } 324114402Sru } 325114402Sru} 326114402Sru 327114402Sruvoid put_string(const string &s, FILE *fp) 328114402Sru{ 329114402Sru int len = s.length(); 330114402Sru const char *ptr = s.contents(); 331114402Sru for (int i = 0; i < len; i++) 332114402Sru putc(ptr[i], fp); 333114402Sru} 334114402Sru 335114402Srustring as_string(int i) 336114402Sru{ 337114402Sru static char buf[INT_DIGITS + 2]; 338114402Sru sprintf(buf, "%d", i); 339114402Sru return string(buf); 340114402Sru} 341114402Sru 342