]> cygwin.com Git - cygwin-apps/setup.git/blob - String++.cc
* site.cc (do_download_site_info_thread): Correct spelling error.
[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 "concat.h"
22 #include "io_stream.h"
23 #include <iostream>
24 #include <strstream>
25 #include <string>
26
27 // _data
28
29 String::_data::_data(_data const &aData) : count (1), theString (new unsigned char[aData.length]), cstr(0), length (aData.length) {
30 memcpy (theString, aData.theString, aData.length);
31 }
32
33 String::_data::_data(): count (1), theString(new unsigned char[0]), cstr (0), length (0) {}
34 String::_data::_data(size_t aLength): count (1), theString(new unsigned char[aLength]), cstr(0), length (aLength) {}
35 String::_data::~_data ()
36 {
37 if (theString)
38 delete[] theString;
39 if (cstr)
40 delete[] cstr;
41 }
42
43 //String
44
45 String::String (const char *acString) : theData (new _data(acString ? strlen(acString) : 0))
46 {
47 memcpy (theData->theString, acString, theData->length);
48 }
49
50 String::~String ()
51 {
52 if (--theData->count == 0)
53 delete theData;
54 }
55
56 String::String (int const anInt)
57 {
58 ostrstream os;
59 os << anInt;
60 theData = new _data(os.pcount());
61 memcpy (theData->theString, os.str(), os.pcount());
62 }
63
64 String::String (string const &aString) : theData (new _data (aString.c_str() ? strlen (aString.c_str()) : 0))
65 {
66 memcpy (theData->theString, aString.c_str(), theData->length);
67 }
68
69 // able to cache the result if needed.
70 char *
71 String::cstr ()
72 {
73 if (theData->length == 0)
74 return NULL;
75 char * tempcStr =new char[theData->length + 1];
76 // remove when exceptions are done
77 if (!tempcStr)
78 exit (100);
79 tempcStr[theData->length] = '\0';
80 memcpy (tempcStr, theData->theString, theData->length);
81 return tempcStr;
82 }
83
84 char *
85 String::cstr () const
86 {
87 if (theData->length == 0)
88 return NULL;
89 char * tempcStr =new char[theData->length + 1];
90 // remove when exceptions are done
91 if (!tempcStr)
92 exit (100);
93 tempcStr[theData->length] = '\0';
94 memcpy (tempcStr, theData->theString, theData->length);
95 return tempcStr;
96 }
97
98 // able to cache the result if needed.
99 char const *
100 String::cstr_oneuse () const
101 {
102 if (theData->length == 0)
103 return NULL;
104 if (theData->cstr)
105 delete[] theData->cstr;
106 theData->cstr = new char[theData->length + 1];
107 theData->cstr[theData->length] = '\0';
108 memcpy (theData->cstr, theData->theString, theData->length);
109 return theData->cstr;
110 }
111
112 // does this character exist in the string?
113 // 0 is false, 1 is the first position...
114 // XXX FIXME: Introduce npos, and change all
115 // if (size) calls to be if (size()==npos)
116 size_t
117 String::find(char aChar) const
118 {
119 for (size_t i=0; i < theData->length; ++i)
120 if (theData->theString[i] == aChar)
121 return i+1;
122 return 0;
123 }
124
125 String
126 String::substr(size_t start, size_t len) const
127 {
128 // Adapt the C++ string class
129 return string(cstr_oneuse()).substr(start, len);
130 }
131
132 int
133 String::compare (String const &aString, size_t const count) const
134 {
135 // trivial cases:
136 if (theData == aString.theData)
137 return 0;
138 size_t length = count ? count : theData->length;
139 if (length > theData->length)
140 length = theData->length;
141 if (length > aString.theData->length)
142 length = aString.theData->length;
143 size_t i;
144 for (i=0; i < length ; ++i)
145 if (theData->theString[i] < aString.theData->theString[i])
146 return -1;
147 else if (theData->theString[i] > aString.theData->theString[i])
148 return 1;
149 // equal for length
150 if (i == count && count != 0)
151 return 0;
152 if (theData->length < aString.theData->length)
153 return -1;
154 else if (theData->length > aString.theData->length)
155 return 1;
156 return 0;
157 }
158
159 int
160 String::casecompare (String const &aString, size_t const count) const
161 {
162 // trivial cases:
163 if (theData == aString.theData)
164 return 0;
165 size_t length = count ? count : theData->length;
166 if (length > theData->length)
167 length = theData->length;
168 if (length > aString.theData->length)
169 length = aString.theData->length;
170 size_t i;
171 for (i=0; i < length; ++i)
172 if (toupper(theData->theString[i]) < toupper(aString.theData->theString[i]))
173 return -1;
174 else if (toupper(theData->theString[i]) > toupper(aString.theData->theString[i]))
175 return 1;
176 // equal for length
177 if (i == count && count != 0)
178 return 0;
179 if (theData->length < aString.theData->length)
180 return -1;
181 else if (theData->length > aString.theData->length)
182 return 1;
183 return 0;
184 }
185
186 String &
187 String::operator+= (String const &aString)
188 {
189 if (theData->count > 1)
190 {
191 _data * someData = new _data(*theData);
192 --theData->count;
193 theData = someData;
194 }
195
196 unsigned char *tempString = theData->theString;
197 theData->theString = new unsigned char [theData->length + aString.theData->length];
198 // remove when exceptions are done
199 if (!theData->theString)
200 exit (100);
201 memcpy (theData->theString, tempString, theData->length);
202 delete[] tempString;
203 memcpy (&theData->theString[theData->length], aString.theData->theString, aString.theData->length);
204 theData->length += aString.theData->length;
205 return *this;
206 }
207
208 String
209 String::operator + (String const &aString) const
210 {
211 unsigned char *tempcString = new unsigned char [theData->length + aString.theData->length];
212 // remove when exceptions are done
213 if (!tempcString)
214 exit (100);
215 memcpy (tempcString, theData->theString, theData->length);
216 memcpy (&tempcString[theData->length], aString.theData->theString, aString.theData->length);
217 return absorb (tempcString, theData->length + aString.theData->length);
218 }
219
220 String
221 String::operator + (char const *aString) const
222 {
223 // expensive, but quick to code.
224 return *this + String (aString);
225 }
226
227 bool
228 String::operator == (String const &rhs) const
229 {
230 return compare (rhs) ? false : true;
231 }
232
233 bool
234 String::operator == (char const *rhs) const
235 {
236 return compare (rhs) ? false : true;
237 }
238
239 String
240 String::absorb (unsigned char *aString, size_t aLength)
241 {
242 String theString;
243 theString.theData->theString = aString;
244 theString.theData->length = aLength;
245 return theString;
246 }
247
248 int
249 String::casecompare (String const lhs, String const rhs)
250 {
251 return lhs.casecompare (rhs);
252 }
253
254 /* TODO: research how wide char and unicode interoperate with
255 * C++ streams
256 */
257 ostream &
258 operator << (ostream &os, String const &theString)
259 {
260 os << theString.cstr_oneuse();
261 return os;
262 }
This page took 0.046434 seconds and 5 git commands to generate.