initial
[prop.git] / lib-src / strings / string.cc
blob9e92158c9c12626c576c9641c418255a207dfe20
1 //////////////////////////////////////////////////////////////////////////////
2 // NOTICE:
3 //
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are free to incorporate any part of ADLib and Prop into
9 // your programs.
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
16 // code.
18 // This software is still under development and we welcome any suggestions
19 // and help from the users.
21 // Allen Leung
22 // 1994
23 //////////////////////////////////////////////////////////////////////////////
25 #include <assert.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <AD/strings/string.h>
32 ////////////////////////////////////////////////////////////////////////////
33 // Constructors
34 ////////////////////////////////////////////////////////////////////////////
36 ////////////////////////////////////////////////////////////////////
37 // Searching
38 ////////////////////////////////////////////////////////////////////
39 int SubString::contains (RegExp& regexp) const
40 { return regexp.Match(get_string(),len); }
42 int SubString::contains (char c) const
43 { /* const char * r = (const char *)memchr(get_string(),c,len);
44 return r ? r - get_string() : -1;
46 return -1;
49 int SubString::contains (const char *, int) const
51 return 0;
54 int SubString::contains (const String&) const
56 return 0;
59 int SubString::contains (const SubString&) const
61 return 0;
64 ////////////////////////////////////////////////////////////////////////////
65 // Class String
66 ////////////////////////////////////////////////////////////////////////////
68 void String::out_of_bounds(int i) const // error handler
69 { cerr << "[Attempting to index location " << i << " of string: "
70 << string << "]\n";
71 exit(1);
74 ////////////////////////////////////////////////////////////////////////////
75 // Constructors
76 ////////////////////////////////////////////////////////////////////////////
77 String::String(int initial_capacity)
78 { if (initial_capacity > 0) {
79 string = new char [cap = initial_capacity];
80 len = initial_capacity; string[len] = '\0';
81 } else { string = 0; len = 0; cap = 0; }
84 String::String(char c, int times)
85 { if (times > 0) {
86 string = new char [cap = (len = times) + 1];
87 memset(string,c,len); string[len] = '\0';
88 } else { string = 0; len = 0; cap = 0; }
91 String::String(const char * s)
92 { if (s) {
93 string = new char [cap = (len = strlen(s)) + 1];
94 memcpy(string,s,len); string[len] = '\0';
95 } else { string = 0; len = cap = 0; }
98 String::String(const char * s, int l)
99 { if (s && l >= 0) {
100 string = new char [cap = (len = l) + 1];
101 memcpy(string,s,len); string[len] = '\0';
102 } else { string = 0; len = cap = 0; }
105 String::String(const String& s)
106 { string = new char [cap = (len = s.len) + 1];
107 memcpy(string,s.string,len);
110 ///////////////////////////////////////////////////////////////////////
111 // String expansion
112 ///////////////////////////////////////////////////////////////////////
113 void String::grow(long new_len)
114 { cap = new_len * 3 / 2 + 1;
115 char * new_string = new char [cap];
116 memcpy(new_string,string,len);
117 delete [] string; string = new_string;
120 ///////////////////////////////////////////////////////////////////////
121 // Assigment
122 ///////////////////////////////////////////////////////////////////////
123 String& String::operator = (const String& s)
124 { if (this != &s) {
125 if (s.len >= cap) grow(s.len);
126 memcpy(string,s.string,len = s.len);
127 string[len] = '\0';
129 return *this;
132 String& String::operator = (const char * s)
133 { if (s == 0) len = 0;
134 else {
135 int l = strlen(s);
136 if (l >= cap) grow(l);
137 strcpy(string,s);
138 len = l;
140 return *this;
143 String& String::operator = (const SubString& s)
144 { if (s.length() >= cap) grow(s.length());
145 memcpy(string, s.get_string(), len = s.length());
146 string[len] = '\0';
147 return *this;
150 ////////////////////////////////////////////////////////////////////
151 // String splicing
152 ////////////////////////////////////////////////////////////////////
153 String& String::splice(int location, int kill_len, const char * s, int size)
154 { if (size < 0) size = s ? strlen(s) : 0;
155 if (kill_len < 0) kill_len = 0;
156 if (location + kill_len >= len) kill_len = len - location;
157 int new_len = len - kill_len + size;
158 if (new_len >= cap) grow(new_len);
159 if (kill_len > size) { // shrink string
160 register char * p, * q;
161 register int n = len - location + kill_len;
162 for (p = string + location, q = p + kill_len - size; n > 0; n--)
163 *p++ = *q++;
164 } else if (kill_len < size) { // expand string
165 register char * p, * q;
166 register int n = len - location + kill_len;
167 for (p = string + location + n - 1, q = p + size - kill_len + n - 1;
168 n > 0; n--)
169 *q-- = *p--;
171 len = new_len; string[len] = '\0';
172 memcpy(string + location, s, size); // now copy substring
173 return *this;
176 ///////////////////////////////////////////////////////////////////////
177 // Concatenation
178 ///////////////////////////////////////////////////////////////////////
179 String operator + (const String& a, const String& b)
180 { String r((int)(a.len + b.len));
181 memcpy(r.string, a.string, a.len);
182 memcpy(r.string + a.len, b.string, b.len);
183 return r;
185 String operator + (const String& a, const char * b)
186 { String r((int)(a.len + strlen(b)));
187 memcpy(r.string, a.string, a.len);
188 strcpy(r.string + a.len, b);
189 return r;
192 String operator + (const String& a, char c)
193 { String r((int)(a.len + 1));
194 memcpy(r.string, a.string, a.len);
195 r.string[a.len] = c;
196 return r;
199 String operator + (const char * a, const String& b)
200 { int a_len = strlen(a);
201 String r((int)(a_len + b.len));
202 memcpy(r.string, a, a_len);
203 memcpy(r.string + a_len, b.string, b.len);
204 return r;
207 String operator + (char c, const String& s)
208 { String r((int)(s.len + 1));
209 r.string[0] = c;
210 memcpy(r.string + 1, s.string, s.len);
211 return r;
214 ///////////////////////////////////////////////////////////////////////
215 // Multiplication
216 ///////////////////////////////////////////////////////////////////////
217 String operator * (const String& s, int n)
218 { String r(s.length() * n);
219 char * p;
220 for (p = r.string; n > 0; p += s.length())
221 memcpy(p, s.string, s.length());
222 *p = '\0';
223 return r;
226 String operator * (const SubString& s, int n)
227 { return String(s) * n; }
229 ///////////////////////////////////////////////////////////////////////
230 // Append to end
231 ///////////////////////////////////////////////////////////////////////
232 String& String::operator += (const String& s)
233 { int new_len = s.len + len;
234 if (new_len >= cap) grow(new_len);
235 memcpy(string + len, s.string, s.len);
236 len = new_len; string[len] = '\0';
237 return *this;
240 String& String::operator += (const char * s)
241 { if (s) {
242 int s_len = strlen(s);
243 int new_len = s_len + len;
244 if (new_len >= cap) grow(new_len);
245 memcpy(string + len, s, s_len);
246 len = new_len; string[len] = '\0';
248 return *this;
251 String& String::operator += (char c)
252 { if (len + 1 >= cap) grow(len + 1);
253 string[len++] = c;
254 string[len] = '\0';
255 return *this;
258 ///////////////////////////////////////////////////////////////////////
259 // Comparisons
260 ///////////////////////////////////////////////////////////////////////
261 int String::compare (const String& s) const
262 { register const char * p, * q;
263 register int n = len < s.len ? len : s.len;
264 for (p = string, q = s.string; n > 0; n--, p++, q++)
265 if (*p - *q) return *p - *q;
266 return *p - *q;
269 int String::compare (const SubString& s) const
270 { int l = len < s.len ? len : s.len;
271 int r = memcmp(string,s.S.string + s.start, l);
272 if (r) return r;
273 return len - s.len;
276 int String::compare (const char * s, int l) const
277 { register const char * p, * q;
278 if (l < 0) l = strlen(s);
279 register int n = len < l ? len : l;
280 for (p = string, q = s; n > 0; n--, p++, q++)
281 if (*p - *q) return *p - *q;
282 return *p - *q;
285 int String::case_insensitive_compare (const String& s) const
286 { return case_insensitive_compare(s.string, s.len); }
288 int String::case_insensitive_compare (const SubString& s) const
289 { return case_insensitive_compare(s.get_string(), s.len); }
291 int String::case_insensitive_compare (const char * s, int l) const
292 { register const char * p, * q;
293 register int i = len < l ? len : l;
294 for (p = string, q = s; i > 0; i--, p++, q++)
295 if (tolower(*p) - tolower(*q))
296 return tolower(*p) - tolower(*q);
297 return tolower(*p) - tolower(*q);
300 int String::collate (const String&) const
301 { return 0; }
303 int String::collate (const SubString&) const
304 { return 0; }
306 int String::collate (const char *, int) const
307 { return 0; }
309 ///////////////////////////////////////////////////////////////////////
310 // In place operations
311 ///////////////////////////////////////////////////////////////////////
312 String& String::to_upper()
313 { register char * p, * q;
314 for (p = string, q = string + len; p < q; p++)
315 *p = toupper(*p);
316 return *this;
319 String& String::to_lower()
320 { register char * p, * q;
321 for (p = string, q = string + len; p < q; p++)
322 *p = tolower(*p);
323 return *this;
326 String& String::trunc(int length)
327 { if (length >= 0 && length < len) {
328 len = length; string[len] = '\0';
330 return *this;
333 ///////////////////////////////////////////////////////////////////////
334 // Searching
335 ///////////////////////////////////////////////////////////////////////
336 int String::contains (RegExp& regexp) const
337 { return regexp.Match(string,len); }
339 int String::contains (char c) const
340 { const char * r = strchr(string,c);
341 return r ? r - string : -1;
344 int String::contains (const char * s, int) const
345 { const char * r = strstr(string,s);
346 return r ? r - string : -1;
349 int String::contains (const String& s) const
350 { const char * r = strstr(string,s.string);
351 return r ? r - string : -1;
354 int String::contains (const SubString&) const
355 { return 0; }
357 ///////////////////////////////////////////////////////////////////////
358 // Input and Output
359 ///////////////////////////////////////////////////////////////////////
360 istream& operator >> (istream& in, String&)
361 { return in; }