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