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