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