nil static member as an optimization
[dyninst.git] / pdutil / 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 // String.C
43
44 #include <assert.h>
45 #include "util/h/headers.h"
46 #include "util/h/String.h"
47
48 // Declare a static member vrble:
49 string string::nil((const char*)NULL);
50
51 string_ll::string_ll()
52     : str_(0), len_(0), key_(0) {
53 }
54
55 string_ll::string_ll(const char* str)
56     : str_(STRDUP(str)), len_(STRLEN(str)) {
57    key_ = 0; // lazy key define
58 }
59
60 string_ll::string_ll(const char *str, unsigned len) {
61    // same as above constructor, but copies less than the entire string.
62    // You specifiy the # of chars to copy.
63    if (len > strlen(str))
64       // just copy the whole string
65       len = strlen(str);
66
67    len_ = len;
68    str_ = new char[len+1];
69    (void) P_memcpy(str_, str, len);
70    str_[len] = '\0';
71
72    key_ = 0; // lazy key define
73 }
74
75 string_ll::string_ll(const string_ll& s)
76     : str_(STRDUP(s.str_)), len_(s.len_), key_(s.key_) {
77    // lazy key define iff "s" lazy key define (as it should be)
78 }
79
80 string_ll::string_ll(int i) {
81    char tempBuffer[40];
82    sprintf(tempBuffer, "%d", i);
83
84    str_ = STRDUP(tempBuffer);
85    len_ = STRLEN(tempBuffer);
86
87    key_ = 0; // lazy key define
88 }
89
90 string_ll::string_ll(long l) {
91    char tempBuffer[40];
92    sprintf(tempBuffer, "%ld", l);
93
94    str_ = STRDUP(tempBuffer);
95    len_ = STRLEN(tempBuffer);
96
97    key_ = 0; // lazy key define
98 }
99
100 string_ll::string_ll(unsigned u) {
101    char tempBuffer[40];
102    sprintf(tempBuffer, "%u", u);
103
104    str_ = STRDUP(tempBuffer);
105    len_ = STRLEN(tempBuffer);
106
107    key_ = 0; // lazy key define
108 }
109
110 string_ll::string_ll(unsigned long ul) {
111    char tempBuffer[40];
112    sprintf(tempBuffer, "%lu", ul);
113
114    str_ = STRDUP(tempBuffer);
115    len_ = STRLEN(tempBuffer);
116
117    key_ = 0; // lazy key define
118 }
119
120 string_ll::string_ll(float f) {
121    char tempBuffer[40];
122    sprintf(tempBuffer, "%f", f);
123
124    str_ = STRDUP(tempBuffer);
125    len_ = STRLEN(tempBuffer);
126
127    key_ = 0; // lazy key define
128 }
129
130 string_ll::string_ll(double d) {
131    char tempBuffer[40];
132    sprintf(tempBuffer, "%g", d);
133
134    str_ = STRDUP(tempBuffer);
135    len_ = STRLEN(tempBuffer);
136
137    key_ = 0; // lazy key define
138 }
139
140 string_ll::~string_ll() {
141     delete [] str_; str_ = 0;
142 }
143
144 string_ll&
145 string_ll::operator=(const char* str) {
146     if (str_ == str) {
147         return *this;
148     }
149
150     delete [] str_; str_ = 0;
151
152     str_ = STRDUP(str);
153     len_ = STRLEN(str);
154
155     key_ = 0; // lazy key define
156
157     return *this;
158 }
159
160 string_ll&
161 string_ll::operator=(const string_ll& s) {
162     if (this == &s) {
163         return *this;
164     }
165
166     delete [] str_; str_ = 0;
167
168     str_ = STRDUP(s.str_);
169     len_ = s.len_;
170     key_ = s.key_; // lazy key define iff "s" lazy key define, which is correct
171
172     return *this;
173 }
174
175 string_ll&
176 string_ll::operator+=(const string_ll& s) {
177     unsigned nlen = len_ + s.len_;
178     char*    ptr  = new char[nlen+1];
179     assert(ptr);
180
181     memcpy(ptr, str_, len_);
182     memcpy(&ptr[len_], s.str_, s.len_);
183     ptr[nlen] = '\0';
184
185     delete[] str_; str_ = 0;
186     str_ = ptr;
187     len_ = nlen;
188
189     key_ = 0;
190
191     return *this;
192 }
193
194 string_ll&
195 string_ll::operator+=(const char *ptr) {
196    // this routine exists as an optimization, sometimes avoiding the need to create
197    // a temporary string, which can be expensive.
198
199    const int ptr_len = P_strlen(ptr);
200    const unsigned nlen = len_ + ptr_len;
201    char *new_ptr = new char[nlen+1];
202    assert(new_ptr);
203
204    memcpy(new_ptr, str_, len_);
205    memcpy(&new_ptr[len_], ptr, ptr_len);
206    new_ptr[nlen] = '\0';
207   
208    delete [] str_;
209    str_ = new_ptr;
210    len_ = nlen;
211
212    key_ = 0; // lazy key define
213
214    return *this;
215 }
216
217
218 string_ll
219 string_ll::operator+(const string_ll& s) const {
220     string_ll ret = *this;
221     return (ret += s);
222 }
223
224 string_ll
225 string_ll::operator+(const char *ptr) const {
226    string_ll ret = *this;
227    return (ret += ptr);
228 }
229
230 bool
231 string_ll::operator==(const string_ll& s) const {
232    if (&s == this) return true;
233
234    updateKeyIfNeeded(); s.updateKeyIfNeeded();
235    if (key_ != s.key_) return false;
236    if (len_ != s.len_) return false;
237    return STREQ(str_, s.str_);
238 }
239
240 bool
241 string_ll::operator!=(const string_ll& s) const {
242    if (&s == this) return false;
243    if (len_ != s.len_) return true;
244    return STRNE(str_, s.str_);
245 }
246
247 bool
248 string_ll::operator<=(const string_ll& s) const {
249     return ((&s == this) || STRLE(str_, s.str_));
250 }
251
252 bool
253 string_ll::operator>=(const string_ll& s) const {
254     return ((&s == this) || STRGE(str_, s.str_));
255 }
256
257 bool
258 string_ll::prefix_of(const char* s, unsigned sl) const {
259     return ((len_ > sl) ? false : STREQN(str_, s, len_));
260 }
261
262 bool
263 string_ll::prefix_of(const string_ll& s) const {
264     return ((&s == this) || prefix_of(s.str_, s.len_));
265 }
266
267 bool
268 string_ll::prefixed_by(const char* s, unsigned sl) const {
269     return ((sl > len_) ? false : STREQN(str_, s, sl));
270 }
271
272 bool
273 string_ll::prefixed_by(const string_ll& s) const {
274     return ((&s == this) || prefixed_by(s.str_, s.len_));
275 }
276
277 unsigned
278 string_ll::hashs(const char* str) {
279     if (!str) {
280         return 0;
281     }
282
283     unsigned h = 5381;
284     while (*str) {
285         h = (h << 5) + h + (unsigned) (*str);
286         str++;
287     }
288     return h;
289 }
290
291 unsigned
292 string_ll::STRLEN(const char* str) {
293     return ((str)?(P_strlen(str)):(0));
294 }
295
296 char*
297 string_ll::STRDUP(const char* str) {
298     if (!str) {
299         return 0;
300     }
301
302     unsigned size = P_strlen(str)+1;
303     char*    p    = new char[size];
304
305     (void) P_memcpy(p, str, size);
306     return p;
307 }
308
309 bool
310 string_ll::STREQ(const char* s1, const char* s2) {
311     return ((s1&&s2)?(P_strcmp(s1,s2)==0):(!(s1||s2)));
312 }
313
314 bool
315 string_ll::STREQN(const char* s1, const char* s2, unsigned len) {
316     return ((s1&&s2)?(P_strncmp(s1,s2,len)==0):(!(s1||s2)));
317 }
318
319 bool
320 string_ll::STRNE(const char* s1, const char* s2) {
321     return ((s1&&s2)?(P_strcmp(s1,s2)!=0):(false));
322 }
323
324 bool
325 string_ll::STRLT(const char* s1, const char* s2) {
326     return ((s1&&s2)?(P_strcmp(s1,s2)<0):(false));
327 }
328
329 bool
330 string_ll::STRLE(const char* s1, const char* s2) {
331     return ((s1&&s2)?(P_strcmp(s1,s2)<=0):(!(s1||s2)));
332 }
333
334 bool
335 string_ll::STRGT(const char* s1, const char* s2) {
336     return ((s1&&s2)?(P_strcmp(s1,s2)>0):(false));
337 }
338
339 bool
340 string_ll::STRGE(const char* s1, const char* s2) {
341     return ((s1&&s2)?(P_strcmp(s1,s2)>=0):(!(s1||s2)));
342 }
343
344 ostream& operator<< (ostream &os, const string_ll &s) {
345    return os << s.str_;
346 }
347
348 debug_ostream& operator<< (debug_ostream &os, const string_ll &s) {
349    return os << s.str_;
350 }
351
352 string operator+(const char *ptr, const string &str) {
353    // a syntactical convenience.
354    // This fn could probably be optimized quite a bit (pre-allocate exactly
355    // the # of bytes that are needed)
356    string result(ptr);
357    result += str;
358    return result;
359 }
360