]> cygwin.com Git - cygwin-apps/setup.git/blob - String++.cc
2006-04-15 Max Bowsher <maxb1@ukf.net>
[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 #include <algorithm>
26
27 using namespace std;
28
29 // _data
30
31 String::_data::_data(_data const &aData) : count (1), theString (new unsigned char[aData.length]), cstr(0), length (aData.length) {
32 memcpy (theString, aData.theString, aData.length);
33 }
34
35 String::_data::_data(): count (1), theString(new unsigned char[0]), cstr (0), length (0) {}
36 String::_data::_data(size_t aLength): count (1), theString(new unsigned char[aLength]), cstr(0), length (aLength) {}
37 String::_data::~_data ()
38 {
39 if (theString)
40 delete[] theString;
41 if (cstr)
42 delete[] cstr;
43 }
44
45 //String
46
47 String::String (const char *acString) : theData (new _data(acString ? strlen(acString) : 0))
48 {
49 memcpy (theData->theString, acString, theData->length);
50 }
51
52 String::~String ()
53 {
54 if (--theData->count == 0)
55 delete theData;
56 }
57
58 String::String (string const &aString) : theData (new _data (aString.c_str() ? strlen (aString.c_str()) : 0))
59 {
60 memcpy (theData->theString, aString.c_str(), theData->length);
61 }
62
63 // able to cache the result if needed.
64 char const *
65 String::c_str () const
66 {
67 if (theData->length == 0)
68 return NULL;
69 if (theData->cstr)
70 delete[] theData->cstr;
71 theData->cstr = new char[theData->length + 1];
72 theData->cstr[theData->length] = '\0';
73 memcpy (theData->cstr, theData->theString, theData->length);
74 return theData->cstr;
75 }
76
77 String
78 String::substr(size_t start, int len) const
79 {
80 // Adapt the C++ string class
81 return string(c_str()).substr(start, len);
82 }
83
84 int
85 String::compare (String const &aString, size_t const count) const
86 {
87 // trivial cases:
88 if (theData == aString.theData)
89 return 0;
90 size_t length = count ? count : theData->length;
91 if (length > theData->length)
92 length = theData->length;
93 if (length > aString.theData->length)
94 length = aString.theData->length;
95 size_t i;
96 for (i=0; i < length ; ++i)
97 if (theData->theString[i] < aString.theData->theString[i])
98 return -1;
99 else if (theData->theString[i] > aString.theData->theString[i])
100 return 1;
101 // equal for length
102 if (i == count && count != 0)
103 return 0;
104 if (theData->length < aString.theData->length)
105 return -1;
106 else if (theData->length > aString.theData->length)
107 return 1;
108 return 0;
109 }
110
111 int
112 String::casecompare (String const &aString, size_t const count) const
113 {
114 // trivial cases:
115 if (theData == aString.theData)
116 return 0;
117 size_t length = count ? count : theData->length;
118 if (length > theData->length)
119 length = theData->length;
120 if (length > aString.theData->length)
121 length = aString.theData->length;
122 size_t i;
123 for (i=0; i < length; ++i)
124 if (toupper(theData->theString[i]) < toupper(aString.theData->theString[i]))
125 return -1;
126 else if (toupper(theData->theString[i]) > toupper(aString.theData->theString[i]))
127 return 1;
128 // equal for length
129 if (i == count && count != 0)
130 return 0;
131 if (theData->length < aString.theData->length)
132 return -1;
133 else if (theData->length > aString.theData->length)
134 return 1;
135 return 0;
136 }
137
138 String &
139 String::operator+= (String const &aString)
140 {
141 if (theData->count > 1)
142 {
143 _data * someData = new _data(*theData);
144 --theData->count;
145 theData = someData;
146 }
147
148 unsigned char *tempString = theData->theString;
149 theData->theString = new unsigned char [theData->length + aString.theData->length];
150 // remove when exceptions are done
151 if (!theData->theString)
152 exit (100);
153 memcpy (theData->theString, tempString, theData->length);
154 delete[] tempString;
155 memcpy (&theData->theString[theData->length], aString.theData->theString, aString.theData->length);
156 theData->length += aString.theData->length;
157 return *this;
158 }
159
160 String
161 String::operator + (String const &aString) const
162 {
163 unsigned char *tempcString = new unsigned char [theData->length + aString.theData->length];
164 // remove when exceptions are done
165 if (!tempcString)
166 exit (100);
167 memcpy (tempcString, theData->theString, theData->length);
168 memcpy (&tempcString[theData->length], aString.theData->theString, aString.theData->length);
169 return absorb (tempcString, theData->length + aString.theData->length);
170 }
171
172 String
173 String::operator + (char const *aString) const
174 {
175 // expensive, but quick to code.
176 return *this + String (aString);
177 }
178
179 bool
180 String::operator == (String const &rhs) const
181 {
182 return compare (rhs) ? false : true;
183 }
184
185 bool
186 String::operator == (char const *rhs) const
187 {
188 return compare (rhs) ? false : true;
189 }
190
191 bool
192 String::operator != (String const &rhs) const
193 {
194 return !(*this == rhs);
195 }
196
197 bool
198 String::operator != (char const *rhs) const
199 {
200 return !(*this == rhs);
201 }
202
203 String
204 String::absorb (unsigned char *aString, size_t aLength)
205 {
206 String theString;
207 theString.theData->theString = aString;
208 theString.theData->length = aLength;
209 return theString;
210 }
211
212 char *
213 new_cstr_char_array (const std::string &s)
214 {
215 size_t len = s.size();
216 char *buf = new char[len + 1];
217 if (len)
218 memcpy (buf, s.c_str (), len);
219 buf[len] = 0;
220 return buf;
221 }
222
223 /* TODO: research how wide char and unicode interoperate with
224 * C++ streams
225 */
226 ostream &
227 operator << (ostream &os, String const &theString)
228 {
229 os << theString.c_str();
230 return os;
231 }
232
233 std::string
234 format_1000s (int num, char sep)
235 {
236 int mult = 1;
237 while (mult * 1000 < num)
238 mult *= 1000;
239 ostringstream os;
240 os << ((num / mult) % 1000);
241 for (mult /= 1000; mult > 0; mult /= 1000)
242 {
243 int triplet = (num / mult) % 1000;
244 os << sep;
245 if (triplet < 100) os << '0';
246 if (triplet < 10) os << '0';
247 os << triplet;
248 }
249 return os.str();
250 }
251
252 std::string
253 stringify(int num)
254 {
255 std::ostringstream os;
256 os << num;
257 return os.str();
258 }
259
260 int
261 casecompare (const std::string& a, const std::string& b, size_t limit)
262 {
263 size_t length_to_check = std::min(a.length(), b.length());
264 if (limit && length_to_check > limit)
265 length_to_check = limit;
266
267 size_t i;
268 for (i = 0; i < length_to_check; ++i)
269 if (toupper(a[i]) < toupper(b[i]))
270 return -1;
271 else if (toupper(a[i]) > toupper(b[i]))
272 return 1;
273
274 // Hit the comparison limit without finding a difference
275 if (limit && i == limit)
276 return 0;
277
278 if (a.length() < b.length())
279 return -1;
280 else if (a.length() > b.length())
281 return 1;
282
283 return 0;
284 }
285
286 std::string
287 replace(const std::string& haystack, const std::string& needle,
288 const std::string& replacement)
289 {
290 std::string rv(haystack);
291 size_t n_len = needle.length(), r_len = replacement.length(),
292 search_start = 0;
293
294 while (true)
295 {
296 size_t pos = rv.find(needle, search_start);
297 if (pos == std::string::npos)
298 return rv;
299 rv.replace(pos, n_len, replacement);
300 search_start = pos + r_len;
301 }
302 }
This page took 0.050776 seconds and 6 git commands to generate.