1 /* $NetBSD: string.cpp,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $ */ 2 3 // -*- C++ -*- 4 /* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 5 Free Software Foundation, Inc. 6 Written by James Clark (jjc@jclark.com) 7 8 This file is part of groff. 9 10 groff is free software; you can redistribute it and/or modify it under 11 the terms of the GNU General Public License as published by the Free 12 Software Foundation; either version 2, or (at your option) any later 13 version. 14 15 groff is distributed in the hope that it will be useful, but WITHOUT ANY 16 WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 for more details. 19 20 You should have received a copy of the GNU General Public License along 21 with groff; see the file COPYING. If not, write to the Free Software 22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 23 24 #include "lib.h" 25 26 #include "stringclass.h" 27 28 static char *salloc(int len, int *sizep); 29 static void sfree(char *ptr, int size); 30 static char *sfree_alloc(char *ptr, int size, int len, int *sizep); 31 static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep); 32 33 static char *salloc(int len, int *sizep) 34 { 35 if (len == 0) { 36 *sizep = 0; 37 return 0; 38 } 39 else 40 return new char[*sizep = len*2]; 41 } 42 43 static void sfree(char *ptr, int) 44 { 45 a_delete ptr; 46 } 47 48 static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep) 49 { 50 if (oldsz >= len) { 51 *sizep = oldsz; 52 return ptr; 53 } 54 a_delete ptr; 55 if (len == 0) { 56 *sizep = 0; 57 return 0; 58 } 59 else 60 return new char[*sizep = len*2]; 61 } 62 63 static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep) 64 { 65 if (oldsz >= newlen) { 66 *sizep = oldsz; 67 return ptr; 68 } 69 if (newlen == 0) { 70 a_delete ptr; 71 *sizep = 0; 72 return 0; 73 } 74 else { 75 char *p = new char[*sizep = newlen*2]; 76 if (oldlen < newlen && oldlen != 0) 77 memcpy(p, ptr, oldlen); 78 a_delete ptr; 79 return p; 80 } 81 } 82 83 string::string() : ptr(0), len(0), sz(0) 84 { 85 } 86 87 string::string(const char *p, int n) : len(n) 88 { 89 assert(n >= 0); 90 ptr = salloc(n, &sz); 91 if (n != 0) 92 memcpy(ptr, p, n); 93 } 94 95 string::string(const char *p) 96 { 97 if (p == 0) { 98 len = 0; 99 ptr = 0; 100 sz = 0; 101 } 102 else { 103 len = strlen(p); 104 ptr = salloc(len, &sz); 105 memcpy(ptr, p, len); 106 } 107 } 108 109 string::string(char c) : len(1) 110 { 111 ptr = salloc(1, &sz); 112 *ptr = c; 113 } 114 115 string::string(const string &s) : len(s.len) 116 { 117 ptr = salloc(len, &sz); 118 if (len != 0) 119 memcpy(ptr, s.ptr, len); 120 } 121 122 string::~string() 123 { 124 sfree(ptr, sz); 125 } 126 127 string &string::operator=(const string &s) 128 { 129 ptr = sfree_alloc(ptr, sz, s.len, &sz); 130 len = s.len; 131 if (len != 0) 132 memcpy(ptr, s.ptr, len); 133 return *this; 134 } 135 136 string &string::operator=(const char *p) 137 { 138 if (p == 0) { 139 sfree(ptr, len); 140 len = 0; 141 ptr = 0; 142 sz = 0; 143 } 144 else { 145 int slen = strlen(p); 146 ptr = sfree_alloc(ptr, sz, slen, &sz); 147 len = slen; 148 memcpy(ptr, p, len); 149 } 150 return *this; 151 } 152 153 string &string::operator=(char c) 154 { 155 ptr = sfree_alloc(ptr, sz, 1, &sz); 156 len = 1; 157 *ptr = c; 158 return *this; 159 } 160 161 void string::move(string &s) 162 { 163 sfree(ptr, sz); 164 ptr = s.ptr; 165 len = s.len; 166 sz = s.sz; 167 s.ptr = 0; 168 s.len = 0; 169 s.sz = 0; 170 } 171 172 void string::grow1() 173 { 174 ptr = srealloc(ptr, sz, len, len + 1, &sz); 175 } 176 177 string &string::operator+=(const char *p) 178 { 179 if (p != 0) { 180 int n = strlen(p); 181 int newlen = len + n; 182 if (newlen > sz) 183 ptr = srealloc(ptr, sz, len, newlen, &sz); 184 memcpy(ptr + len, p, n); 185 len = newlen; 186 } 187 return *this; 188 } 189 190 string &string::operator+=(const string &s) 191 { 192 if (s.len != 0) { 193 int newlen = len + s.len; 194 if (newlen > sz) 195 ptr = srealloc(ptr, sz, len, newlen, &sz); 196 memcpy(ptr + len, s.ptr, s.len); 197 len = newlen; 198 } 199 return *this; 200 } 201 202 void string::append(const char *p, int n) 203 { 204 if (n > 0) { 205 int newlen = len + n; 206 if (newlen > sz) 207 ptr = srealloc(ptr, sz, len, newlen, &sz); 208 memcpy(ptr + len, p, n); 209 len = newlen; 210 } 211 } 212 213 string::string(const char *s1, int n1, const char *s2, int n2) 214 { 215 assert(n1 >= 0 && n2 >= 0); 216 len = n1 + n2; 217 if (len == 0) { 218 sz = 0; 219 ptr = 0; 220 } 221 else { 222 ptr = salloc(len, &sz); 223 if (n1 == 0) 224 memcpy(ptr, s2, n2); 225 else { 226 memcpy(ptr, s1, n1); 227 if (n2 != 0) 228 memcpy(ptr + n1, s2, n2); 229 } 230 } 231 } 232 233 int operator<=(const string &s1, const string &s2) 234 { 235 return (s1.len <= s2.len 236 ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 237 : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); 238 } 239 240 int operator<(const string &s1, const string &s2) 241 { 242 return (s1.len < s2.len 243 ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 244 : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); 245 } 246 247 int operator>=(const string &s1, const string &s2) 248 { 249 return (s1.len >= s2.len 250 ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 251 : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); 252 } 253 254 int operator>(const string &s1, const string &s2) 255 { 256 return (s1.len > s2.len 257 ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 258 : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); 259 } 260 261 void string::set_length(int i) 262 { 263 assert(i >= 0); 264 if (i > sz) 265 ptr = srealloc(ptr, sz, len, i, &sz); 266 len = i; 267 } 268 269 void string::clear() 270 { 271 len = 0; 272 } 273 274 int string::search(char c) const 275 { 276 char *p = ptr ? (char *)memchr(ptr, c, len) : NULL; 277 return p ? p - ptr : -1; 278 } 279 280 // we silently strip nuls 281 282 char *string::extract() const 283 { 284 char *p = ptr; 285 int n = len; 286 int nnuls = 0; 287 int i; 288 for (i = 0; i < n; i++) 289 if (p[i] == '\0') 290 nnuls++; 291 char *q = new char[n + 1 - nnuls]; 292 char *r = q; 293 for (i = 0; i < n; i++) 294 if (p[i] != '\0') 295 *r++ = p[i]; 296 *r = '\0'; 297 return q; 298 } 299 300 void string::remove_spaces() 301 { 302 int l = len - 1; 303 while (l >= 0 && ptr[l] == ' ') 304 l--; 305 char *p = ptr; 306 if (l > 0) 307 while (*p == ' ') { 308 p++; 309 l--; 310 } 311 if (len - 1 != l) { 312 if (l >= 0) { 313 len = l + 1; 314 char *tmp = new char[len]; 315 memcpy(tmp, p, len); 316 a_delete ptr; 317 ptr = tmp; 318 } 319 else { 320 len = 0; 321 if (ptr) { 322 a_delete ptr; 323 ptr = 0; 324 } 325 } 326 } 327 } 328 329 void put_string(const string &s, FILE *fp) 330 { 331 int len = s.length(); 332 const char *ptr = s.contents(); 333 for (int i = 0; i < len; i++) 334 putc(ptr[i], fp); 335 } 336 337 string as_string(int i) 338 { 339 static char buf[INT_DIGITS + 2]; 340 sprintf(buf, "%d", i); 341 return string(buf); 342 } 343 344