cb21075d |
1 | // String.C -*- C++ -*- |
2 | // Copyright (c) 1997, 1998 Etienne BERNARD |
3 | |
4 | // This program is free software; you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation; either version 2 of the License, or |
7 | // any later version. |
8 | |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program; if not, write to the Free Software |
16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. |
17 | |
18 | #include "String.H" |
19 | |
20 | #include <cstring> |
21 | #include <cctype> |
22 | #include <sstream> |
23 | |
24 | String::String() |
25 | { |
26 | p = new srep; |
27 | len = 0; |
28 | p->s = 0; |
29 | } |
30 | |
31 | String::String(const char *s) |
32 | { |
33 | p = new srep; |
34 | len = strlen(s); |
35 | p->s = new char[len + 1]; |
36 | std::strcpy(p->s, s); |
37 | } |
38 | |
39 | String::String(const std::string & s) |
40 | { |
41 | p = new srep; |
6530edbf |
42 | // We do this instead of just s.length () because there might be a |
43 | // \0 in the string before the end (e.g. this is a message from the |
44 | // Socket's buffer). |
45 | const char* temp_str = s.c_str (); |
46 | len = strlen (temp_str); |
cb21075d |
47 | p->s = new char[len + 1]; |
6530edbf |
48 | std::strcpy (p->s, temp_str); |
cb21075d |
49 | } |
50 | |
51 | String::String(const String & s) |
52 | { |
53 | s.p->n++; |
54 | p = s.p; |
55 | len = s.len; |
56 | } |
57 | |
58 | String::String(long i) |
59 | { |
60 | std::ostringstream temp; |
61 | temp << i; |
62 | |
63 | p = new srep; |
64 | len = strlen(temp.str().c_str ()); |
65 | p->s = new char[len + 1]; |
66 | strcpy(p->s, temp.str().c_str ()); |
67 | } |
68 | |
69 | String::String(char c) |
70 | { |
71 | p = new srep; |
72 | p->s = new char[2]; |
73 | p->s[0] = c; |
74 | p->s[1] = '\0'; |
75 | len = 1; |
76 | } |
77 | |
78 | String::~String() |
79 | { |
80 | if (--p->n == 0) { |
81 | delete[] p->s; |
82 | delete p; |
83 | } |
84 | } |
85 | |
86 | String & |
87 | String::operator=(const char *s) |
88 | { |
89 | if (p->n > 1) { |
90 | p->n--; |
91 | p = new srep; |
92 | } |
93 | else |
94 | delete[] p->s; |
95 | |
96 | len = strlen(s); |
97 | p->s = new char[len + 1]; |
98 | strcpy(p->s, s); |
99 | |
100 | return *this; |
101 | } |
102 | |
103 | String & |
104 | String::operator=(const String & s) |
105 | { |
106 | s.p->n++; // protection contre st = st |
107 | if (--p->n == 0) { |
108 | delete[] p->s; |
109 | delete p; |
110 | } |
111 | p = s.p; |
112 | len = s.len; |
113 | return *this; |
114 | } |
115 | |
116 | String & |
117 | String::operator=(const std::string & s) |
118 | { |
119 | if (p->n > 1) { |
120 | p->n--; |
121 | p = new srep; |
122 | } |
123 | else |
124 | delete[] p->s; |
125 | |
126 | len = s.length (); |
127 | p->s = new char[len + 1]; |
128 | strcpy(p->s, s.c_str ()); |
129 | |
130 | return *this; |
131 | } |
132 | |
133 | int |
134 | String::length() const |
135 | { |
136 | return len; |
137 | } |
138 | |
139 | int |
140 | String::find(char c) |
141 | { |
142 | if (!strchr(p->s, c)) |
143 | return -1; |
144 | |
145 | return (int)(strchr(p->s, c) - p->s); |
146 | } |
147 | |
148 | void |
149 | String::fill(char c) |
150 | { |
151 | for (char * s = p->s; *s; s++) |
152 | *s = c; |
153 | } |
154 | |
155 | String |
156 | String::pad(int n) |
157 | { |
158 | int l = len; |
159 | |
160 | if (n <= l) |
161 | return subString(0, n-1); |
162 | |
163 | char *temp = new char[n+1]; |
164 | strcpy(temp, p->s); |
165 | |
166 | for (int i = l; i < n; i++) |
167 | temp[i] = ' '; |
168 | temp[n] = '\0'; |
169 | |
170 | String res(temp); |
171 | delete temp; |
172 | |
173 | return res; |
174 | } |
175 | |
176 | String |
177 | String::subString(int debut, int fin) |
178 | { |
179 | if (fin < debut) return ""; |
180 | |
181 | char * temp = new char[fin-debut+2]; |
182 | strncpy(temp, p->s + debut, fin - debut + 1); |
183 | temp[fin - debut + 1] = '\0'; |
184 | String res(temp); |
185 | delete temp; |
186 | return res; |
187 | } |
188 | |
189 | String |
190 | String::subString(int debut) |
191 | { |
192 | return subString(debut, len - 1); |
193 | } |
194 | |
195 | String |
196 | String::toLower() |
197 | { |
198 | char *temp = new char[len + 1]; |
199 | |
200 | for (int i = 0; i < len + 1; i++) |
201 | if (isupper(p->s[i])) |
202 | temp[i] = tolower(p->s[i]); |
203 | else |
204 | temp[i] = p->s[i]; |
205 | |
206 | String res(temp); |
207 | delete temp; |
208 | return res; |
209 | } |
210 | |
211 | String |
212 | String::toUpper() |
213 | { |
214 | char *temp = new char[len + 1]; |
215 | |
216 | for (int i = 0; i < len + 1; i++) |
217 | if (islower(p->s[i])) |
218 | temp[i] = toupper(p->s[i]); |
219 | else |
220 | temp[i] = p->s[i]; |
221 | |
222 | String res(temp); |
223 | delete temp; |
224 | return res; |
225 | } |
226 | |
227 | String |
228 | String::trim() |
229 | { |
230 | int i = 0, j = len - 1; |
231 | |
232 | while (i < j && (p->s[i] == ' ' || p->s[i] == '\t' || p->s[i] == '\r')) |
233 | i++; |
234 | |
235 | while (j > 0 && (p->s[j] == ' ' || p->s[j] == '\t' || p->s[i] == '\r')) |
236 | j--; |
237 | |
238 | return subString(i, j); |
239 | } |
240 | |
241 | int |
242 | String::indexOf(char c) |
243 | { |
244 | char *s = std::strchr(p->s, c); |
245 | if (s) |
246 | return p->s - s; |
247 | |
248 | return -1; |
249 | } |
250 | |
251 | char & |
252 | String::operator[](int i) |
253 | { |
254 | if (i < 0 || len < i) { |
255 | std::cerr << "String index out of range\n"; |
256 | std::exit(1); |
257 | } |
258 | return p->s[i]; |
259 | } |
260 | |
261 | const char & |
262 | String::operator[](int i) const |
263 | { |
264 | if (i < 0 || len < i) { |
265 | std::cerr << "String index out of range\n"; |
266 | exit(1); |
267 | } |
268 | return p->s[i]; |
269 | } |
270 | |
271 | bool |
272 | String::operator==(const char *s) const |
273 | { |
274 | return std::strcmp(p->s, s) == 0; |
275 | } |
276 | |
277 | bool |
278 | String::operator==(const String & s) const |
279 | { |
280 | return (p == s.p) || (std::strcmp(p->s, s.p->s) == 0); |
281 | } |
282 | |
283 | bool |
284 | String::operator==(const std::string & s) const |
285 | { |
286 | return (p->s == s.c_str ()) || (std::strcmp (p->s, s.c_str()) == 0); |
287 | } |
288 | |
289 | bool |
290 | String::operator!=(const char *s) const |
291 | { |
292 | return std::strcmp(p->s, s) != 0; |
293 | } |
294 | |
295 | bool |
296 | String::operator!=(const String & s) const |
297 | { |
298 | return std::strcmp(p->s, s.p->s) != 0; |
299 | } |
300 | |
301 | bool |
302 | String::operator!=(const std::string & s) const |
303 | { |
304 | return ! (*this == s); |
305 | } |
306 | |
307 | bool |
308 | String::operator<(const String & s) const |
309 | { |
310 | return std::strcmp(p->s, s.p->s) < 0; |
311 | } |
312 | |
313 | bool |
314 | String::operator<(const std::string & s) const |
315 | { |
316 | return std::strcmp(p->s, s.c_str ()) < 0; |
317 | } |
318 | |
319 | bool |
320 | String::operator>(const String & s) const |
321 | { |
322 | return std::strcmp(p->s, s.p->s) > 0; |
323 | } |
324 | |
325 | bool |
326 | String::operator<=(const String & s) const |
327 | { |
328 | return std::strcmp(p->s, s.p->s) <= 0; |
329 | } |
330 | |
331 | bool |
332 | String::operator<=(const std::string & s) const |
333 | { |
334 | return (*this < s) || (*this == s); |
335 | } |
336 | |
337 | bool |
338 | String::operator>=(const String & s) const |
339 | { |
340 | return std::strcmp(p->s, s.p->s) >= 0; |
341 | } |
342 | |
343 | bool String::operator>=(const std::string & s) const |
344 | { |
345 | return ! (*this < s); |
346 | } |
347 | |
348 | String |
349 | String::operator+(const char *s) |
350 | { |
351 | char *temp = new char[len + std::strlen(s) + 1]; |
352 | |
353 | std::strcpy(temp, p->s); |
354 | std::strcat(temp, s); |
355 | |
356 | String res(temp); |
357 | delete temp; |
358 | |
359 | return res; |
360 | } |
361 | |
362 | String |
363 | String::operator+(const String & s) |
364 | { |
365 | char * temp = new char[len + s.len + 1]; |
366 | |
367 | std::strcpy(temp, p->s); |
368 | std::strcat(temp, s.p->s); |
369 | |
370 | String res(temp); |
371 | delete temp; |
372 | |
373 | return res; |
374 | } |
375 | |
376 | String |
377 | String::operator+(const std::string & s) |
378 | { |
379 | char * temp = new char[len + s.length () + 1]; |
380 | std::strcpy (temp, p->s); |
381 | std::strcat (temp, s.c_str ()); |
382 | |
383 | String res (temp); |
384 | delete temp; |
385 | |
386 | return res; |
387 | } |
388 | |
389 | String::operator const char *() const |
390 | { |
391 | return p->s; |
392 | } |
393 | |
394 | String::operator std::string () const |
395 | { |
396 | return std::string (p->s); |
397 | } |
398 | |
399 | std::ostream & |
400 | operator<<(std::ostream & s, const String & st) |
401 | { |
402 | return s << st.p->s; |
403 | } |
404 | |
405 | std::istream & |
406 | operator>>(std::istream & s, String & st) |
407 | { |
408 | if (st.p->n > 1) { |
409 | st.p->n--; |
410 | st.p = new String::srep; |
411 | } |
412 | else |
413 | delete[] st.p->s; |
414 | |
415 | char buf[2048]; |
416 | char c; |
417 | |
418 | s.getline (buf, 2048, '\n'); |
419 | //s.get(c); |
420 | |
421 | st.len = strlen(buf); |
422 | st.p->s = new char[st.len + 1]; |
423 | strcpy(st.p->s, buf); |
424 | |
425 | return s; |
426 | } |
427 | |
428 | std::string operator+(const std::string & s, const String & p) |
429 | { |
430 | std::string temp = s; |
431 | temp += p.p->s; |
432 | return temp; |
433 | } |
434 | |
435 | bool operator==(const std::string & s, const String & p) |
436 | { |
437 | return p == s; |
438 | } |
439 | |
440 | bool operator!=(const std::string & s, const String & p) |
441 | { |
442 | return p != s; |
443 | } |
444 | |
445 | bool operator>(const std::string & s, const String & p) |
446 | { |
447 | return p <= s; |
448 | } |
449 | |
450 | bool operator<(const std::string & s, const String & p) |
451 | { |
452 | return p >= s; |
453 | } |
454 | |
455 | bool operator<=(const std::string & s, const String & p) |
456 | { |
457 | return p > s; |
458 | } |
459 | |
460 | bool operator>=(const std::string & s, const String & p) |
461 | { |
462 | return p < s; |
463 | } |