]> cygwin.com Git - cygwin-apps/setup.git/blob - String++.cc
2006-03-14 Dave Korn <dave.korn@artimi.com>
[cygwin-apps/setup.git] / String++.cc
1 /*
2 * Copyright (c) 2002, Robert Collins.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Robert Collins.
13 *
14 */
15
16 // A String class to replace all the char * manipulation.
17
18 #include "String++.h"
19 #include <string.h>
20 #include <ctype.h>
21 #include "io_stream.h"
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25
26 using namespace std;
27
28 // _data
29
30 String::_data::_data(_data const &aData) : count (1), theString (new unsigned char[aData.length]), cstr(0), length (aData.length) {
31 memcpy (theString, aData.theString, aData.length);
32 }
33
34 String::_data::_data(): count (1), theString(new unsigned char[0]), cstr (0), length (0) {}
35 String::_data::_data(size_t aLength): count (1), theString(new unsigned char[aLength]), cstr(0), length (aLength) {}
36 String::_data::~_data ()
37 {
38 if (theString)
39 delete[] theString;
40 if (cstr)
41 delete[] cstr;
42 }
43
44 //String
45
46 String::String (const char *acString) : theData (new _data(acString ? strlen(acString) : 0))
47 {
48 memcpy (theData->theString, acString, theData->length);
49 }
50
51 String::~String ()
52 {
53 if (--theData->count == 0)
54 delete theData;
55 }
56
57 String::String (int const anInt)
58 {
59 ostringstream os;
60 os << anInt;
61 theData = new _data(os.str().size());
62 memcpy (theData->theString, os.str().c_str(), os.str().size());
63 }
64
65 String::String (string const &aString) : theData (new _data (aString.c_str() ? strlen (aString.c_str()) : 0))
66 {
67 memcpy (theData->theString, aString.c_str(), theData->length);
68 }
69
70 // able to cache the result if needed.
71 char const *
72 String::c_str () const
73 {
74 if (theData->length == 0)
75 return NULL;
76 if (theData->cstr)
77 delete[] theData->cstr;
78 theData->cstr = new char[theData->length + 1];
79 theData->cstr[theData->length] = '\0';
80 memcpy (theData->cstr, theData->theString, theData->length);
81 return theData->cstr;
82 }
83
84 // does this character exist in the string?
85 // 0 is false, 1 is the first position...
86 // XXX FIXME: Introduce npos, and change all
87 // if (size) calls to be if (size()==npos)
88 size_t
89 String::find(char aChar) const
90 {
91 for (size_t i=0; i < theData->length; ++i)
92 if (theData->theString[i] == aChar)
93 return i+1;
94 return 0;
95 }
96
97 String
98 String::substr(size_t start, int len) const
99 {
100 // Adapt the C++ string class
101 return string(c_str()).substr(start, len);
102 }
103
104 int
105 String::compare (String const &aString, size_t const count) const
106 {
107 // trivial cases:
108 if (theData == aString.theData)
109 return 0;
110 size_t length = count ? count : theData->length;
111 if (length > theData->length)
112 length = theData->length;
113 if (length > aString.theData->length)
114 length = aString.theData->length;
115 size_t i;
116 for (i=0; i < length ; ++i)
117 if (theData->theString[i] < aString.theData->theString[i])
118 return -1;
119 else if (theData->theString[i] > aString.theData->theString[i])
120 return 1;
121 // equal for length
122 if (i == count && count != 0)
123 return 0;
124 if (theData->length < aString.theData->length)
125 return -1;
126 else if (theData->length > aString.theData->length)
127 return 1;
128 return 0;
129 }
130
131 int
132 String::casecompare (String const &aString, size_t const count) const
133 {
134 // trivial cases:
135 if (theData == aString.theData)
136 return 0;
137 size_t length = count ? count : theData->length;
138 if (length > theData->length)
139 length = theData->length;
140 if (length > aString.theData->length)
141 length = aString.theData->length;
142 size_t i;
143 for (i=0; i < length; ++i)
144 if (toupper(theData->theString[i]) < toupper(aString.theData->theString[i]))
145 return -1;
146 else if (toupper(theData->theString[i]) > toupper(aString.theData->theString[i]))
147 return 1;
148 // equal for length
149 if (i == count && count != 0)
150 return 0;
151 if (theData->length < aString.theData->length)
152 return -1;
153 else if (theData->length > aString.theData->length)
154 return 1;
155 return 0;
156 }
157
158 String &
159 String::operator+= (String const &aString)
160 {
161 if (theData->count > 1)
162 {
163 _data * someData = new _data(*theData);
164 --theData->count;
165 theData = someData;
166 }
167
168 unsigned char *tempString = theData->theString;
169 theData->theString = new unsigned char [theData->length + aString.theData->length];
170 // remove when exceptions are done
171 if (!theData->theString)
172 exit (100);
173 memcpy (theData->theString, tempString, theData->length);
174 delete[] tempString;
175 memcpy (&theData->theString[theData->length], aString.theData->theString, aString.theData->length);
176 theData->length += aString.theData->length;
177 return *this;
178 }
179
180 String
181 String::operator + (String const &aString) const
182 {
183 unsigned char *tempcString = new unsigned char [theData->length + aString.theData->length];
184 // remove when exceptions are done
185 if (!tempcString)
186 exit (100);
187 memcpy (tempcString, theData->theString, theData->length);
188 memcpy (&tempcString[theData->length], aString.theData->theString, aString.theData->length);
189 return absorb (tempcString, theData->length + aString.theData->length);
190 }
191
192 String
193 String::operator + (char const *aString) const
194 {
195 // expensive, but quick to code.
196 return *this + String (aString);
197 }
198
199 bool
200 String::operator == (String const &rhs) const
201 {
202 return compare (rhs) ? false : true;
203 }
204
205 bool
206 String::operator == (char const *rhs) const
207 {
208 return compare (rhs) ? false : true;
209 }
210
211 bool
212 String::operator != (String const &rhs) const
213 {
214 return !(*this == rhs);
215 }
216
217 bool
218 String::operator != (char const *rhs) const
219 {
220 return !(*this == rhs);
221 }
222
223 String
224 String::absorb (unsigned char *aString, size_t aLength)
225 {
226 String theString;
227 theString.theData->theString = aString;
228 theString.theData->length = aLength;
229 return theString;
230 }
231
232 String
233 String::replace (char pattern, char replacement) const
234 {
235 unsigned char *tempcString = new unsigned char [theData->length];
236 // remove when exceptions are done
237 if (!tempcString)
238 exit (100);
239 unsigned char *s = theData->theString;
240 unsigned char *d = tempcString;
241 unsigned char *end = theData->theString + theData->length;
242 for (s = theData->theString; s < end; ++s)
243 {
244 if (*s == pattern)
245 *d++ = replacement;
246 else
247 *d++ = *s;
248 }
249 return absorb (tempcString, theData->length);
250 }
251
252 String
253 String::replace (String const &pattern, String const &replacement) const
254 {
255 int growth = replacement.theData->length - pattern.theData->length + 1;
256 if (growth < 1) growth = 1;
257 unsigned char *tempcString = new unsigned char [theData->length * growth];
258 // remove when exceptions are done
259 if (!tempcString)
260 exit (100);
261 unsigned char *s = theData->theString;
262 unsigned char *d = tempcString;
263 unsigned char *end = theData->theString + theData->length;
264 for (s = theData->theString; s < end - pattern.theData->length; )
265 {
266 if (memcmp(s, pattern.theData->theString, pattern.theData->length) == 0)
267 {
268 s += pattern.theData->length;
269 memcpy(d, replacement.theData->theString, replacement.theData->length);
270 d += replacement.theData->length;
271 }
272 else
273 *d++ = *s++;
274 }
275 for (; s < end; )
276 *d++ = *s++;
277 size_t length = d - tempcString;
278 // Avoid wasting space
279 unsigned char *newCopy = new unsigned char[length];
280 // remove when exceptions are done
281 if (!newCopy)
282 exit (100);
283 memcpy (newCopy, tempcString, length);
284 delete[] tempcString;
285
286 return absorb (newCopy, length);
287 }
288
289 char *
290 new_cstr_char_array (const String &s)
291 {
292 size_t len = s.size();
293 char *buf = new char[len + 1];
294 if (len)
295 memcpy (buf, s.c_str (), len);
296 buf[len] = 0;
297 return buf;
298 }
299
300 /* TODO: research how wide char and unicode interoperate with
301 * C++ streams
302 */
303 ostream &
304 operator << (ostream &os, String const &theString)
305 {
306 os << theString.c_str();
307 return os;
308 }
309
310 String
311 format_1000s(const int num, char sep)
312 {
313 int mult = 1;
314 while (mult * 1000 < num)
315 mult *= 1000;
316 ostringstream os;
317 os << ((num / mult) % 1000);
318 for (mult /= 1000; mult > 0; mult /= 1000)
319 {
320 int triplet = (num / mult) % 1000;
321 os << sep;
322 if (triplet < 100) os << '0';
323 if (triplet < 10) os << '0';
324 os << triplet;
325 }
326 return String(os.str());
327 }
328
This page took 0.052173 seconds and 6 git commands to generate.