1 /**************************************************************************
2 ** (c) Copyright 1997, Andromeda Technology & Automation
3 ***************************************************************************
4 ** MODULE INFORMATION *
5 ***********************
6 ** FILE NAME : string.cpp
7 ** SYSTEM NAME : Andromeda X-Windows Encapsulation
8 ** VERSION NUMBER : $Revision: 1.5 $
10 ** DESCRIPTION : String class implementation.
15 ***************************************************************************
16 ** ADMINISTRATIVE INFORMATION *
17 ********************************
18 ** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
19 ** CREATION DATE : Nov 17, 1997
20 ** LAST UPDATE : Nov 30, 2003
22 **************************************************************************/
24 /*****************************
26 Revision 1.5 2007-05-04 13:55:18 arjen
27 Dynamically allocate more memory if the string buffer runs out of space when
28 reading a String object from an input stream.
30 Revision 1.4 2003/03/29 07:18:54 arjen
31 String constructor and assignment from char * are more robust fro NULL pointers.
33 Revision 1.3 2002/11/03 13:18:57 arjen
34 New functions - String::escape() and String::unescape()
36 Revision 1.2 2002/09/28 06:42:11 arjen
37 A few small bug fixes.
39 Revision 1.1 2002/07/25 08:01:27 arjen
40 First checkin, AXE release 0.2
42 *****************************/
44 static const char RCSID[] = "$Id: string.cpp,v 1.5 2007-05-04 13:55:18 arjen Exp $";
50 // Constructors and destructors for the String class
52 String::String() // Create an empty String
60 String::String(char c) // Create a String from a char
69 String::String(const char *s) // Create a String from a char *
78 p->s = new char[strlen(s)+1];
84 String::String(const String& x) // Create a String from another String
90 String::String(const substring &x)
94 p->s = new char[x.len+1];
95 strncpy(p->s, x.str->p->s+x.start, x.len);
96 p->s[x.len] = '\0'; // strncpy does not add the \0
110 * Assignment operators must handle cleanup of their left-hand operand.
113 String& String::operator=(const char c)
130 String& String::operator=(const char *s)
142 p->s = new char[strlen(s)+1];
149 /* Make sure that assignment of an object to itself works correctly: */
151 String& String::operator=(const String& x)
164 /* Numerical conversion */
166 String::String(int i)
169 p->s = new char[15]; // A little longer than needed...
170 sprintf(p->s, "%d", i);
174 String::String(long i)
177 p->s = new char[15]; // A little longer than needed...
178 sprintf(p->s, "%ld", i);
182 String::String(unsigned long i)
185 p->s = new char[15]; // A little longer than needed...
186 sprintf(p->s, "%lu", i);
190 String::String(double d)
193 p->s = new char[25]; // A little longer than needed...
194 sprintf(p->s, "%.3f", d);
198 /* String concatenation */
200 String& String::operator+=(const String& x)
202 char *s = new char[strlen(p->s) + strlen(x.p->s) + 1];
220 String& String::operator+=(const char * str)
222 char *s = new char[strlen(p->s) + strlen(str) + 1];
240 String operator+(const String& x, const String& y)
248 String operator+(const String& x, const char * y)
256 String operator+(const char * x, const String& y)
264 /* Shift operators */
267 String operator<<(const String &x, int n)
275 String & String::operator<<=(int n)
277 // Make sure we are the only one being shifted.
281 char *s = new char[strlen(p->s) + 1];
290 // Shift left means we really have to copy all characters.
292 int len = strlen(p->s);
297 // Shift more than we have: the String becomes empty.
302 for (i = 0; i <= len - n; i++)
311 String operator>>(const String &x, int n)
319 String & String::operator>>=(int n)
321 // Make sure we are the only one being shifted.
325 char *s = new char[strlen(p->s) + 1];
334 // Shift right is simple: just put the '\0' n places back.
337 int len = strlen(p->s);
341 // Shift more than we have: the String becomes empty.
346 p->s[len - n] = '\0';
352 /* Substring selection and assignment */
354 substring String::operator()(int start, int len)
359 _start = start; // Proper type conversion
361 if (_start >= strlen(p->s) || _start + len >= strlen(p->s))
363 throw StringException("Substring Out of bounds: ("
364 + String(start) + ", " + String(len) + ")");
372 String& substring::operator=(const String &x)
374 char *s = new char[strlen(x.p->s) + ~*str - len + 1];
376 strncpy(s, str->p->s, start);
379 strcat(s, str->p->s+start+len);
384 /* Input and output */
386 std::ostream& operator<<(std::ostream& s, const String& x)
393 std::istream& operator>>(std::istream& s, String& x)
400 buf = new char[bufsize];
407 // Buffer is too small. Allocate some new space.
409 char *newbuf = new char[bufsize * 2];
410 memcpy(newbuf, buf, bufsize);
419 while (s && buf[i] != '\n');
432 * The subscript operator is provided for access to individual characters
435 // TODO: Assignment to an individual character does not decouple references (BUG)
437 char& String::operator[](size_t i)
439 if (i >= strlen(p->s))
441 throw StringException("Out of bounds: " + String((int)i));
447 String String::upper()
452 up.p->s = new char[strlen(p->s)+1];
454 for(i=0; p->s[i]; i++)
456 up.p->s[i] = toupper(p->s[i]);
463 String String::lower()
468 low.p->s = new char[strlen(p->s)+1];
470 for(i=0; p->s[i]; i++)
472 low.p->s[i] = tolower(p->s[i]);
479 String String::escape()
481 const int BUFSIZE = 500;
483 char buffer[BUFSIZE];
485 int i; // Index in buffer[]
486 int j; // Index in *this
489 for (j = 0; p->s[j] != '\0'; j++)
550 if (p->s[j] > '\x20' && p->s[j] < '\x7F')
552 buffer[i++] = p->s[j];
558 // Turn into hexadecimal representation
562 nibble = (p->s[j] >> 4) & 0x0f;
563 buffer[i++] = nibble < 10 ? nibble + '0' : nibble - 10 + 'A';
564 nibble = p->s[j] & 0x0f;
565 buffer[i++] = nibble < 10 ? nibble + '0' : nibble - 10 + 'A';
577 String String::unescape()
582 unescaped.p->s = new char[strlen(p->s)+1];
643 while (*s >= '0' && *s <= '7')
654 s++; // Skip the initial 'x'
658 *d += *s > '9' ? toupper(*s) - 'A' + 10 : *s - '0';
681 // Find the first occurance of 'c'
683 int String::index(char c)
687 found = strchr(p->s, c);
694 // Find the last occurance of 'c'
696 int String::rindex(char c)
700 found = strrchr(p->s, c);
707 /* In: see if I am part of x, return -1 if not found */
709 int String::in(String & x)
713 match = strstr(x.p->s, p->s);
715 return match - x.p->s;
720 SuperString String::split(const String &separator)
722 SuperString splitted;
726 sep = strstr(p->s, separator.p->s);
730 // Create a new string from the part until the separator
732 int len = sep - part;
733 char *str = new char[len + 1];
735 strncpy(str, part, len);
737 splitted += String(str);
739 // Look for the next separator
743 sep = strstr(sep, separator.p->s);
746 // Add the leftover after the last separator.
748 splitted += String(part);