These are the windows fixes that I previously alluded to, combined with
[dyninst.git] / common / h / String.h
1 /*
2  * Copyright (c) 1996-2007 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 /************************************************************************
33  * String.h: a simple character string class.
34  * $Id: String.h,v 1.34 2008/05/09 00:25:37 jaw Exp $
35 ************************************************************************/
36
37 #if !defined(_String_h_)
38 #define _String_h_
39
40 #if defined(__XLC__) || defined(__xlC__)
41 #pragma implementation ("../src/String.C")
42 #endif
43
44
45 /************************************************************************
46  * header files.
47 ************************************************************************/
48
49 #if 0
50 #include "common/h/debugOstream.h"
51 #endif
52 #include "common/h/headers.h"
53
54 /************************************************************************
55  * class string
56 ************************************************************************/
57
58 const char WILDCARD_CHAR = '?';
59 const char MULTIPLE_WILDCARD_CHAR = '*';
60
61 class string_ll {
62 public:
63     string_ll ();
64     string_ll (const char *);
65     string_ll (const char *, unsigned n); // just copy the first n chars
66     string_ll (const string_ll &);
67     ~string_ll ();
68
69     // conversions to string_ll from standard types
70     string_ll (char);
71     string_ll (int);
72     string_ll (unsigned);
73     string_ll (long);
74     string_ll (unsigned long);
75     string_ll (float);
76     string_ll (double);
77
78     string_ll& operator= (const char *);
79     string_ll& operator= (const string_ll &);
80     string_ll& operator+= (const string_ll &);
81     string_ll& operator+= (const char *);
82     string_ll  operator+ (const string_ll &) const;
83     string_ll  operator+ (const char *) const;
84
85     char operator[] (unsigned pos) const {return str_[pos];}
86
87     bool operator== (const string_ll &) const;
88     bool operator== (const char *ptr) const {
89       // This routine exists as an optimization; doesn't need to create 
90       // a temporary instance of "string" for "ptr"; hence, doesn't call
91       // string::pdstring(char *) which calls new[].
92       return STREQ(ptr, str_);
93     }
94     bool operator!= (const string_ll &) const;
95     bool operator<  (const string_ll &s) const {return STRLT(str_, s.str_);}
96     bool operator<= (const string_ll &) const;
97     bool operator>  (const string_ll &s) const {return STRGT(str_, s.str_);}
98     bool operator>= (const string_ll &) const;
99
100     bool prefix_of (const char *, unsigned) const;
101     bool prefix_of (const char *s)          const {return prefix_of(s, STRLEN(s));};
102     bool prefix_of (const string_ll &)      const;
103
104     bool prefixed_by (const char *, unsigned) const;
105     bool prefixed_by (const char *s)          const {return prefixed_by(s, STRLEN(s));};
106     bool prefixed_by (const string_ll &)      const;
107
108     bool suffix_of (const char *, unsigned) const;
109     bool suffix_of (const char *s)          const {return suffix_of(s, STRLEN(s));};
110     bool suffix_of (const string_ll &)      const;
111
112     bool suffixed_by (const char *, unsigned) const;
113     bool suffixed_by (const char *s)          const {return suffixed_by(s, STRLEN(s));};
114     bool suffixed_by (const string_ll &)      const;
115
116     unsigned find (const char *, unsigned) const;
117     unsigned find (const char *s)          const {return find(s, STRLEN(s));};
118     unsigned find (const string_ll &)      const;
119
120     string_ll substr (unsigned, unsigned) const;
121
122     bool wildcardEquiv( const string_ll &, bool ) const;
123         bool wildcardEquiv( const char *ptr, bool checkCase ) const {
124                 return pattern_match( str_, ptr, checkCase );
125         }
126
127     bool regexEquiv( const string_ll &them, bool checkCase ) const {
128                 return regexEquiv( them.str_, checkCase );
129         }
130         bool regexEquiv( const char *, bool ) const;
131
132     const char*       c_str() const {return str_;}
133     unsigned         length() const {return len_;}
134
135     //friend ostream& operator<< (ostream &os, const string_ll &s);
136     //friend debug_ostream& operator<< (debug_ostream &os, const string_ll &s);
137 //    friend string_ll operator+(const char *, const string_ll &);
138 //       // a syntactical convenience
139
140     static unsigned       hash (const string_ll &s) {
141        s.updateKeyIfNeeded(); return s.key_;
142     }
143
144 private:
145     void updateKeyIfNeeded() const {if (0==key_) updateKey(); }
146     void updateKey() const {
147        key_ = hashs(str_); // properly checks for NULL; properly won't return 0
148     }
149
150     static unsigned      hashs (const char *);
151
152     static unsigned     STRLEN (const char *);
153     static char*        STRDUP (const char *);
154
155     static bool          STREQ (const char *, const char *);
156     static bool         STREQN (const char *, const char *, unsigned);
157     static bool          STRNE (const char *, const char *);
158     static bool          STRLT (const char *, const char *);
159     static bool          STRLE (const char *, const char *);
160     static bool          STRGT (const char *, const char *);
161     static bool          STRGE (const char *, const char *);
162     static const char*  STRCHR (const char *, char);
163
164     static bool  pattern_match ( const char *, const char *, bool );
165
166     char*    str_;
167     unsigned len_;
168
169     mutable unsigned key_;
170 };
171
172 #include "common/h/refCounter.h"
173
174 #define MAGIC_NILPTR_FLAG 1234567
175
176 class pdstring {
177    friend class string_counter;
178  private:
179    refCounter<string_ll> data;
180
181    static pdstring *nilptr;
182    static long nilptr_initialized;
183
184    static void initialize_static_stuff();
185    static void free_static_stuff();
186
187  public:
188    inline pdstring * getNilptr() {
189            // Lam(01/28/08): static members are not always initialized when
190            // nilptr is needed, so we use a magic number to ensure that the
191            // static initialization flag is not zero or some random
192            // (uninitialized) value
193            if (nilptr_initialized != MAGIC_NILPTR_FLAG) {
194                    initialize_static_stuff();
195            }
196            return nilptr;
197    }
198
199    // The second of the constructors below should be faster, but it means
200    // we must rely on nil.data being initialized before any global string
201    // objects (or static class members) created with this constructor.
202 //   pdstring() : data(string_ll()) {};
203    pdstring() : data(getNilptr()->data) {} // should be more efficient than above
204    pdstring(const char *str) : data(string_ll(str)) {}
205    pdstring(const char *str, unsigned n) : data(string_ll(str,n)) {}
206    pdstring(const pdstring& src) : data(src.data) {}
207    ~pdstring() {}
208
209    // don't allow implicit conversion to pdstring from standard types;
210    // forces correct usage & removes ambiguities
211    explicit pdstring(char c) : data(string_ll(c)) {}
212    explicit pdstring(int i) : data(string_ll(i)) {}
213    explicit pdstring(long l) : data(string_ll(l)) {}
214    explicit pdstring(unsigned u) : data(string_ll(u)) {}
215    explicit pdstring(unsigned long ul) : data(string_ll(ul)) {}
216    explicit pdstring(float f) : data(string_ll(f)) {}
217    explicit pdstring(double d) : data(string_ll(d)) {}
218
219    char operator[] (unsigned pos) const {
220            return data.getData()[ pos ];
221    }
222
223    pdstring& operator=(const char *str) {
224       string_ll new_str_ll(str);
225       refCounter<string_ll> newRefCtr(new_str_ll);
226       
227       data = newRefCtr;
228       return *this;
229    }
230    pdstring& operator=(const pdstring &src) {
231       data = src.data;
232       return *this;
233    }
234
235    pdstring& operator+=(const pdstring &addme) {
236       // see comment in next routine as to why we don't modify in-place.
237       string_ll newstr = data.getData() + addme.data.getData();
238       data = newstr;
239       return *this;
240    }
241    pdstring& operator+=(const char *str) {
242       // You might wonder why we can't just do:
243       // data.getData() += str; return *this;
244       // The answer is that that would make an in-place modification,
245       // thus messing up any others who might be attached to the same object as us.
246       // There are two alternative solutions: use prepareToModifyInPlace() followed
247       // by the above sequence, or what we use below.  In general, if the in-place
248       // modification doesn't require making an entirely new low-level object
249       // (the below example does require that), then it's better to use prepareToModifyInPlace()
250       // instead of operator=().
251       
252       string_ll newstr = data.getData() + str;
253       data = newstr;
254       return *this;
255    }
256
257    pdstring operator+(const pdstring &src) const {
258       pdstring result = *this;
259       return (result += src);
260    }
261    pdstring operator+(const char *src) const {
262       pdstring result = *this;
263       return (result += src);
264    }
265    friend pdstring operator+(const char *src, const pdstring &str);
266       // a syntactical convenience
267
268    bool operator==(const pdstring &src) const {
269       const string_ll &me = data.getData();
270       const string_ll &them = src.data.getData();
271       return (me == them);
272    }
273    bool operator==(const char *ptr) const {
274       const string_ll &me = data.getData();
275       return (me == ptr);
276    }
277    bool operator!=(const pdstring &src) const {
278       const string_ll &me = data.getData();
279       const string_ll &them = src.data.getData();
280       return (me != them);
281    }
282    bool operator<(const pdstring &src) const {
283       const string_ll &me = data.getData();
284       const string_ll &them = src.data.getData();
285       return (me < them);
286    }
287    bool operator<=(const pdstring &src) const {
288       const string_ll &me = data.getData();
289       const string_ll &them = src.data.getData();
290       return (me <= them);
291    }
292    bool operator>(const pdstring &src) const {
293       const string_ll &me = data.getData();
294       const string_ll &them = src.data.getData();
295       return (me > them);
296    }
297    bool operator>=(const pdstring &src) const {
298       const string_ll &me = data.getData();
299       const string_ll &them = src.data.getData();
300       return (me >= them);
301    }
302    bool prefix_of(const char *str, unsigned n) const {
303       const string_ll &me = data.getData();
304       return (me.prefix_of(str, n));
305    }
306    bool prefix_of(const char *str) const {
307       const string_ll &me = data.getData();
308       return (me.prefix_of(str));
309    }
310    bool prefix_of(const pdstring &src) const {
311       const string_ll &me = data.getData();
312       const string_ll &them = src.data.getData();
313       return (me.prefix_of(them));
314    }
315
316    bool prefixed_by(const char *str, unsigned n) const {
317       const string_ll &me = data.getData();
318       return (me.prefixed_by(str, n));
319    }
320    bool prefixed_by(const char *str) const {
321       const string_ll &me = data.getData();
322       return (me.prefixed_by(str));
323    }
324    bool prefixed_by(const pdstring &src) const {
325       const string_ll &me = data.getData();
326       const string_ll &them = src.data.getData();
327       return (me.prefixed_by(them));
328    }
329
330    bool suffixed_by(const char *str, unsigned n) const {
331       const string_ll &me = data.getData();
332       return (me.suffixed_by(str, n));
333    }
334    bool suffixed_by(const char *str) const {
335       const string_ll &me = data.getData();
336       return (me.suffixed_by(str));
337    }
338    bool suffixed_by(const pdstring &src) const {
339       const string_ll &me = data.getData();
340       const string_ll &them = src.data.getData();
341       return (me.suffixed_by(them));
342    }
343    
344    unsigned find(const char *str, unsigned n) const {
345      const string_ll &me = data.getData();
346      return (me.find(str, n));
347    }
348    
349    unsigned find(const char *str) const {
350      const string_ll &me = data.getData();
351      return (me.find(str));
352    }
353
354    unsigned find(const pdstring &src) const {
355      const string_ll &me = data.getData();
356      const string_ll &them = src.data.getData();
357      return (me.find(them));
358    }
359
360
361    const char *c_str() const {
362       const string_ll &me = data.getData();
363       return me.c_str();
364    }
365
366    unsigned length() const {
367       const string_ll &me = data.getData();
368       return me.length();
369    }
370
371 #if 0
372    friend ostream& operator<<(ostream &os, const pdstring &s) {
373       const string_ll &it = s.data.getData();
374       return (os << it);
375    }
376 #endif
377    //friend debug_ostream& operator<<(debug_ostream &os, const pdstring &s);
378
379    pdstring substr( unsigned pos, unsigned len ) const {
380            pdstring result = *this;
381            string_ll newstr = data.getData().substr( pos, len );
382            result.data = newstr;
383            return result;
384    }
385
386    bool wildcardEquiv( const pdstring &src, bool checkCase = true ) const {
387       const string_ll &me = data.getData();
388       const string_ll &them = src.data.getData();
389       return me.wildcardEquiv( them, checkCase );
390    }
391    bool wildcardEquiv( const char *ptr, bool checkCase = true ) const {
392       const string_ll &me = data.getData();
393       return me.wildcardEquiv( ptr, checkCase );
394    }
395
396    bool regexEquiv( const pdstring &src, bool checkCase = true ) const {
397       const string_ll &me = data.getData();
398       const string_ll &them = src.data.getData();
399       return me.regexEquiv( them, checkCase );
400    }
401    bool regexEquiv( const char *ptr, bool checkCase = true ) const {
402       const string_ll &me = data.getData();
403       return me.regexEquiv( ptr, checkCase );
404    }
405
406    static unsigned hash(const pdstring &s) {
407       const string_ll &it = s.data.getData();
408       return (string_ll::hash(it));
409    }
410 };
411
412 const pdstring nullString("");
413
414 // See Stroustrup, D & E, sec 3.11.4.2:
415 class string_counter {
416  private:
417    static int count;
418   
419  public:
420    string_counter() {
421       if (count++ == 0)
422          pdstring::initialize_static_stuff();
423    }
424   ~string_counter() {
425       if (--count == 0)
426          pdstring::free_static_stuff();
427    }
428 };
429 extern string_counter sc;
430
431 #endif /* !defined(_String_h_) */