/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * (C) Copyright The MITRE Corporation 1999 All rights reserved. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * The program provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * The Copyright owner will not be liable for any damages suffered by * you as a result of using the Program. In no event will the Copyright * owner be liable for any special, indirect or consequential damages or * lost profits even if the Copyright owner has been advised of the * possibility of their occurrence. * * Contributor(s): * * Tom Kneeland * -- original author. * * Keith Visco * Larry Fitzpatrick * */ #include "TxString.h" #include #include String::String() : mBuffer(0), mBufferLength(0), mLength(0) { } String::String(const String& aSource) : mBuffer(aSource.toUnicode()), mBufferLength(aSource.mLength), mLength(aSource.mLength) { } String::String(const UNICODE_CHAR* aSource, PRUint32 aLength) : mBuffer(0), mBufferLength(0), mLength(0) { if (!aSource) { return; } if (aLength == 0) { aLength = unicodeLength(aSource); } if (!ensureCapacity(aLength)) { return; } memcpy(mBuffer, aSource, aLength * sizeof(UNICODE_CHAR)); mLength = aLength; } String::~String() { delete [] mBuffer; } void String::append(UNICODE_CHAR aSource) { if (!ensureCapacity(1)) { return; } mBuffer[mLength] = aSource; ++mLength; } void String::append(const String& aSource) { if (!ensureCapacity(aSource.mLength)) { return; } memcpy(&mBuffer[mLength], aSource.mBuffer, aSource.mLength * sizeof(UNICODE_CHAR)); mLength += aSource.mLength; } void String::append(const UNICODE_CHAR* aSource, PRUint32 aLength) { if (!ensureCapacity(aLength)) { return; } memcpy(&mBuffer[mLength], aSource, aLength * sizeof(UNICODE_CHAR)); mLength += aLength; } void String::insert(PRUint32 aOffset, UNICODE_CHAR aSource) { if (!ensureCapacity(1)) { return; } if (aOffset < mLength) { memmove(&mBuffer[aOffset + 1], &mBuffer[aOffset], (mLength - aOffset) * sizeof(UNICODE_CHAR)); } mBuffer[aOffset] = aSource; mLength += 1; } void String::insert(PRUint32 aOffset, const String& aSource) { if (!ensureCapacity(aSource.mLength)) { return; } if (aOffset < mLength) { memmove(&mBuffer[aOffset + aSource.mLength], &mBuffer[aOffset], (mLength - aOffset) * sizeof(UNICODE_CHAR)); } memcpy(&mBuffer[aOffset], aSource.mBuffer, aSource.mLength * sizeof(UNICODE_CHAR)); mLength += aSource.mLength; } void String::replace(PRUint32 aOffset, UNICODE_CHAR aSource) { if (aOffset < mLength) { mBuffer[aOffset] = aSource; } else { append(aSource); } } void String::replace(PRUint32 aOffset, const String& aSource) { if (aOffset < mLength) { PRUint32 finalLength = aOffset + aSource.mLength; if (finalLength > mLength) { if (!ensureCapacity(finalLength - mBufferLength)) { return; } mLength = finalLength; } memcpy(&mBuffer[aOffset], aSource.mBuffer, aSource.mLength * sizeof(UNICODE_CHAR)); } else { append(aSource); } } void String::deleteChars(PRUint32 aOffset, PRUint32 aCount) { PRUint32 cutEnd = aOffset + aCount; if (cutEnd < mLength) { memmove(&mBuffer[aOffset], &mBuffer[cutEnd], (mLength - cutEnd) * sizeof(UNICODE_CHAR)); mLength -= aCount; } else { mLength = aOffset; } } void String::clear() { mLength = 0; } PRInt32 String::indexOf(UNICODE_CHAR aData, PRInt32 aOffset) const { NS_ASSERTION(aOffset >= 0, "Passed negative offset to indexOf."); if (aOffset < 0) { return kNotFound; } PRInt32 searchIndex = aOffset; while (searchIndex < (PRInt32)mLength) { if (mBuffer[searchIndex] == aData) { return searchIndex; } ++searchIndex; } return kNotFound; } PRInt32 String::indexOf(const String& aData, PRInt32 aOffset) const { NS_ASSERTION(aOffset >= 0, "Passed negative offset to indexOf."); if (aOffset < 0) { return kNotFound; } PRInt32 searchIndex = aOffset; PRInt32 searchLimit = mLength - aData.mLength; while (searchIndex <= searchLimit) { if (memcmp(&mBuffer[searchIndex], aData.mBuffer, aData.mLength * sizeof(UNICODE_CHAR)) == 0) { return searchIndex; } ++searchIndex; } return kNotFound; } PRInt32 String::lastIndexOf(UNICODE_CHAR aData, PRInt32 aOffset) const { NS_ASSERTION(aOffset >= 0, "Passed negative offset to lastIndexOf."); if (aOffset < 0) { return kNotFound; } PRUint32 searchIndex = mLength - aOffset; while (--searchIndex >= 0) { if (mBuffer[searchIndex] == aData) { return searchIndex; } } return kNotFound; } MBool String::isEqual(const String& aData) const { if (mLength != aData.mLength) { return MB_FALSE; } return (memcmp(mBuffer, aData.mBuffer, mLength * sizeof(UNICODE_CHAR)) == 0); } MBool String::isEqualIgnoreCase(const String& aData) const { if (mLength != aData.mLength) { return MB_FALSE; } UNICODE_CHAR thisChar, otherChar; PRUint32 compLoop = 0; while (compLoop < mLength) { thisChar = mBuffer[compLoop]; if ((thisChar >= 'A') && (thisChar <= 'Z')) { thisChar += 32; } otherChar = aData.mBuffer[compLoop]; if ((otherChar >= 'A') && (otherChar <= 'Z')) { otherChar += 32; } if (thisChar != otherChar) { return MB_FALSE; } ++compLoop; } return MB_TRUE; } void String::truncate(PRUint32 aLength) { NS_ASSERTION(aLength <= mBufferLength, "truncate can't increase buffer"); mLength = (aLength > mBufferLength) ? mBufferLength : aLength; } String& String::subString(PRUint32 aStart, String& aDest) const { return subString(aStart, mLength, aDest); } String& String::subString(PRUint32 aStart, PRUint32 aEnd, String& aDest) const { PRUint32 end = (aEnd > mLength) ? mLength : aEnd; aDest.clear(); if (aStart >= end) { return aDest; } PRUint32 substrLength = end - aStart; if (!aDest.ensureCapacity(substrLength)) { return aDest; } memcpy(aDest.mBuffer, &mBuffer[aStart], substrLength * sizeof(UNICODE_CHAR)); aDest.mLength = substrLength; return aDest; } void String::toLowerCase() { PRUint32 conversionLoop; for (conversionLoop = 0; conversionLoop < mLength; ++conversionLoop) { if ((mBuffer[conversionLoop] >= 'A') && (mBuffer[conversionLoop] <= 'Z')) mBuffer[conversionLoop] += 32; } } void String::toUpperCase() { PRUint32 conversionLoop; for (conversionLoop = 0; conversionLoop < mLength; ++conversionLoop) { if ((mBuffer[conversionLoop] >= 'a') && (mBuffer[conversionLoop] <= 'z')) mBuffer[conversionLoop] -= 32; } } String& String::operator = (const String& aSource) { delete [] mBuffer; mBuffer = aSource.toUnicode(); mBufferLength = aSource.mLength; mLength = aSource.mLength; return *this; } MBool String::ensureCapacity(PRUint32 aCapacity) { PRUint32 needed = aCapacity + mLength; if (needed >= 0x8000) { NS_ASSERTION(0, "Asked for too large a buffer."); return MB_FALSE; } if (needed < mBufferLength) { return MB_TRUE; } UNICODE_CHAR* tempBuffer = new UNICODE_CHAR[needed]; NS_ASSERTION(tempBuffer, "Couldn't allocate string buffer."); if (!tempBuffer) { return MB_FALSE; } if (mLength > 0) { memcpy(tempBuffer, mBuffer, mLength * sizeof(UNICODE_CHAR)); } delete [] mBuffer; mBuffer = tempBuffer; mBufferLength = needed; return MB_TRUE; } UNICODE_CHAR* String::toUnicode() const { if (mLength == 0) { return 0; } UNICODE_CHAR* tmpBuffer = new UNICODE_CHAR[mLength]; NS_ASSERTION(tmpBuffer, "out of memory"); if (tmpBuffer) { memcpy(tmpBuffer, mBuffer, mLength * sizeof(UNICODE_CHAR)); } return tmpBuffer; } PRUint32 String::unicodeLength(const UNICODE_CHAR* aData) { PRUint32 index = 0; // Count UNICODE_CHARs Until a Unicode "NULL" is found. while (aData[index] != 0x0000) { ++index; } return index; } ostream& operator<<(ostream& aOutput, const String& aSource) { PRUint32 outputLoop; for (outputLoop = 0; outputLoop < aSource.mLength; ++outputLoop) { aOutput << (char)aSource.charAt(outputLoop); } return aOutput; } // XXX DEPRECATED String::String(PRUint32 aSize) : mBuffer(0), mBufferLength(0), mLength(0) { ensureCapacity(aSize); } String::String(const char* aSource) : mBuffer(0), mBufferLength(0), mLength(0) { if (!aSource) { return; } PRUint32 length = strlen(aSource); if (!ensureCapacity(length)) { return; } PRUint32 counter; for (counter = 0; counter < length; ++counter) { mBuffer[counter] = (UNICODE_CHAR)aSource[counter]; } mLength = length; } void String::append(const char* aSource) { if (!aSource) { return; } PRUint32 length = strlen(aSource); if (!ensureCapacity(length)) { return; } PRUint32 counter; for (counter = 0; counter < length; ++counter) { mBuffer[mLength + counter] = (UNICODE_CHAR)aSource[counter]; } mLength += length; } MBool String::isEqual(const char* aData) const { if (!aData) { return MB_FALSE; } PRUint32 length = strlen(aData); if (length != mLength) { return MB_FALSE; } PRUint32 counter; for (counter = 0; counter < length; ++counter) { if (mBuffer[counter] != (UNICODE_CHAR)aData[counter]) { return MB_FALSE; } } return MB_TRUE; } NS_ConvertASCIItoUCS2::NS_ConvertASCIItoUCS2(const char* aSource) { NS_ASSERTION(aSource, "can't convert a null to UCS2"); PRUint32 length = strlen(aSource); if (!ensureCapacity(length)) { return; } PRUint32 counter; for (counter = 0; counter < length; ++counter) { mBuffer[counter] = (UNICODE_CHAR)aSource[counter]; } mLength = length; }