]> cygwin.com Git - cygwin-apps/setup.git/blob - String++.cc
This commit was generated by cvs2svn to track changes on a CVS vendor
[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 *
72 String::cstr ()
73 {
74 if (theData->length == 0)
75 return NULL;
76 char * tempcStr =new char[theData->length + 1];
77 // remove when exceptions are done
78 if (!tempcStr)
79 exit (100);
80 tempcStr[theData->length] = '\0';
81 memcpy (tempcStr, theData->theString, theData->length);
82 return tempcStr;
83 }
84
85 char *
86 String::cstr () const
87 {
88 if (theData->length == 0)
89 return NULL;
90 char * tempcStr =new char[theData->length + 1];
91 // remove when exceptions are done
92 if (!tempcStr)
93 exit (100);
94 tempcStr[theData->length] = '\0';
95 memcpy (tempcStr, theData->theString, theData->length);
96 return tempcStr;
97 }
98
99 // able to cache the result if needed.
100 char const *
101 String::cstr_oneuse () const
102 {
103 if (theData->length == 0)
104 return NULL;
105 if (theData->cstr)
106 delete[] theData->cstr;
107 theData->cstr = new char[theData->length + 1];
108 theData->cstr[theData->length] = '\0';
109 memcpy (theData->cstr, theData->theString, theData->length);
110 return theData->cstr;
111 }
112
113 // does this character exist in the string?
114 // 0 is false, 1 is the first position...
115 // XXX FIXME: Introduce npos, and change all
116 // if (size) calls to be if (size()==npos)
117 size_t
118 String::find(char aChar) const
119 {
120 for (size_t i=0; i < theData->length; ++i)
121 if (theData->theString[i] == aChar)
122 return i+1;
123 return 0;
124 }
125
126 String
127 String::substr(size_t start, size_t len) const
128 {
129 // Adapt the C++ string class
130 return string(cstr_oneuse()).substr(start, len);
131 }
132
133 int
134 String::compare (String const &aString, size_t const count) const
135 {
136 // trivial cases:
137 if (theData == aString.theData)
138 return 0;
139 size_t length = count ? count : theData->length;
140 if (length > theData->length)
141 length = theData->length;
142 if (length > aString.theData->length)
143 length = aString.theData->length;
144 size_t i;
145 for (i=0; i < length ; ++i)
146 if (theData->theString[i] < aString.theData->theString[i])
147 return -1;
148 else if (theData->theString[i] > aString.theData->theString[i])
149 return 1;
150 // equal for length
151 if (i == count && count != 0)
152 return 0;
153 if (theData->length < aString.theData->length)
154 return -1;
155 else if (theData->length > aString.theData->length)
156 return 1;
157 return 0;
158 }
159
160 int
161 String::casecompare (String const &aString, size_t const count) const
162 {
163 // trivial cases:
164 if (theData == aString.theData)
165 return 0;
166 size_t length = count ? count : theData->length;
167 if (length > theData->length)
168 length = theData->length;
169 if (length > aString.theData->length)
170 length = aString.theData->length;
171 size_t i;
172 for (i=0; i < length; ++i)
173 if (toupper(theData->theString[i]) < toupper(aString.theData->theString[i]))
174 return -1;
175 else if (toupper(theData->theString[i]) > toupper(aString.theData->theString[i]))
176 return 1;
177 // equal for length
178 if (i == count && count != 0)
179 return 0;
180 if (theData->length < aString.theData->length)
181 return -1;
182 else if (theData->length > aString.theData->length)
183 return 1;
184 return 0;
185 }
186
187 String &
188 String::operator+= (String const &aString)
189 {
190 if (theData->count > 1)
191 {
192 _data * someData = new _data(*theData);
193 --theData->count;
194 theData = someData;
195 }
196
197 unsigned char *tempString = theData->theString;
198 theData->theString = new unsigned char [theData->length + aString.theData->length];
199 // remove when exceptions are done
200 if (!theData->theString)
201 exit (100);
202 memcpy (theData->theString, tempString, theData->length);
203 delete[] tempString;
204 memcpy (&theData->theString[theData->length], aString.theData->theString, aString.theData->length);
205 theData->length += aString.theData->length;
206 return *this;
207 }
208
209 String
210 String::operator + (String const &aString) const
211 {
212 unsigned char *tempcString = new unsigned char [theData->length + aString.theData->length];
213 // remove when exceptions are done
214 if (!tempcString)
215 exit (100);
216 memcpy (tempcString, theData->theString, theData->length);
217 memcpy (&tempcString[theData->length], aString.theData->theString, aString.theData->length);
218 return absorb (tempcString, theData->length + aString.theData->length);
219 }
220
221 String
222 String::operator + (char const *aString) const
223 {
224 // expensive, but quick to code.
225 return *this + String (aString);
226 }
227
228 bool
229 String::operator == (String const &rhs) const
230 {
231 return compare (rhs) ? false : true;
232 }
233
234 bool
235 String::operator == (char const *rhs) const
236 {
237 return compare (rhs) ? false : true;
238 }
239
240 String
241 String::absorb (unsigned char *aString, size_t aLength)
242 {
243 String theString;
244 theString.theData->theString = aString;
245 theString.theData->length = aLength;
246 return theString;
247 }
248
249 int
250 String::casecompare (String const lhs, String const rhs)
251 {
252 return lhs.casecompare (rhs);
253 }
254
255 /* TODO: research how wide char and unicode interoperate with
256 * C++ streams
257 */
258 ostream &
259 operator << (ostream &os, String const &theString)
260 {
261 os << theString.cstr_oneuse();
262 return os;
263 }
This page took 0.051512 seconds and 6 git commands to generate.