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