+++ /dev/null
-/**************************************************************************
-** (c) Copyright 1997, Andromeda Technology & Automation
-***************************************************************************
-** MODULE INFORMATION *
-***********************
-** FILE NAME : string.cpp
-** SYSTEM NAME : Andromeda X-Windows Encapsulation
-** VERSION NUMBER : $Revision: 1.5 $
-**
-** DESCRIPTION : String class implementation.
-**
-** EXPORTED OBJECTS :
-** LOCAL OBJECTS :
-** MODULES USED :
-***************************************************************************
-** ADMINISTRATIVE INFORMATION *
-********************************
-** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
-** CREATION DATE : Nov 17, 1997
-** LAST UPDATE : Nov 30, 2003
-** MODIFICATIONS :
-**************************************************************************/
-
-/*****************************
- $Log: string.cpp,v $
- Revision 1.5 2007-05-04 13:55:18 arjen
- Dynamically allocate more memory if the string buffer runs out of space when
- reading a String object from an input stream.
-
- Revision 1.4 2003/03/29 07:18:54 arjen
- String constructor and assignment from char * are more robust fro NULL pointers.
-
- Revision 1.3 2002/11/03 13:18:57 arjen
- New functions - String::escape() and String::unescape()
-
- Revision 1.2 2002/09/28 06:42:11 arjen
- A few small bug fixes.
-
- Revision 1.1 2002/07/25 08:01:27 arjen
- First checkin, AXE release 0.2
-
-*****************************/
-
-static const char RCSID[] = "$Id: string.cpp,v 1.5 2007-05-04 13:55:18 arjen Exp $";
-
-#include <stdio.h>
-#include <ctype.h>
-#include "String.h"
-
- // Constructors and destructors for the String class
-
-String::String() // Create an empty String
-{
- p = new srep;
- p->s = 0;
- p->n = 1;
-}
-
-String::String(char c) // Create a String from a char
-{
- p = new srep;
- p->s = new char[2];
- p->s[0] = c;
- p->s[1] = '\0';
- p->n = 1;
-}
-
-String::String(const char *s) // Create a String from a char *
-{
- p = new srep;
-
- p->s = 0;
- p->n = 1;
-
- if (s != 0)
- {
- p->s = new char[strlen(s)+1];
- strcpy(p->s, s);
- p->n = 1;
- }
-}
-
-String::String(const String& x) // Create a String from another String
-{
- x.p->n++;
- p = x.p;
-}
-
-String::String(const substring &x)
-{
- p = new srep;
-
- p->s = new char[x.len+1];
- strncpy(p->s, x.str->p->s+x.start, x.len);
- p->s[x.len] = '\0'; // strncpy does not add the \0
- p->n = 1;
-}
-
-String::~String()
-{
- if (--p->n == 0)
- {
- delete p->s;
- delete p;
- }
-}
-
-/*
- * Assignment operators must handle cleanup of their left-hand operand.
- */
-
-String& String::operator=(const char c)
-{
- if (p->n > 1)
- { // Dsiconnect self
- p->n--;
- p = new srep;
- }
- else if (p->n == 1)
- delete p->s;
-
- p->s = new char[2];
- p->s[0] = c;
- p->s[1] = '\0';
- p->n = 1;
- return *this;
-}
-
-String& String::operator=(const char *s)
-{
- if (p->n > 1)
- { // Disconnect self
- p->n--;
- p = new srep;
- }
- else if (p->n == 1)
- delete p->s;
-
- if (s != 0)
- {
- p->s = new char[strlen(s)+1];
- strcpy(p->s, s);
- p->n = 1;
- }
- return *this;
-}
-
-/* Make sure that assignment of an object to itself works correctly: */
-
-String& String::operator=(const String& x)
-{
- x.p->n++;
- if (--p->n == 0)
- {
- delete p->s;
- delete p;
- }
-
- p = x.p;
- return *this;
-}
-
-/* Numerical conversion */
-
-String::String(int i)
-{
- p = new srep;
- p->s = new char[15]; // A little longer than needed...
- sprintf(p->s, "%d", i);
- p->n = 1;
-}
-
-String::String(long i)
-{
- p = new srep;
- p->s = new char[15]; // A little longer than needed...
- sprintf(p->s, "%ld", i);
- p->n = 1;
-}
-
-String::String(unsigned long i)
-{
- p = new srep;
- p->s = new char[15]; // A little longer than needed...
- sprintf(p->s, "%lu", i);
- p->n = 1;
-}
-
-String::String(double d)
-{
- p = new srep;
- p->s = new char[25]; // A little longer than needed...
- sprintf(p->s, "%.3f", d);
- p->n = 1;
-}
-
-/* String concatenation */
-
-String& String::operator+=(const String& x)
-{
- char *s = new char[strlen(p->s) + strlen(x.p->s) + 1];
-
- strcpy(s, p->s);
- strcat(s, x.p->s);
-
- if (p->n > 1)
- { // Disconnect self
- p->n--;
- p = new srep;
- }
- else if (p->n == 1)
- delete p->s;
-
- p->s = s;
- p->n = 1;
- return *this;
-}
-
-String& String::operator+=(const char * str)
-{
- char *s = new char[strlen(p->s) + strlen(str) + 1];
-
- strcpy(s, p->s);
- strcat(s, str);
-
- if (p->n > 1)
- { // Disconnect self
- p->n--;
- p = new srep;
- }
- else if (p->n == 1)
- delete p->s;
-
- p->s = s;
- p->n = 1;
- return *this;
-}
-
-String operator+(const String& x, const String& y)
-{
- String cat = x;
-
- cat += y;
- return cat;
-}
-
-String operator+(const String& x, const char * y)
-{
- String cat = x;
-
- cat += y;
- return cat;
-}
-
-String operator+(const char * x, const String& y)
-{
- String cat = x;
-
- cat += y;
- return cat;
-}
-
-/* Shift operators */
-
-
-String operator<<(const String &x, int n)
-{
- String s(x);
-
- s <<= n;
- return s;
-}
-
-String & String::operator<<=(int n)
-{
- // Make sure we are the only one being shifted.
-
- if (p->n > 1)
- { // Disconnect self
- char *s = new char[strlen(p->s) + 1];
-
- strcpy(s, p->s);
- p->n--;
- p = new srep;
- p->s = s;
- p->n = 1;
- }
-
- // Shift left means we really have to copy all characters.
-
- int len = strlen(p->s);
- int i;
-
- if (n >= len)
- {
- // Shift more than we have: the String becomes empty.
- p->s[0] = '\0';
- }
- else
- {
- for (i = 0; i <= len - n; i++)
- {
- p->s[i] = p->s[i+n];
- }
- }
-
- return *this;
-}
-
-String operator>>(const String &x, int n)
-{
- String s(x);
-
- s >>= n;
- return s;
-}
-
-String & String::operator>>=(int n)
-{
- // Make sure we are the only one being shifted.
-
- if (p->n > 1)
- { // Disconnect self
- char *s = new char[strlen(p->s) + 1];
-
- strcpy(s, p->s);
- p->n--;
- p = new srep;
- p->s = s;
- p->n = 1;
- }
-
- // Shift right is simple: just put the '\0' n places back.
-
-
- int len = strlen(p->s);
-
- if (n >= len)
- {
- // Shift more than we have: the String becomes empty.
- p->s[0] = '\0';
- }
- else
- {
- p->s[len - n] = '\0';
- }
-
- return *this;
-}
-
-/* Substring selection and assignment */
-
-substring String::operator()(int start, int len)
-{
- substring sub;
-
- sub.str = this;
- sub.start = start;
- sub.len = len;
- return sub;
-}
-
-String& substring::operator=(const String &x)
-{
- char *s = new char[strlen(x.p->s) + ~*str - len + 1];
-
- strncpy(s, str->p->s, start);
- s[start] = '\0';
- strcat(s, x.p->s);
- strcat(s, str->p->s+start+len);
-
- return *str = s;
-}
-
-/* Input and output */
-
-std::ostream& operator<<(std::ostream& s, const String& x)
-{
- if (x.p->s)
- s << x.p->s;
- return s;
-}
-
-std::istream& operator>>(std::istream& s, String& x)
-{
- char *buf;
- int i;
-
- int bufsize = 1024;
-
- buf = new char[bufsize];
-
- i = -1;
- do
- {
- if (i >= bufsize)
- {
- // Buffer is too small. Allocate some new space.
-
- char *newbuf = new char[bufsize * 2];
- memcpy(newbuf, buf, bufsize);
- delete [] buf;
- buf = newbuf;
- bufsize *= 2;
- }
-
- i++;
- s.get(buf[i]);
- }
- while (s && buf[i] != '\n');
- if (buf[i] == '\n')
- {
- buf[i] = '\0';
- }
- x = buf;
-
- delete [] buf;
-
- return s;
-}
-
-/*
- * The subscript operator is provided for access to individual characters
- */
-
-char& String::operator[](int i)
-{
- return p->s[i];
-}
-
-String String::upper()
-{
- String up;
- int i;
-
- up.p->s = new char[strlen(p->s)+1];
-
- for(i=0; p->s[i]; i++)
- {
- up.p->s[i] = toupper(p->s[i]);
- }
- up.p->s[i] = '\0';
-
- return up;
-}
-
-String String::lower()
-{
- String low;
- int i;
-
- low.p->s = new char[strlen(p->s)+1];
-
- for(i=0; p->s[i]; i++)
- {
- low.p->s[i] = tolower(p->s[i]);
- }
- low.p->s[i] = '\0';
-
- return low;
-}
-
-String String::escape()
-{
- const int BUFSIZE = 500;
-
- char buffer[BUFSIZE];
- String escaped = "";
- int i; // Index in buffer[]
- int j; // Index in *this
-
- i = 0;
- for (j = 0; p->s[j] != '\0'; j++)
- {
- if (i + 5 > BUFSIZE)
- {
- escaped += buffer;
- i = 0;
- }
-
- switch (p->s[j])
- {
- case '\a':
- buffer[i++] = '\\';
- buffer[i++] = 'a';
- break;
-
- case '\b':
- buffer[i++] = '\\';
- buffer[i++] = 'b';
- break;
-
- case '\f':
- buffer[i++] = '\\';
- buffer[i++] = 'f';
- break;
-
- case '\n':
- buffer[i++] = '\\';
- buffer[i++] = 'n';
- break;
-
- case '\r':
- buffer[i++] = '\\';
- buffer[i++] = 'r';
- break;
-
- case '\t':
- buffer[i++] = '\\';
- buffer[i++] = 't';
- break;
-
- case '\v':
- buffer[i++] = '\\';
- buffer[i++] = 'v';
- break;
-
- case '\'':
- buffer[i++] = '\\';
- buffer[i++] = '\'';
- break;
-
- case '"':
- buffer[i++] = '\\';
- buffer[i++] = '"';
- break;
-
- case '\\':
- buffer[i++] = '\\';
- buffer[i++] = '\\';
- break;
-
- default:
- if (p->s[j] > '\x20' && p->s[j] < '\x7F')
- {
- buffer[i++] = p->s[j];
- }
- else
- {
- short nibble;
-
- // Turn into hexadecimal representation
-
- buffer[i++] = '\\';
- buffer[i++] = 'x';
- nibble = (p->s[j] >> 4) & 0x0f;
- buffer[i++] = nibble < 10 ? nibble + '0' : nibble - 10 + 'A';
- nibble = p->s[j] & 0x0f;
- buffer[i++] = nibble < 10 ? nibble + '0' : nibble - 10 + 'A';
- }
- break;
- }
- }
-
- buffer[i] = '\0';
- escaped += buffer;
-
- return escaped;
-}
-
-String String::unescape()
-{
- String unescaped;
- char *s, *d;
-
- unescaped.p->s = new char[strlen(p->s)+1];
- s = p->s;
- d = unescaped.p->s;
-
- while (*s != '\0')
- {
- if (*s == '\\')
- {
- s++;
-
- switch (*s)
- {
- case 'a':
- *d = '\a';
- break;
-
- case 'b':
- *d = '\b';
- break;
-
- case 'f':
- *d = '\f';
- break;
-
- case 'n':
- *d = '\n';
- break;
-
- case 'r':
- *d = '\r';
- break;
-
- case 't':
- *d = '\t';
- break;
-
- case 'v':
- *d = '\v';
- break;
-
- case '\'':
- *d = '\'';
- break;
-
- case '"':
- *d = '"';
- break;
-
- case '\\':
- *d = '\\';
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- *d = 0;
- while (*s >= '0' && *s <= '7')
- {
- *d *= 8;
- *d += *s - '0';
- s++;
- }
- s--;
- break;
-
- case 'x':
- *d = 0;
- s++; // Skip the initial 'x'
- while (isxdigit(*s))
- {
- *d *= 16;
- *d += *s > '9' ? toupper(*s) - 'A' + 10 : *s - '0';
- s++;
- }
- s--;
- break;
-
- default:
- *d = *s;
- break;
- }
- }
- else
- {
- *d = *s;
- }
- s++;
- d++;
- }
-
- return unescaped;
-}
-
-
-// Find the first occurance of 'c'
-
-int String::index(char c)
-{
- char *found;
-
- found = strchr(p->s, c);
- if (found)
- return found - p->s;
- else
- return -1;
-}
-
-// Find the last occurance of 'c'
-
-int String::rindex(char c)
-{
- char *found;
-
- found = strrchr(p->s, c);
- if (found)
- return found - p->s;
- else
- return -1;
-}
-
-/* In: see if I am part of x, return -1 if not found */
-
-int String::in(String & x)
-{
- char *match;
-
- match = strstr(x.p->s, p->s);
- if (match)
- return match - x.p->s;
- else
- return -1;
-}