default ctor sped up
[dyninst.git] / common / h / String.h
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 /************************************************************************
43  * String.h: a simple character string class.
44 ************************************************************************/
45
46 #if !defined(_String_h_)
47 #define _String_h_
48
49
50 /************************************************************************
51  * header files.
52 ************************************************************************/
53
54 #include <iostream.h>
55 #include "util/h/debugOstream.h"
56 #include "util/h/headers.h"
57
58 \f
59 /************************************************************************
60  * class string
61 ************************************************************************/
62
63 class string_ll {
64 public:
65      string_ll ();
66      string_ll (const char *);
67      string_ll (const char *, unsigned n); // just copy the first n chars
68      string_ll (const string_ll &);
69      string_ll (int);      // convert int to its string_ll representation
70      string_ll (long);      // convert int to its string_ll representation
71      string_ll (unsigned); // convert unsigned to its string_ll representation
72      string_ll (unsigned long); // convert unsigned to its string_ll representation
73      string_ll (float);    // convert float to its string_ll representation
74      string_ll (double);   // convert double to its string_ll representation
75     ~string_ll ();
76
77     string_ll& operator= (const char *);
78     string_ll& operator= (const string_ll &);
79     string_ll& operator+= (const string_ll &);
80     string_ll& operator+= (const char *);
81     string_ll  operator+ (const string_ll &) const;
82     string_ll  operator+ (const char *) const;
83
84     bool operator== (const string_ll &) const;
85     bool operator== (const char *ptr) const {
86        // This routine exists as an optimization; doesn't need to create a temporary
87        // instance of "string" for "ptr"; hence, doesn't call string::string(char *)
88        // which calls new[].
89        return STREQ(ptr, str_);
90     }
91     bool operator!= (const string_ll &) const;
92     bool operator<  (const string_ll &s) const {return STRLT(str_, s.str_);}
93     bool operator<= (const string_ll &) const;
94     bool operator>  (const string_ll &s) const {return STRGT(str_, s.str_);}
95     bool operator>= (const string_ll &) const;
96
97     bool prefix_of (const char *, unsigned) const;
98     bool prefix_of (const char *s)          const {return prefix_of(s, STRLEN(s));};
99     bool prefix_of (const string_ll &)         const;
100
101     bool prefixed_by (const char *, unsigned) const;
102     bool prefixed_by (const char *s)          const {return prefixed_by(s, STRLEN(s));};
103     bool prefixed_by (const string_ll &)         const;
104
105     const char*   string_of () const {return str_;}
106     unsigned         length () const {return len_;}
107
108     friend ostream& operator<< (ostream &os, const string_ll &s);
109     friend debug_ostream& operator<< (debug_ostream &os, const string_ll &s);
110 //    friend string_ll operator+(const char *, const string_ll &);
111 //       // a syntactical convenience
112
113     static unsigned       hash (const string_ll &s) {
114        s.updateKeyIfNeeded(); return s.key_;
115     }
116
117 private:
118     void updateKeyIfNeeded() const {if (0==key_) updateKey(); }
119     void updateKey() const {
120        key_ = hashs(str_); // properly checks for NULL; properly won't return 0
121     }
122
123     static unsigned      hashs (const char *);
124
125     static unsigned     STRLEN (const char *);
126     static char*        STRDUP (const char *);
127
128     static bool          STREQ (const char *, const char *);
129     static bool         STREQN (const char *, const char *, unsigned);
130     static bool          STRNE (const char *, const char *);
131     static bool          STRLT (const char *, const char *);
132     static bool          STRLE (const char *, const char *);
133     static bool          STRGT (const char *, const char *);
134     static bool          STRGE (const char *, const char *);
135
136     char*    str_;
137     unsigned len_;
138
139     mutable unsigned key_;
140 };
141
142 #include "util/h/refCounter.h"
143
144 class string {
145    friend class string_counter;
146  private:
147    refCounter<string_ll> data;
148
149    static string *nilptr;
150
151    static void initialize_static_stuff();
152    static void free_static_stuff();
153
154  public:
155    // The second of the constructors below should be faster, but it means
156    // we must rely on nil.data being initialized before any global string
157    // objects (or static class members) created with this constructor.
158 //   string() : data(string_ll()) {};
159    string() : data(nilptr->data) {} // should be more efficient than above
160
161    string(const char *str) : data(string_ll(str)) {}
162
163    string(const char *str, unsigned n) : data(string_ll(str,n)) {}
164
165    string(const string& src) : data(src.data) {}
166    string(int i) : data(string_ll(i)) {}
167    string(long l) : data(string_ll(l)) {}
168    string(unsigned u) : data(string_ll(u)) {}
169    string(unsigned long ul) : data(string_ll(ul)) {}
170    string(float f) : data(string_ll(f)) {}
171    string(double d) : data(string_ll(d)) {}
172   ~string() {}
173
174    string& operator=(const char *str) {
175       string_ll new_str_ll(str);
176       refCounter<string_ll> newRefCtr(new_str_ll);
177       
178       data = newRefCtr;
179       return *this;
180    }
181    string& operator=(const string &src) {
182       data = src.data;
183       return *this;
184    }
185
186    string& operator+=(const string &addme) {
187       // see comment in next routine as to why we don't modify in-place.
188       string_ll newstr = data.getData() + addme.data.getData();
189       data = newstr;
190       return *this;
191    }
192
193    string& operator+=(const char *str) {
194       // You might wonder why we can't just do:
195       // data.getData() += str; return *this;
196       // The answer is that that would make an in-place modification,
197       // thus messing up any others who might be attached to the same object as us.
198       // There are two alternative solutions: use prepareToModifyInPlace() followed
199       // by the above sequence, or what we use below.  In general, if the in-place
200       // modification doesn't require making an entirely new low-level object
201       // (the below example does require that), then it's better to use prepareToModifyInPlace()
202       // instead of operator=().
203       
204       string_ll newstr = data.getData() + str;
205       data = newstr;
206       return *this;
207    }
208
209    string operator+(const string &src) const {
210       string result = *this;
211       return (result += src);
212    }
213    string operator+(const char *src) const {
214       string result = *this;
215       return (result += src);
216    }
217    friend string operator+(const char *src, const string &str);
218       // a syntactical convenience
219
220    bool operator==(const string &src) const {
221       const string_ll &me = data.getData();
222       const string_ll &them = src.data.getData();
223       return (me == them);
224    }
225    bool operator==(const char *ptr) const {
226       const string_ll &me = data.getData();
227       return (me == ptr);
228    }
229    bool operator!=(const string &src) const {
230       const string_ll &me = data.getData();
231       const string_ll &them = src.data.getData();
232       return (me != them);
233    }
234    bool operator<(const string &src) const {
235       const string_ll &me = data.getData();
236       const string_ll &them = src.data.getData();
237       return (me < them);
238    }
239    bool operator<=(const string &src) const {
240       const string_ll &me = data.getData();
241       const string_ll &them = src.data.getData();
242       return (me <= them);
243    }
244    bool operator>(const string &src) const {
245       const string_ll &me = data.getData();
246       const string_ll &them = src.data.getData();
247       return (me > them);
248    }
249    bool operator>=(const string &src) const {
250       const string_ll &me = data.getData();
251       const string_ll &them = src.data.getData();
252       return (me >= them);
253    }
254    bool prefix_of(const char *str, unsigned n) const {
255       const string_ll &me = data.getData();
256       return (me.prefix_of(str, n));
257    }
258    bool prefix_of(const char *str) const {
259       const string_ll &me = data.getData();
260       return (me.prefix_of(str));
261    }
262    bool prefix_of(const string &src) const {
263       const string_ll &me = data.getData();
264       const string_ll &them = src.data.getData();
265       return (me.prefix_of(them));
266    }
267
268    bool prefixed_by(const char *str, unsigned n) const {
269       const string_ll &me = data.getData();
270       return (me.prefixed_by(str, n));
271    }
272    bool prefixed_by(const char *str) const {
273       const string_ll &me = data.getData();
274       return (me.prefixed_by(str));
275    }
276    bool prefixed_by(const string &src) const {
277       const string_ll &me = data.getData();
278       const string_ll &them = src.data.getData();
279       return (me.prefixed_by(them));
280    }
281
282    const char *string_of() const {
283       const string_ll &me = data.getData();
284       return me.string_of();
285    }
286
287    unsigned length() const {
288       const string_ll &me = data.getData();
289       return me.length();
290    }
291
292    friend ostream& operator<<(ostream &os, const string &s) {
293       const string_ll &it = s.data.getData();
294       return (os << it);
295    }
296    friend debug_ostream& operator<<(debug_ostream &os, const string &s) {
297       const string_ll &it = s.data.getData();
298       return (os << it);
299    }
300
301    static unsigned hash(const string &s) {
302       const string_ll &it = s.data.getData();
303       return (string_ll::hash(it));
304    }
305 };
306
307 // See Stroustrup, D & E, sec 3.11.4.2:
308 class string_counter {
309  private:
310    static int count;
311   
312  public:
313    string_counter() {
314       if (count++ == 0)
315          string::initialize_static_stuff();
316    }
317   ~string_counter() {
318       if (--count == 0)
319          string::free_static_stuff();
320    }
321 };
322 static string_counter sc;
323
324 #endif /* !defined(_String_h_) */