Compilation fixes for gcc 3.1, MSVC 6.0 & 7.0
[dyninst.git] / common / src / String.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: String.C,v 1.19 2002/06/17 17:04:03 gaburici Exp $
43
44 #include <assert.h>
45 #include "common/h/headers.h"
46
47 #if !(defined i386_unknown_nt4_0) && !(defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
48 #include <regex.h>
49 #endif
50
51 #include "common/h/String.h"
52
53 // Declare static member vrbles:
54 string *string::nilptr;
55 int string_counter::count;
56
57 string_ll::string_ll()
58     : str_(0), len_(0), key_(0) {
59 }
60
61 string_ll::string_ll(const char* str)
62     : str_(STRDUP(str)), len_(STRLEN(str)) {
63    key_ = 0; // lazy key define
64 }
65
66 string_ll::string_ll(const char *str, unsigned len) {
67    // same as above constructor, but copies less than the entire string.
68    // You specifiy the # of chars to copy.
69    if (len > strlen(str))
70       // just copy the whole string
71       len = strlen(str);
72
73    len_ = len;
74    str_ = new char[len+1];
75    (void) P_memcpy(str_, str, len);
76    str_[len] = '\0';
77
78    key_ = 0; // lazy key define
79 }
80
81 string_ll::string_ll(const string_ll& s)
82     : str_(STRDUP(s.str_)), len_(s.len_), key_(s.key_) {
83    // lazy key define iff "s" lazy key define (as it should be)
84 }
85
86 string_ll::string_ll(const char c) {
87   char tempBuffer[2]; //only need space for one character and '\0'
88   sprintf(tempBuffer, "%c", c);
89
90   str_ = STRDUP(tempBuffer);
91   len_ = STRLEN(tempBuffer);
92
93   key_ = 0; // lazy key define
94 }
95
96 string_ll::string_ll(int i) {
97    char tempBuffer[40];
98    sprintf(tempBuffer, "%d", i);
99
100    str_ = STRDUP(tempBuffer);
101    len_ = STRLEN(tempBuffer);
102
103    key_ = 0; // lazy key define
104 }
105
106 string_ll::string_ll(long l) {
107    char tempBuffer[40];
108    sprintf(tempBuffer, "%ld", l);
109
110    str_ = STRDUP(tempBuffer);
111    len_ = STRLEN(tempBuffer);
112
113    key_ = 0; // lazy key define
114 }
115
116 string_ll::string_ll(unsigned u) {
117    char tempBuffer[40];
118    sprintf(tempBuffer, "%u", u);
119
120    str_ = STRDUP(tempBuffer);
121    len_ = STRLEN(tempBuffer);
122
123    key_ = 0; // lazy key define
124 }
125
126 string_ll::string_ll(unsigned long ul) {
127    char tempBuffer[40];
128    sprintf(tempBuffer, "%lu", ul);
129
130    str_ = STRDUP(tempBuffer);
131    len_ = STRLEN(tempBuffer);
132
133    key_ = 0; // lazy key define
134 }
135
136 string_ll::string_ll(float f) {
137    char tempBuffer[40];
138    sprintf(tempBuffer, "%f", f);
139
140    str_ = STRDUP(tempBuffer);
141    len_ = STRLEN(tempBuffer);
142
143    key_ = 0; // lazy key define
144 }
145
146 string_ll::string_ll(double d) {
147    char tempBuffer[40];
148    sprintf(tempBuffer, "%g", d);
149
150    str_ = STRDUP(tempBuffer);
151    len_ = STRLEN(tempBuffer);
152
153    key_ = 0; // lazy key define
154 }
155
156 string_ll::~string_ll() {
157     delete [] str_; str_ = 0;
158 }
159
160 string_ll&
161 string_ll::operator=(const char* str) {
162     if (str_ == str) {
163         return *this;
164     }
165
166     delete [] str_; str_ = 0;
167
168     str_ = STRDUP(str);
169     len_ = STRLEN(str);
170
171     key_ = 0; // lazy key define
172
173     return *this;
174 }
175
176 string_ll&
177 string_ll::operator=(const string_ll& s) {
178     if (this == &s) {
179         return *this;
180     }
181
182     delete [] str_; str_ = 0;
183
184     str_ = STRDUP(s.str_);
185     len_ = s.len_;
186     key_ = s.key_; // lazy key define iff "s" lazy key define, which is correct
187
188     return *this;
189 }
190
191 string_ll&
192 string_ll::operator+=(const string_ll& s) {
193     unsigned nlen = len_ + s.len_;
194     char*    ptr  = new char[nlen+1];
195     assert(ptr);
196
197     memcpy(ptr, str_, len_);
198     memcpy(&ptr[len_], s.str_, s.len_);
199     ptr[nlen] = '\0';
200
201     delete[] str_; str_ = 0;
202     str_ = ptr;
203     len_ = nlen;
204
205     key_ = 0;
206
207     return *this;
208 }
209
210 string_ll&
211 string_ll::operator+=(const char *ptr) {
212    // this routine exists as an optimization, sometimes avoiding the need to create
213    // a temporary string, which can be expensive.
214
215    const int ptr_len = P_strlen(ptr);
216    const unsigned nlen = len_ + ptr_len;
217    char *new_ptr = new char[nlen+1];
218    assert(new_ptr);
219
220    memcpy(new_ptr, str_, len_);
221    memcpy(&new_ptr[len_], ptr, ptr_len);
222    new_ptr[nlen] = '\0';
223   
224    delete [] str_;
225    str_ = new_ptr;
226    len_ = nlen;
227
228    key_ = 0; // lazy key define
229
230    return *this;
231 }
232
233 string_ll
234 string_ll::operator+(const string_ll& s) const {
235     string_ll ret = *this;
236     return (ret += s);
237 }
238
239 string_ll
240 string_ll::operator+(const char *ptr) const {
241    string_ll ret = *this;
242    return (ret += ptr);
243 }
244
245 bool
246 string_ll::operator==(const string_ll& s) const {
247    if (&s == this) return true;
248
249    updateKeyIfNeeded(); s.updateKeyIfNeeded();
250    if (key_ != s.key_) return false;
251    if (len_ != s.len_) return false;
252    return STREQ(str_, s.str_);
253 }
254
255 bool
256 string_ll::operator!=(const string_ll& s) const {
257    if (&s == this) return false;
258    if (len_ != s.len_) return true;
259    return STRNE(str_, s.str_);
260 }
261
262 bool
263 string_ll::operator<=(const string_ll& s) const {
264     return ((&s == this) || STRLE(str_, s.str_));
265 }
266
267 bool
268 string_ll::operator>=(const string_ll& s) const {
269     return ((&s == this) || STRGE(str_, s.str_));
270 }
271
272 bool
273 string_ll::prefix_of(const char* s, unsigned sl) const {
274     return ((len_ > sl) ? false : STREQN(str_, s, len_));
275 }
276
277 bool
278 string_ll::prefix_of(const string_ll& s) const {
279     return ((&s == this) || prefix_of(s.str_, s.len_));
280 }
281
282 bool
283 string_ll::prefixed_by(const char* s, unsigned sl) const {
284     return ((sl > len_) ? false : STREQN(str_, s, sl));
285 }
286
287 bool
288 string_ll::prefixed_by(const string_ll& s) const {
289     return ((&s == this) || prefixed_by(s.str_, s.len_));
290 }
291
292 bool
293 string_ll::suffix_of(const char* s, unsigned sl) const {
294     return ((len_ > sl) ? false : STREQN(str_, s + strlen( s ) - len_, len_));
295 }
296
297 bool
298 string_ll::suffix_of(const string_ll& s) const {
299     return ((&s == this) || suffix_of(s.str_, s.len_));
300 }
301
302 bool
303 string_ll::suffixed_by(const char* s, unsigned sl) const {
304     return ((sl > len_) ? false : STREQN(str_ + len_ - sl, s, sl));
305 }
306
307 bool
308 string_ll::suffixed_by(const string_ll& s) const {
309     return ((&s == this) || suffixed_by(s.str_, s.len_));
310 }
311
312
313 unsigned
314 string_ll::find (const char *s, unsigned sl) const {
315   for(int i=0; i<=(len_-sl); i++) {
316     if( STREQN(str_ + i, s, sl) ) return i;
317   }
318   return len_;
319 }
320
321 unsigned 
322 string_ll::find (const string_ll &s) const{
323   return ((&s == this) ? 0 : find(s.str_, s.len_)); 
324 }
325
326 unsigned
327 string_ll::hashs(const char* str) {
328     if (!str)
329        return 1; // 0 is reserved for unhashed key
330
331     unsigned h = 5381;
332     while (*str) {
333         h = (h << 5) + h + (unsigned) (*str);
334         str++;
335     }
336     return h==0 ? 1 : h; // 0 is reserved for unhashed key
337 }
338
339 unsigned
340 string_ll::STRLEN(const char* str) {
341     return ((str)?(P_strlen(str)):(0));
342 }
343
344 char*
345 string_ll::STRDUP(const char* str) {
346     if (!str) {
347         return 0;
348     }
349
350     unsigned size = P_strlen(str)+1;
351     char*    p    = new char[size];
352
353     (void) P_memcpy(p, str, size);
354     return p;
355 }
356
357 bool
358 string_ll::STREQ(const char* s1, const char* s2) {
359     return ((s1&&s2)?(P_strcmp(s1,s2)==0):(!(s1||s2)));
360 }
361
362 bool
363 string_ll::STREQN(const char* s1, const char* s2, unsigned len) {
364     return ((s1&&s2)?(P_strncmp(s1,s2,len)==0):(!(s1||s2)));
365 }
366
367 bool
368 string_ll::STRNE(const char* s1, const char* s2) {
369     return ((s1&&s2)?(P_strcmp(s1,s2)!=0):(false));
370 }
371
372 bool
373 string_ll::STRLT(const char* s1, const char* s2) {
374     return ((s1&&s2)?(P_strcmp(s1,s2)<0):(false));
375 }
376
377 bool
378 string_ll::STRLE(const char* s1, const char* s2) {
379     return ((s1&&s2)?(P_strcmp(s1,s2)<=0):(!(s1||s2)));
380 }
381
382 bool
383 string_ll::STRGT(const char* s1, const char* s2) {
384     return ((s1&&s2)?(P_strcmp(s1,s2)>0):(false));
385 }
386
387 bool
388 string_ll::STRGE(const char* s1, const char* s2) {
389     return ((s1&&s2)?(P_strcmp(s1,s2)>=0):(!(s1||s2)));
390 }
391
392 const char *
393 string_ll::STRCHR(const char* s, char c) {
394     return (s?(P_strchr(s,c)):(NULL));
395 }
396
397 string_ll
398 string_ll::substr(unsigned pos, unsigned len) const {
399         if( pos >= len_ )
400                 return string_ll( "" );
401         else
402                 return string_ll( str_ + pos, len );
403 }
404
405 bool
406 string_ll::wildcardEquiv( const string_ll &them, bool checkCase ) const {
407         if( *this == them )
408                 return true;
409         else
410                 return pattern_match( str_, them.str_, checkCase );
411 }
412
413
414 // This function will match string s against pattern p.
415 // Asterisks match 0 or more wild characters, and a question
416 // mark matches exactly one wild character.  In other words,
417 // the asterisk is the equivalent of the regex ".*" and the
418 // question mark is the equivalent of "."
419
420 bool
421 string_ll::pattern_match( const char *p, const char *s, bool checkCase ) {
422         //const char *p = ptrn;
423         //char *s = str;
424
425         while ( true ) {
426                 // If at the end of the pattern, it matches if also at the end of the string
427                 if( *p == '\0' )
428                         return ( *s == '\0' );
429
430                 // Process a '*'
431                 if( *p == MULTIPLE_WILDCARD_CHAR ) {
432                         ++p;
433                         
434                         // If at the end of the pattern, it matches
435                         if( *p == '\0' )
436                                 return true;
437
438                         // Try to match the remaining pattern for each remaining substring of s
439                         for(; *s != '\0'; ++s )
440                                 if( pattern_match( p, s, checkCase ) )
441                                         return true;
442                         // Failed
443                         return false;
444                 }
445
446                 // If at the end of the string (and at this point, not of the pattern), it fails
447                 if( *s == '\0' )
448                         return false;
449
450                 // Check if this character matches
451                 bool matchChar = false;
452                 if( *p == WILDCARD_CHAR || *p == *s )
453                         matchChar = true;
454                 else if( !checkCase ) {
455                         if( *p >= 'A' && *p <= 'Z' && *s == ( *p + ( 'a' - 'A' ) ) )
456                                 matchChar = true;
457                         else if( *p >= 'a' && *p <= 'z' && *s == ( *p - ( 'a' - 'A' ) ) )
458                                 matchChar = true;
459                 }
460
461                 if( matchChar ) {
462                         ++p;
463                         ++s;
464                         continue;
465                 }
466
467                 // Did not match
468                 return false;
469         }
470 }
471
472
473 // Use POSIX regular expression pattern matching to check if string s matches
474 // the pattern in this string
475 bool
476 string_ll::regexEquiv( const char *s, bool checkCase ) const {
477 // Would this work under NT?  I don't know.
478 #if !(defined i386_unknown_nt4_0) && !(defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
479         regex_t r;
480         int err;
481         bool match = false;
482         int cflags = REG_NOSUB;
483         if( !checkCase )
484                 cflags |= REG_ICASE;
485
486         // Regular expressions must be compiled first, see 'man regexec'
487         err = regcomp( &r, str_, cflags );
488
489         if( err == 0 ) {
490                 // Now we can check for a match
491                 err = regexec( &r, s, 0, NULL, 0 );
492                 if( err == 0 )
493                         match = true;
494         }
495
496         // Deal with errors
497         if( err != 0 && err != REG_NOMATCH ) {
498                 char errbuf[80];
499                 regerror( err, &r, errbuf, 80 );
500                 cerr << "string_ll::regexEquiv -- " << errbuf << endl;
501         }
502
503         // Free the pattern buffer
504         regfree( &r );
505         return match;
506 #else
507         return false;
508 #endif
509 }
510
511
512 ostream& operator<< (ostream &os, const string_ll &s) {
513    return os << s.str_;
514 }
515
516 debug_ostream& operator<< (debug_ostream &os, const string_ll &s) {
517    return os << s.str_;
518 }
519
520 string operator+(const char *ptr, const string &str) {
521    // a syntactical convenience.
522    // This fn could probably be optimized quite a bit (pre-allocate exactly
523    // the # of bytes that are needed)
524    string result(ptr);
525    result += str;
526    return result;
527 }
528
529 void string::initialize_static_stuff() {
530    // should only get called once:
531    // VG(06/15/02): this assertion doesn't hold w/VC.NET because nilptr is never initialized!
532    //assert(nilptr == NULL);
533
534    nilptr = new string((char*)NULL);
535       // the typecast is essential, lest NULL be interpreted
536       // as the integer 0 instead of the pointer 0!
537 }
538
539 void string::free_static_stuff() {
540    delete nilptr;
541    nilptr = NULL;
542 }
543
544
545