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