]>
cygwin.com Git - cygwin-apps/setup.git/blob - String++.cc
2 * Copyright (c) 2002, Robert Collins.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by Robert Collins.
16 // A String class to replace all the char * manipulation.
21 #include "io_stream.h"
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
);
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 ()
46 String::String (const char *acString
) : theData (new _data(acString
? strlen(acString
) : 0))
48 memcpy (theData
->theString
, acString
, theData
->length
);
53 if (--theData
->count
== 0)
57 String::String (int const anInt
)
61 theData
= new _data(os
.str().size());
62 memcpy (theData
->theString
, os
.str().c_str(), os
.str().size());
65 String::String (string
const &aString
) : theData (new _data (aString
.c_str() ? strlen (aString
.c_str()) : 0))
67 memcpy (theData
->theString
, aString
.c_str(), theData
->length
);
70 // able to cache the result if needed.
74 if (theData
->length
== 0)
76 char * tempcStr
=new char[theData
->length
+ 1];
77 // remove when exceptions are done
80 tempcStr
[theData
->length
] = '\0';
81 memcpy (tempcStr
, theData
->theString
, theData
->length
);
88 if (theData
->length
== 0)
90 char * tempcStr
=new char[theData
->length
+ 1];
91 // remove when exceptions are done
94 tempcStr
[theData
->length
] = '\0';
95 memcpy (tempcStr
, theData
->theString
, theData
->length
);
99 // able to cache the result if needed.
101 String::cstr_oneuse () const
103 if (theData
->length
== 0)
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
;
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)
118 String::find(char aChar
) const
120 for (size_t i
=0; i
< theData
->length
; ++i
)
121 if (theData
->theString
[i
] == aChar
)
127 String::substr(size_t start
, int len
) const
129 // Adapt the C++ string class
130 return string(cstr_oneuse()).substr(start
, len
);
134 String::compare (String
const &aString
, size_t const count
) const
137 if (theData
== aString
.theData
)
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
;
145 for (i
=0; i
< length
; ++i
)
146 if (theData
->theString
[i
] < aString
.theData
->theString
[i
])
148 else if (theData
->theString
[i
] > aString
.theData
->theString
[i
])
151 if (i
== count
&& count
!= 0)
153 if (theData
->length
< aString
.theData
->length
)
155 else if (theData
->length
> aString
.theData
->length
)
161 String::casecompare (String
const &aString
, size_t const count
) const
164 if (theData
== aString
.theData
)
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
;
172 for (i
=0; i
< length
; ++i
)
173 if (toupper(theData
->theString
[i
]) < toupper(aString
.theData
->theString
[i
]))
175 else if (toupper(theData
->theString
[i
]) > toupper(aString
.theData
->theString
[i
]))
178 if (i
== count
&& count
!= 0)
180 if (theData
->length
< aString
.theData
->length
)
182 else if (theData
->length
> aString
.theData
->length
)
188 String::operator+= (String
const &aString
)
190 if (theData
->count
> 1)
192 _data
* someData
= new _data(*theData
);
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
)
202 memcpy (theData
->theString
, tempString
, theData
->length
);
204 memcpy (&theData
->theString
[theData
->length
], aString
.theData
->theString
, aString
.theData
->length
);
205 theData
->length
+= aString
.theData
->length
;
210 String::operator + (String
const &aString
) const
212 unsigned char *tempcString
= new unsigned char [theData
->length
+ aString
.theData
->length
];
213 // remove when exceptions are done
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
);
222 String::operator + (char const *aString
) const
224 // expensive, but quick to code.
225 return *this + String (aString
);
229 String::operator == (String
const &rhs
) const
231 return compare (rhs
) ? false : true;
235 String::operator == (char const *rhs
) const
237 return compare (rhs
) ? false : true;
241 String::operator != (String
const &rhs
) const
243 return !(*this == rhs
);
247 String::operator != (char const *rhs
) const
249 return !(*this == rhs
);
253 String::absorb (unsigned char *aString
, size_t aLength
)
256 theString
.theData
->theString
= aString
;
257 theString
.theData
->length
= aLength
;
262 String::casecompare (String
const lhs
, String
const rhs
)
264 return lhs
.casecompare (rhs
);
268 * This supports two wildcard characters, '*' and '?', as well as the
269 * '[]'-style character sets ('^' to invert).
270 * Use '\' to escape special characters.
271 * Shamelessly stolen from fileutils-4.1 (adapted for <buf,len> strings).
274 strmatch (const unsigned char *pattern
, size_t plen
,
275 const unsigned char *name
, size_t nlen
)
277 register const unsigned char *pend
= pattern
+ plen
, *nend
= name
+ nlen
;
278 register const unsigned char *p
= pattern
, *n
= name
;
279 register unsigned char c
;
286 case '?': /* A '?' matches exactly one character */
291 case '\\': /* Escape next character */
295 if (n
== nend
|| *n
!= c
)
299 case '*': /* A '*' matches any number of characters */
300 while (p
< pend
&& (c
== '?' || c
== '*'))
305 /* A '?' needs to match one character. */
307 /* There isn't another character; no match. */
310 /* One character of the name is consumed in matching
311 this ? wildcard, so *??? won't match if there are
312 less than three characters. */
321 unsigned char c1
= (c
== '\\') ? *p
: c
;
322 for (--p
; n
!= nend
; ++n
) /* Eat up all chars */
323 if ((c
== '[' || *n
== c1
) && strmatch (p
, pend
-p
, n
, nend
-n
))
328 case '[': /* A '[A-Z]' matches any char between 'A' and 'Z' */
330 /* Nonzero if the sense of the character class is inverted. */
331 register bool invert
;
336 invert
= (*p
== '^');
341 /* [ (unterminated) loses. */
347 register unsigned char cstart
= c
, cend
= c
;
350 /* [ (unterminated) loses. */
355 if (c
== '-' && *p
!= ']')
364 if (*n
>= cstart
&& *n
<= cend
)
375 /* Skip the rest of the [...] that already matched. */
379 /* [... (unterminated) loses. */
390 if (n
== nend
|| c
!= *n
)
404 String::matches (String
const &pattern
) const
406 return strmatch (pattern
.theData
->theString
, pattern
.theData
->length
,
407 theData
->theString
, theData
->length
);
411 String::replace (char pattern
, char replacement
) const
413 unsigned char *tempcString
= new unsigned char [theData
->length
];
414 // remove when exceptions are done
417 unsigned char *s
= theData
->theString
;
418 unsigned char *d
= tempcString
;
419 unsigned char *end
= theData
->theString
+ theData
->length
;
420 for (s
= theData
->theString
; s
< end
; ++s
)
427 return absorb (tempcString
, theData
->length
);
431 String::replace (String
const &pattern
, String
const &replacement
) const
433 int growth
= replacement
.theData
->length
- pattern
.theData
->length
+ 1;
434 if (growth
< 1) growth
= 1;
435 unsigned char *tempcString
= new unsigned char [theData
->length
* growth
];
436 // remove when exceptions are done
439 unsigned char *s
= theData
->theString
;
440 unsigned char *d
= tempcString
;
441 unsigned char *end
= theData
->theString
+ theData
->length
;
442 for (s
= theData
->theString
; s
< end
- pattern
.theData
->length
; )
444 if (memcmp(s
, pattern
.theData
->theString
, pattern
.theData
->length
) == 0)
446 s
+= pattern
.theData
->length
;
447 memcpy(d
, replacement
.theData
->theString
, replacement
.theData
->length
);
448 d
+= replacement
.theData
->length
;
455 size_t length
= d
- tempcString
;
456 // Avoid wasting space
457 unsigned char *newCopy
= new unsigned char[length
];
458 // remove when exceptions are done
461 memcpy (newCopy
, tempcString
, length
);
462 delete[] tempcString
;
464 return absorb (newCopy
, length
);
467 /* TODO: research how wide char and unicode interoperate with
471 operator << (ostream
&os
, String
const &theString
)
473 os
<< theString
.cstr_oneuse();
This page took 0.061498 seconds and 6 git commands to generate.