/*
- * Copyright (c) 2002, Robert Collins.
+ * Copyright 2005-2006, Various Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* A copy of the GNU General Public License can be found at
* http://www.gnu.org/
- *
- * Written by Robert Collins.
- *
*/
-// A String class to replace all the char * manipulation.
-
#include "String++.h"
#include <string.h>
-#include <ctype.h>
-#include "concat.h"
-#include "io_stream.h"
-#include <iostream>
-
-// _data
-
-String::_data::_data(_data const &aData) : count (1), theString (new unsigned char[aData.length]), cstr(0), length (aData.length) {
- memcpy (theString, aData.theString, aData.length);
-}
-
-String::_data::_data(): count (1), theString(new unsigned char[0]), cstr (0), length (0) {}
-String::_data::_data(size_t aLength): count (1), theString(new unsigned char[aLength]), cstr(0), length (aLength) {}
-String::_data::~_data ()
-{
- if (theString)
- delete[] theString;
- if (cstr)
- delete[] cstr;
-}
-
-//String
-
-String::String (const char *acString) : theData (new _data(acString ? strlen(acString) : 0))
-{
- memcpy (theData->theString, acString, theData->length);
-}
-
-String::~String ()
-{
- if (--theData->count == 0)
- delete theData;
-}
-
-// able to cache the result if needed.
-char *
-String::cstr ()
-{
- if (theData->length == 0)
- return NULL;
- char * tempcStr =new char[theData->length + 1];
- // remove when exceptions are done
- if (!tempcStr)
- exit (100);
- tempcStr[theData->length] = '\0';
- memcpy (tempcStr, theData->theString, theData->length);
- return tempcStr;
-}
+#include <sstream>
+#include <algorithm>
char *
-String::cstr () const
+new_cstr_char_array (const std::string &s)
{
- if (theData->length == 0)
- return NULL;
- char * tempcStr =new char[theData->length + 1];
- // remove when exceptions are done
- if (!tempcStr)
- exit (100);
- tempcStr[theData->length] = '\0';
- memcpy (tempcStr, theData->theString, theData->length);
- return tempcStr;
+ size_t len = s.size();
+ char *buf = new char[len + 1];
+ if (len)
+ memcpy(buf, s.c_str(), len);
+ buf[len] = 0;
+ return buf;
}
-// able to cache the result if needed.
-char const *
-String::cstr_oneuse () const
+std::string
+format_1000s (int num, char sep)
{
- if (theData->length == 0)
- return NULL;
- if (theData->cstr)
- delete[] theData->cstr;
- theData->cstr = new char[theData->length + 1];
- theData->cstr[theData->length] = '\0';
- memcpy (theData->cstr, theData->theString, theData->length);
- return theData->cstr;
+ int mult = 1;
+ while (mult * 1000 < num)
+ mult *= 1000;
+ std::ostringstream os;
+ os << ((num / mult) % 1000);
+ for (mult /= 1000; mult > 0; mult /= 1000)
+ {
+ int triplet = (num / mult) % 1000;
+ os << sep;
+ if (triplet < 100) os << '0';
+ if (triplet < 10) os << '0';
+ os << triplet;
+ }
+ return os.str();
}
-// does this character exist in the string?
-// 0 is false, 1 is the first position...
-// XXX FIXME: Introduce npos, and change all
-// if (size) calls to be if (size()==npos)
-size_t
-String::find(char aChar) const
+std::string
+stringify (int num)
{
- for (size_t i=0; i < theData->length; ++i)
- if (theData->theString[i] == aChar)
- return i+1;
- return 0;
+ std::ostringstream os;
+ os << num;
+ return os.str();
}
int
-String::compare (String const &aString, size_t const count) const
+casecompare (const std::string& a, const std::string& b, size_t limit)
{
- // trivial cases:
- if (theData == aString.theData)
- return 0;
- size_t length = count ? count : theData->length;
- if (length > theData->length)
- length = theData->length;
- if (length > aString.theData->length)
- length = aString.theData->length;
- size_t i;
- for (i=0; i < length ; ++i)
- if (theData->theString[i] < aString.theData->theString[i])
- return -1;
- else if (theData->theString[i] > aString.theData->theString[i])
- return 1;
- // equal for length
- if (i == count && count != 0)
- return 0;
- if (theData->length < aString.theData->length)
- return -1;
- else if (theData->length > aString.theData->length)
- return 1;
- return 0;
-}
+ size_t length_to_check = std::min(a.length(), b.length());
+ if (limit && length_to_check > limit)
+ length_to_check = limit;
-int
-String::casecompare (String const &aString, size_t const count) const
-{
- // trivial cases:
- if (theData == aString.theData)
- return 0;
- size_t length = count ? count : theData->length;
- if (length > theData->length)
- length = theData->length;
- if (length > aString.theData->length)
- length = aString.theData->length;
size_t i;
- for (i=0; i < length; ++i)
- if (toupper(theData->theString[i]) < toupper(aString.theData->theString[i]))
+ for (i = 0; i < length_to_check; ++i)
+ if (toupper(a[i]) < toupper(b[i]))
return -1;
- else if (toupper(theData->theString[i]) > toupper(aString.theData->theString[i]))
+ else if (toupper(a[i]) > toupper(b[i]))
return 1;
- // equal for length
- if (i == count && count != 0)
+
+ // Hit the comparison limit without finding a difference
+ if (limit && i == limit)
return 0;
- if (theData->length < aString.theData->length)
+
+ if (a.length() < b.length())
return -1;
- else if (theData->length > aString.theData->length)
+ else if (a.length() > b.length())
return 1;
+
return 0;
}
-String &
-String::operator+= (String const &aString)
+std::string
+replace(const std::string& haystack, const std::string& needle,
+ const std::string& replacement)
{
- if (theData->count > 1)
+ std::string rv(haystack);
+ size_t n_len = needle.length(), r_len = replacement.length(),
+ search_start = 0;
+
+ while (true)
{
- _data * someData = new _data(*theData);
- --theData->count;
- theData = someData;
+ size_t pos = rv.find(needle, search_start);
+ if (pos == std::string::npos)
+ return rv;
+ rv.replace(pos, n_len, replacement);
+ search_start = pos + r_len;
}
-
- unsigned char *tempString = theData->theString;
- theData->theString = new unsigned char [theData->length + aString.theData->length];
- // remove when exceptions are done
- if (!theData->theString)
- exit (100);
- memcpy (theData->theString, tempString, theData->length);
- delete[] tempString;
- memcpy (&theData->theString[theData->length], aString.theData->theString, aString.theData->length);
- theData->length += aString.theData->length;
- return *this;
-}
-
-String
-String::operator + (String const &aString) const
-{
- unsigned char *tempcString = new unsigned char [theData->length + aString.theData->length];
- // remove when exceptions are done
- if (!tempcString)
- exit (100);
- memcpy (tempcString, theData->theString, theData->length);
- memcpy (&tempcString[theData->length], aString.theData->theString, aString.theData->length);
- return absorb (tempcString, theData->length + aString.theData->length);
-}
-
-String
-String::operator + (char const *aString) const
-{
- // expensive, but quick to code.
- return *this + String (aString);
-}
-
-bool
-String::operator == (String const &rhs) const
-{
- return compare (rhs) ? false : true;
-}
-
-bool
-String::operator == (char const *rhs) const
-{
- return compare (rhs) ? false : true;
-}
-
-String
-String::absorb (unsigned char *aString, size_t aLength)
-{
- String theString;
- theString.theData->theString = aString;
- theString.theData->length = aLength;
- return theString;
-}
-
-int
-String::casecompare (String const lhs, String const rhs)
-{
- return lhs.casecompare (rhs);
-}
-
-/* TODO: research how wide char and unicode interoperate with
- * C++ streams
- */
-ostream &
-operator << (ostream &os, String const &theString)
-{
- os << theString.cstr_oneuse();
- return os;
}