Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright (c) 1993-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <TCollection_ExtendedString.hxx>
#include <NCollection_UtfIterator.hxx>
#include <Standard.hxx>
#include <Standard_NullObject.hxx>
#include <Standard_OutOfRange.hxx>
#include <TCollection_AsciiString.hxx>
#include <algorithm>
#include <cstddef>
namespace
{
static char16_t THE_DEFAULT_EXT_CHAR_STRING[1] = {u'\0'};
//! Calculate padded allocation size for ExtendedString (2-byte characters)
//! Guarantees at least +1 character space for null terminator, aligned to 4-byte boundary
inline size_t calculatePaddedSize(const int theLength)
{
return (((theLength + 1) * sizeof(char16_t)) + 3) & ~0x3;
}
//! Returns the number of 16-bit code units in Unicode string
template <typename T>
static int nbSymbols(const T* theUtfString)
{
int aNbCodeUnits = 0;
for (NCollection_UtfIterator<T> anIter(theUtfString); *anIter != 0; ++anIter)
{
aNbCodeUnits += anIter.AdvanceCodeUnitsUtf16();
}
return aNbCodeUnits;
}
//! Convert from wchar_t* to extended string.
//! Default implementation when size of wchar_t and extended char is different (e.g. Linux / UNIX).
template <size_t CharSize>
inline char16_t* Standard_UNUSED fromWideString(const wchar_t* theUtfString, int& theLength)
{
theLength = nbSymbols(theUtfString);
if (theLength == 0)
{
return THE_DEFAULT_EXT_CHAR_STRING;
}
const size_t aRoundSize = calculatePaddedSize(theLength);
char16_t* aString = static_cast<char16_t*>(Standard::AllocateOptimal(aRoundSize));
NCollection_UtfIterator<wchar_t> anIterRead(theUtfString);
for (char16_t* anIterWrite = aString; *anIterRead != 0; ++anIterRead)
{
anIterWrite = anIterRead.GetUtf(anIterWrite);
}
aString[theLength] = 0;
return aString;
}
//! Use memcpy() conversion when size is the same (e.g. on Windows).
template <>
inline char16_t* Standard_UNUSED fromWideString<sizeof(char16_t)>(const wchar_t* theUtfString,
int& theLength)
{
for (theLength = 0; theUtfString[theLength] != 0; ++theLength)
{
}
if (theLength == 0)
{
return THE_DEFAULT_EXT_CHAR_STRING;
}
const size_t aRoundSize = calculatePaddedSize(theLength);
char16_t* aString = static_cast<char16_t*>(Standard::AllocateOptimal(aRoundSize));
const int aSize = theLength * sizeof(char16_t);
memcpy(aString, theUtfString, aSize);
aString[theLength] = 0;
return aString;
}
//! Helper structure to hold formatted integer string with its length
struct FormattedInteger
{
char Buffer[16]; // Enough for 32-bit int + sign + null terminator
int Length;
FormattedInteger(const int theValue) { Length = Sprintf(Buffer, "%d", theValue); }
};
//! Helper structure to hold formatted real number string with its length
struct FormattedReal
{
char Buffer[64]; // Enough for double in %g format + null terminator
int Length;
FormattedReal(const double theValue) { Length = Sprintf(Buffer, "%g", theValue); }
};
} // namespace
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString() noexcept
{
allocate(0);
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const char* const theString,
const bool theIsMultiByte)
{
if (theString == nullptr)
{
throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
}
if (theIsMultiByte)
{
allocate(nbSymbols(theString));
myString[myLength] = 0;
if (ConvertToUnicode(theString))
{
return;
}
reallocate((int)strlen(theString));
}
else
{
allocate((int)strlen(theString));
}
for (int aCharIter = 0; aCharIter < myLength; ++aCharIter)
{
myString[aCharIter] = ToExtCharacter(theString[aCharIter]);
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const char16_t* const theString)
{
if (theString == nullptr)
{
throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
}
for (myLength = 0; theString[myLength] != 0; ++myLength)
{
}
allocate(myLength);
memcpy(myString, theString, myLength * sizeof(char16_t));
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const char16_t* theString,
const int theLength)
{
if (theString == nullptr)
{
throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
}
if (theLength < 0)
{
throw Standard_OutOfRange("TCollection_ExtendedString : negative length");
}
allocate(theLength);
if (theLength > 0)
{
memcpy(myString, theString, theLength * sizeof(char16_t));
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const wchar_t* theStringUtf)
{
if (theStringUtf == nullptr)
{
throw Standard_NullObject("TCollection_ExtendedString : null parameter ");
}
myString = fromWideString<sizeof(wchar_t)>(theStringUtf, myLength);
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const char theChar)
{
if (theChar != '\0')
{
allocate(1);
myString[0] = ToExtCharacter(theChar);
}
else
{
allocate(0);
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const char16_t theChar)
{
if (theChar != u'\0')
{
allocate(1);
myString[0] = theChar;
}
else
{
allocate(0);
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const int theLength,
const char16_t theFiller)
{
if (theLength < 0)
{
throw Standard_OutOfRange("TCollection_ExtendedString : negative length");
}
allocate(theLength);
for (int i = 0; i < theLength; i++)
{
myString[i] = theFiller;
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const int theValue)
{
const FormattedInteger aFormatted(theValue);
allocate(aFormatted.Length);
for (int i = 0; i < myLength; i++)
{
myString[i] = ToExtCharacter(aFormatted.Buffer[i]);
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const double theValue)
{
const FormattedReal aFormatted(theValue);
allocate(aFormatted.Length);
for (int i = 0; i < myLength; i++)
{
myString[i] = ToExtCharacter(aFormatted.Buffer[i]);
}
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const TCollection_ExtendedString& theString)
{
allocate(theString.myLength);
memcpy(myString, theString.myString, myLength * sizeof(char16_t));
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(
TCollection_ExtendedString&& theOther) noexcept
{
if (theOther.myString == THE_DEFAULT_EXT_CHAR_STRING)
{
allocate(0);
}
else
{
myString = theOther.myString;
myLength = theOther.myLength;
}
theOther.myString = THE_DEFAULT_EXT_CHAR_STRING;
theOther.myLength = 0;
}
//=================================================================================================
TCollection_ExtendedString::TCollection_ExtendedString(const TCollection_AsciiString& theString,
const bool theIsMultiByte)
{
allocate(nbSymbols(theString.ToCString()));
if (theIsMultiByte && ConvertToUnicode(theString.ToCString()))
{
return;
}
reallocate(theString.Length());
const char* aCString = theString.ToCString();
for (int aCharIter = 0; aCharIter <= myLength; ++aCharIter)
{
myString[aCharIter] = ToExtCharacter(aCString[aCharIter]);
}
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const TCollection_ExtendedString& theOther)
{
if (theOther.myLength == 0)
{
return;
}
// Handle self-append case: theOther.myString will be invalidated by reallocate
if (&theOther == this)
{
const int anOldLength = myLength;
reallocate(myLength + myLength);
memcpy(myString + anOldLength, myString, anOldLength * sizeof(char16_t));
return;
}
const int anOtherLength = theOther.myLength;
const int anOldLength = myLength;
reallocate(myLength + anOtherLength);
memcpy(myString + anOldLength, theOther.myString, anOtherLength * sizeof(char16_t));
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const int theOther)
{
const FormattedInteger aFormatted(theOther);
const int anOldLength = myLength;
reallocate(myLength + aFormatted.Length);
for (int i = 0; i < aFormatted.Length; ++i)
{
myString[anOldLength + i] = ToExtCharacter(aFormatted.Buffer[i]);
}
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const char theChar)
{
AssignCat(ToExtCharacter(theChar));
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const double theOther)
{
const FormattedReal aFormatted(theOther);
const int anOldLength = myLength;
reallocate(myLength + aFormatted.Length);
for (int i = 0; i < aFormatted.Length; ++i)
{
myString[anOldLength + i] = ToExtCharacter(aFormatted.Buffer[i]);
}
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const char16_t theChar)
{
if (theChar != u'\0')
{
reallocate(myLength + 1);
myString[myLength - 1] = theChar;
}
}
//=================================================================================================
void TCollection_ExtendedString::AssignCat(const char16_t* theString, const int theLength)
{
if (theString == nullptr || theLength <= 0)
{
return;
}
// Check if theString points into current buffer (aliasing case)
const bool isAliased = (theString >= myString && theString < myString + myLength);
if (isAliased)
{
// Save offset before reallocate invalidates the pointer
const std::ptrdiff_t anOffset = theString - myString;
const int anOldLength = myLength;
reallocate(myLength + theLength);
// Use memmove since source and destination may overlap
memmove(myString + anOldLength, myString + anOffset, theLength * sizeof(char16_t));
}
else
{
const int anOldLength = myLength;
reallocate(myLength + theLength);
memcpy(myString + anOldLength, theString, theLength * sizeof(char16_t));
}
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Cat(const char16_t* theOther,
const int theLength) const
{
TCollection_ExtendedString aResult(myLength + theLength, 0);
if (myLength > 0)
{
memcpy(aResult.myString, myString, myLength * sizeof(char16_t));
}
if (theLength > 0)
{
memcpy(aResult.myString + myLength, theOther, theLength * sizeof(char16_t));
}
return aResult;
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Cat(const int theOther) const
{
const FormattedInteger aFormatted(theOther);
TCollection_ExtendedString aResult(myLength + aFormatted.Length, 0);
if (myLength > 0)
{
memcpy(aResult.myString, myString, myLength * sizeof(char16_t));
}
for (int i = 0; i < aFormatted.Length; ++i)
{
aResult.myString[myLength + i] = ToExtCharacter(aFormatted.Buffer[i]);
}
return aResult;
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Cat(const double theOther) const
{
const FormattedReal aFormatted(theOther);
TCollection_ExtendedString aResult(myLength + aFormatted.Length, 0);
if (myLength > 0)
{
memcpy(aResult.myString, myString, myLength * sizeof(char16_t));
}
for (int i = 0; i < aFormatted.Length; ++i)
{
aResult.myString[myLength + i] = ToExtCharacter(aFormatted.Buffer[i]);
}
return aResult;
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Cat(const char theChar) const
{
if (theChar == '\0')
{
return TCollection_ExtendedString(*this);
}
const char16_t anExt = ToExtCharacter(theChar);
TCollection_ExtendedString aResult(myLength + 1, 0);
if (myLength > 0)
{
memcpy(aResult.myString, myString, myLength * sizeof(char16_t));
}
aResult.myString[myLength] = anExt;
return aResult;
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Cat(const char16_t theChar) const
{
if (theChar == u'\0')
{
return TCollection_ExtendedString(*this);
}
TCollection_ExtendedString aResult(myLength + 1, 0);
if (myLength > 0)
{
memcpy(aResult.myString, myString, myLength * sizeof(char16_t));
}
aResult.myString[myLength] = theChar;
return aResult;
}
//=================================================================================================
void TCollection_ExtendedString::ChangeAll(const char16_t theChar, const char16_t theNewChar)
{
for (int i = 0; i < myLength; i++)
{
if (myString[i] == theChar)
{
myString[i] = theNewChar;
}
}
}
//=================================================================================================
void TCollection_ExtendedString::Clear()
{
deallocate();
}
//=================================================================================================
void TCollection_ExtendedString::Copy(const char16_t* theString, const int theLength)
{
if (theString == nullptr || theLength <= 0)
{
if (myString != THE_DEFAULT_EXT_CHAR_STRING)
{
myLength = 0;
myString[0] = 0;
}
return;
}
reallocate(theLength);
memcpy(myString, theString, theLength * sizeof(char16_t));
}
//=================================================================================================
void TCollection_ExtendedString::Move(TCollection_ExtendedString&& theOther)
{
if (&theOther == this)
{
return;
}
if (theOther.myString == THE_DEFAULT_EXT_CHAR_STRING)
{
reallocate(0);
}
else
{
if (myString != THE_DEFAULT_EXT_CHAR_STRING)
{
Standard::Free(myString);
}
myString = theOther.myString;
myLength = theOther.myLength;
}
theOther.myString = THE_DEFAULT_EXT_CHAR_STRING;
theOther.myLength = 0;
}
//=================================================================================================
void TCollection_ExtendedString::Swap(TCollection_ExtendedString& theOther)
{
if (&theOther == this)
{
return;
}
std::swap(myString, theOther.myString);
std::swap(myLength, theOther.myLength);
}
//=================================================================================================
TCollection_ExtendedString::~TCollection_ExtendedString()
{
deallocate();
}
//=================================================================================================
void TCollection_ExtendedString::Insert(const int theWhere, const char16_t theWhat)
{
if (theWhere > myLength + 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
"Parameter theWhere is too big");
}
if (theWhere < 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
"Parameter theWhere is out of range");
}
reallocate(myLength + 1);
if (theWhere != myLength)
{
for (int i = myLength - 2; i >= theWhere - 1; i--)
{
myString[i + 1] = myString[i];
}
}
myString[theWhere - 1] = theWhat;
}
//=================================================================================================
void TCollection_ExtendedString::Insert(const int theWhere,
const char16_t* theWhat,
const int theLength)
{
if (theWhere > myLength + 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
"Parameter theWhere is too big");
}
if (theWhere < 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Insert : "
"Parameter theWhere is out of range");
}
if (theWhat == nullptr || theLength <= 0)
{
return;
}
const int anOldLength = myLength;
reallocate(myLength + theLength);
if (theWhere != anOldLength + 1)
{
for (int i = anOldLength - 1; i >= theWhere - 1; i--)
{
myString[i + theLength] = myString[i];
}
}
for (int i = 0; i < theLength; i++)
{
myString[theWhere - 1 + i] = theWhat[i];
}
}
//=================================================================================================
bool TCollection_ExtendedString::IsEqual(const char16_t* const theOther, const int theLength) const
{
if (theLength < 0)
{
return false;
}
if (myLength != theLength)
{
return false;
}
if (theLength == 0)
{
return true;
}
if (theOther == nullptr)
{
return false;
}
return memcmp(myString, theOther, theLength * sizeof(char16_t)) == 0;
}
//=================================================================================================
bool TCollection_ExtendedString::IsDifferent(const char16_t* const theOther,
const int theLength) const
{
if (theLength < 0)
{
return true;
}
if (myLength != theLength)
{
return true;
}
if (theLength == 0)
{
return false;
}
if (theOther == nullptr)
{
return true;
}
return memcmp(myString, theOther, theLength * sizeof(char16_t)) != 0;
}
//=================================================================================================
bool TCollection_ExtendedString::IsLess(const char16_t* const theOther, const int theLength) const
{
if (theLength < 0)
{
return false; // this >= invalid
}
if (theOther == nullptr)
{
return theLength > 0 ? false : myLength < 0; // this >= empty/invalid
}
const int aMinLen = (myLength < theLength) ? myLength : theLength;
for (int i = 0; i < aMinLen; ++i)
{
if (myString[i] < theOther[i])
{
return true;
}
if (myString[i] > theOther[i])
{
return false;
}
}
return myLength < theLength;
}
//=================================================================================================
bool TCollection_ExtendedString::IsGreater(const char16_t* const theOther,
const int theLength) const
{
if (theLength < 0)
{
return true; // this > invalid
}
if (theOther == nullptr)
{
return theLength == 0 ? myLength > 0 : true; // this > empty/invalid
}
const int aMinLen = (myLength < theLength) ? myLength : theLength;
for (int i = 0; i < aMinLen; ++i)
{
if (myString[i] > theOther[i])
{
return true;
}
if (myString[i] < theOther[i])
{
return false;
}
}
return myLength > theLength;
}
//=================================================================================================
bool TCollection_ExtendedString::StartsWith(const char16_t* const theStartString,
const int theLength) const
{
if (theLength < 0)
{
return false;
}
if (theLength == 0)
{
return true;
}
if (theStartString == nullptr)
{
return false;
}
if (myLength < theLength)
{
return false;
}
return memcmp(myString, theStartString, theLength * sizeof(char16_t)) == 0;
}
//=================================================================================================
bool TCollection_ExtendedString::EndsWith(const char16_t* const theEndString,
const int theLength) const
{
if (theLength < 0)
{
return false;
}
if (theLength == 0)
{
return true;
}
if (theEndString == nullptr)
{
return false;
}
if (myLength < theLength)
{
return false;
}
return memcmp(myString + myLength - theLength, theEndString, theLength * sizeof(char16_t)) == 0;
}
//=================================================================================================
bool TCollection_ExtendedString::IsAscii() const
{
for (int i = 0; i < myLength; i++)
{
if (!IsAnAscii(myString[i]))
{
return false;
}
}
return true;
}
//=================================================================================================
int TCollection_ExtendedString::Length() const
{
return myLength;
}
//=================================================================================================
void TCollection_ExtendedString::Print(Standard_OStream& theStream) const
{
if (myLength > 0)
{
const TCollection_AsciiString aUtf8(myString);
theStream << aUtf8;
}
}
//=================================================================================================
Standard_OStream& operator<<(Standard_OStream& theStream,
const TCollection_ExtendedString& theString)
{
theString.Print(theStream);
return theStream;
}
//=================================================================================================
void TCollection_ExtendedString::RemoveAll(const char16_t theWhat)
{
if (myLength == 0)
{
return;
}
int c = 0;
for (int i = 0; i < myLength; i++)
{
if (myString[i] != theWhat)
{
myString[c++] = myString[i];
}
}
myLength = c;
myString[myLength] = u'\0';
}
//=================================================================================================
void TCollection_ExtendedString::Remove(const int theWhere, const int theHowMany)
{
if (theWhere < 1 || theWhere > myLength || theHowMany < 0 || theWhere + theHowMany > myLength + 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Remove: "
"Invalid parameters");
}
if (theHowMany == 0)
{
return;
}
for (int i = theWhere + theHowMany - 1, j = theWhere - 1; i < myLength; i++, j++)
{
myString[j] = myString[i];
}
myLength -= theHowMany;
myString[myLength] = u'\0';
}
//=================================================================================================
int TCollection_ExtendedString::Search(const char16_t* const theWhat, const int theLength) const
{
if (theWhat == nullptr || theLength <= 0)
{
return -1;
}
if (theLength > myLength)
{
return -1;
}
int k, j;
int i = 0;
bool find = false;
while (i < myLength - theLength + 1 && !find)
{
k = i++;
j = 0;
while (j < theLength && myString[k++] == theWhat[j++])
{
if (j == theLength)
{
find = true;
}
}
}
if (find)
{
return i;
}
return -1;
}
//=================================================================================================
int TCollection_ExtendedString::SearchFromEnd(const char16_t* const theWhat,
const int theLength) const
{
if (theWhat == nullptr || theLength <= 0)
{
return -1;
}
if (theLength > myLength)
{
return -1;
}
int k, j;
int i = myLength - 1;
bool find = false;
while (i >= theLength - 1 && !find)
{
k = i--;
j = theLength - 1;
while (j >= 0 && myString[k--] == theWhat[j--])
{
if (j == -1)
{
find = true;
}
}
}
if (find)
{
return i - theLength + 3;
}
return -1;
}
//=================================================================================================
void TCollection_ExtendedString::SetValue(const int theWhere, const char16_t theWhat)
{
if (theWhere > 0 && theWhere <= myLength)
{
myString[theWhere - 1] = theWhat;
}
else
{
throw Standard_OutOfRange("TCollection_ExtendedString::SetValue : parameter theWhere");
}
}
//=================================================================================================
void TCollection_ExtendedString::SetValue(const int theWhere,
const char16_t* const theWhat,
const int theLength)
{
if (theWhere < 1 || theWhere > myLength + 1)
{
throw Standard_OutOfRange("TCollection_ExtendedString::SetValue : parameter theWhere");
}
if (theWhat == nullptr || theLength <= 0)
{
return;
}
const int aNewEnd = theWhere - 1 + theLength;
if (aNewEnd > myLength)
{
reallocate(aNewEnd);
}
for (int i = 0; i < theLength; i++)
{
myString[theWhere - 1 + i] = theWhat[i];
}
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::SubString(const int theFromIndex,
const int theToIndex) const
{
if (theFromIndex < 1 || theFromIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::SubString : theFromIndex");
}
if (theToIndex < 1 || theToIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::SubString : theToIndex");
}
if (theFromIndex > theToIndex)
{
throw Standard_OutOfRange("TCollection_ExtendedString::SubString : theFromIndex > theToIndex");
}
const int aSubLen = theToIndex - theFromIndex + 1;
return TCollection_ExtendedString(myString + theFromIndex - 1, aSubLen);
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Split(const int theWhere)
{
if (theWhere >= 0 && theWhere < myLength)
{
TCollection_ExtendedString res(&myString[theWhere]);
Trunc(theWhere);
return res;
}
throw Standard_OutOfRange("TCollection_ExtendedString::Split index");
}
//=================================================================================================
TCollection_ExtendedString TCollection_ExtendedString::Token(const char16_t* const theSeparators,
const int theWhichOne) const
{
if (myLength == 0)
{
return TCollection_ExtendedString();
}
TCollection_ExtendedString res(myLength, 0);
if (!theSeparators)
{
throw Standard_NullObject("TCollection_ExtendedString::Token : "
"parameter 'theSeparators'");
}
int i, j, k, l;
char16_t* buftmp = res.myString;
char16_t aSep;
bool isSepFound = false, otherSepFound;
j = 0;
for (i = 0; i < theWhichOne && j < myLength; i++)
{
isSepFound = false;
k = 0;
buftmp[0] = 0;
// Avant de commencer il faut virer les saloperies devant
//
otherSepFound = true;
while (j < myLength && otherSepFound)
{
l = 0;
otherSepFound = false;
aSep = theSeparators[l];
while (aSep != 0)
{
if (aSep == myString[j])
{
aSep = 0;
otherSepFound = true;
}
else
{
aSep = theSeparators[l++];
}
}
if (otherSepFound)
{
j++;
}
}
while (!isSepFound && k < myLength && j < myLength)
{
l = 0;
aSep = theSeparators[l];
while (aSep != 0 && !isSepFound)
{
if (aSep == myString[j])
{
buftmp[k] = 0;
isSepFound = true;
}
else
{
buftmp[k] = myString[j];
}
l++;
aSep = theSeparators[l];
}
j++;
k++;
if (j == myLength)
{
buftmp[k] = 0;
}
}
}
if (i < theWhichOne)
{
res.myLength = 0;
res.myString[0] = 0;
}
else
{
for (res.myLength = 0; buftmp[res.myLength]; ++res.myLength)
{
;
}
res.myString[res.myLength] = u'\0';
}
return res;
}
//=================================================================================================
const char16_t* TCollection_ExtendedString::ToExtString() const
{
return myString;
}
//=================================================================================================
void TCollection_ExtendedString::Trunc(const int theHowMany)
{
if (theHowMany < 0 || theHowMany > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Trunc : "
"parameter 'theHowMany'");
}
myLength = theHowMany;
myString[myLength] = u'\0';
}
//=================================================================================================
char16_t TCollection_ExtendedString::Value(const int theWhere) const
{
if (theWhere > 0 && theWhere <= myLength)
{
if (myString)
{
return myString[theWhere - 1];
}
else
{
return 0;
}
}
throw Standard_OutOfRange("TCollection_ExtendedString::Value : "
"parameter theWhere");
}
//=================================================================================================
bool TCollection_ExtendedString::ConvertToUnicode(const char* theString)
{
NCollection_UtfIterator<char> anIterRead(theString);
char16_t* anIterWrite = myString;
if (*anIterRead == 0)
{
*anIterWrite = u'\0';
return true;
}
for (; *anIterRead != 0; ++anIterRead)
{
if (!anIterRead.IsValid())
{
return false;
}
anIterWrite = anIterRead.GetUtf(anIterWrite);
}
return true;
}
//=================================================================================================
int TCollection_ExtendedString::LengthOfCString() const
{
int aSizeBytes = 0;
for (NCollection_UtfIterator<char16_t> anIter(myString); *anIter != 0; ++anIter)
{
aSizeBytes += anIter.AdvanceBytesUtf8();
}
return aSizeBytes;
}
//=================================================================================================
int TCollection_ExtendedString::ToUTF8CString(Standard_PCharacter& theCString) const
{
NCollection_UtfIterator<char16_t> anIterRead(myString);
char* anIterWrite = theCString;
if (*anIterRead == 0)
{
*anIterWrite = '\0';
return 0;
}
for (; *anIterRead != 0; ++anIterRead)
{
anIterWrite = anIterRead.GetUtf(anIterWrite);
}
*anIterWrite = '\0';
return int(anIterWrite - theCString);
}
//=================================================================================================
void TCollection_ExtendedString::allocate(const int theLength)
{
myLength = theLength;
if (theLength == 0)
{
myString = THE_DEFAULT_EXT_CHAR_STRING;
}
else
{
const size_t aRoundSize = calculatePaddedSize(theLength);
myString = static_cast<char16_t*>(Standard::AllocateOptimal(aRoundSize));
myString[myLength] = u'\0';
}
}
//=================================================================================================
void TCollection_ExtendedString::reallocate(const int theLength)
{
if (theLength == 0)
{
// When shrinking to empty, just set length to 0 and null-terminate
if (myString != THE_DEFAULT_EXT_CHAR_STRING)
{
myString[0] = 0;
}
myLength = 0;
return;
}
if (myString == THE_DEFAULT_EXT_CHAR_STRING)
{
const size_t aRoundSize = calculatePaddedSize(theLength);
myString = static_cast<char16_t*>(Standard::AllocateOptimal(aRoundSize));
}
else
{
const size_t aRoundSize = calculatePaddedSize(theLength);
myString = static_cast<char16_t*>(Standard::Reallocate(myString, aRoundSize));
}
myString[theLength] = 0;
myLength = theLength;
}
//=================================================================================================
void TCollection_ExtendedString::deallocate()
{
if (myString != THE_DEFAULT_EXT_CHAR_STRING)
{
Standard::Free(myString);
}
myLength = 0;
myString = THE_DEFAULT_EXT_CHAR_STRING;
}
//=================================================================================================
const TCollection_ExtendedString& TCollection_ExtendedString::EmptyString() noexcept
{
static const TCollection_ExtendedString THE_EMPTY_STRING;
return THE_EMPTY_STRING;
}
//=================================================================================================
void TCollection_ExtendedString::LeftAdjust()
{
if (myLength == 0)
{
return;
}
int anIndex = 0;
while (anIndex < myLength && myString[anIndex] == u' ')
{
++anIndex;
}
if (anIndex > 0)
{
myLength -= anIndex;
memmove(myString, myString + anIndex, myLength * sizeof(char16_t));
myString[myLength] = u'\0';
}
}
//=================================================================================================
void TCollection_ExtendedString::RightAdjust()
{
if (myLength == 0)
{
return;
}
while (myLength > 0 && myString[myLength - 1] == u' ')
{
--myLength;
}
myString[myLength] = u'\0';
}
//=================================================================================================
void TCollection_ExtendedString::LeftJustify(const int theWidth, const char16_t theFiller)
{
if (theWidth < 0)
{
throw Standard_OutOfRange("TCollection_ExtendedString::LeftJustify : theWidth is negative");
}
if (theWidth > myLength)
{
const int anOldLength = myLength;
reallocate(theWidth);
for (int i = anOldLength; i < theWidth; ++i)
{
myString[i] = theFiller;
}
}
}
//=================================================================================================
void TCollection_ExtendedString::RightJustify(const int theWidth, const char16_t theFiller)
{
if (theWidth < 0)
{
throw Standard_OutOfRange("TCollection_ExtendedString::RightJustify : theWidth is negative");
}
if (theWidth > myLength)
{
const int aShift = theWidth - myLength;
const int anOldLen = myLength;
reallocate(theWidth);
// Move existing characters to the end
memmove(myString + aShift, myString, anOldLen * sizeof(char16_t));
// Fill the beginning with filler
for (int i = 0; i < aShift; ++i)
{
myString[i] = theFiller;
}
}
}
//=================================================================================================
void TCollection_ExtendedString::Center(const int theWidth, const char16_t theFiller)
{
if (theWidth < 0)
{
throw Standard_OutOfRange("TCollection_ExtendedString::Center : theWidth is negative");
}
if (theWidth > myLength)
{
const int aLeftShift = (theWidth - myLength) / 2;
const int aRightSpace = theWidth - myLength - aLeftShift;
const int anOldLen = myLength;
reallocate(theWidth);
// Move existing characters to the center
memmove(myString + aLeftShift, myString, anOldLen * sizeof(char16_t));
// Fill the beginning
for (int i = 0; i < aLeftShift; ++i)
{
myString[i] = theFiller;
}
// Fill the end
for (int i = 0; i < aRightSpace; ++i)
{
myString[anOldLen + aLeftShift + i] = theFiller;
}
}
}
//=================================================================================================
void TCollection_ExtendedString::Capitalize()
{
if (myLength == 0)
{
return;
}
// Convert first character to uppercase (ASCII only)
if (myString[0] >= u'a' && myString[0] <= u'z')
{
myString[0] = static_cast<char16_t>(myString[0] - u'a' + u'A');
}
// Convert remaining characters to lowercase (ASCII only)
for (int i = 1; i < myLength; ++i)
{
if (myString[i] >= u'A' && myString[i] <= u'Z')
{
myString[i] = static_cast<char16_t>(myString[i] - u'A' + u'a');
}
}
}
//=================================================================================================
void TCollection_ExtendedString::Prepend(const char16_t* const theOther, const int theLength)
{
if (theOther == nullptr || theLength <= 0)
{
return;
}
// Check if theOther points into current buffer (aliasing case)
const bool isAliased = (theOther >= myString && theOther < myString + myLength);
if (isAliased)
{
// Save offset before reallocate invalidates the pointer
const std::ptrdiff_t anOffset = theOther - myString;
const int anOldLength = myLength;
reallocate(myLength + theLength);
// Move existing characters to the end first
memmove(myString + theLength, myString, anOldLength * sizeof(char16_t));
// Copy from the shifted position (offset + theLength because content was moved)
memmove(myString, myString + theLength + anOffset, theLength * sizeof(char16_t));
}
else
{
const int anOldLength = myLength;
reallocate(myLength + theLength);
// Move existing characters to the end
memmove(myString + theLength, myString, anOldLength * sizeof(char16_t));
// Copy theOther to the beginning
memcpy(myString, theOther, theLength * sizeof(char16_t));
}
}
//=================================================================================================
int TCollection_ExtendedString::FirstLocationInSet(const TCollection_ExtendedString& theSet,
const int theFromIndex,
const int theToIndex) const
{
if (theFromIndex < 1 || theFromIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::FirstLocationInSet : theFromIndex");
}
if (theToIndex < 1 || theToIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::FirstLocationInSet : theToIndex");
}
if (theSet.myLength == 0)
{
return 0;
}
for (int i = theFromIndex - 1; i < theToIndex; ++i)
{
for (int j = 0; j < theSet.myLength; ++j)
{
if (myString[i] == theSet.myString[j])
{
return i + 1;
}
}
}
return 0;
}
//=================================================================================================
int TCollection_ExtendedString::FirstLocationNotInSet(const TCollection_ExtendedString& theSet,
const int theFromIndex,
const int theToIndex) const
{
if (theFromIndex < 1 || theFromIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::FirstLocationNotInSet : theFromIndex");
}
if (theToIndex < 1 || theToIndex > myLength)
{
throw Standard_OutOfRange("TCollection_ExtendedString::FirstLocationNotInSet : theToIndex");
}
if (theSet.myLength == 0)
{
return (theFromIndex <= theToIndex) ? theFromIndex : 0;
}
for (int i = theFromIndex - 1; i < theToIndex; ++i)
{
bool isFound = false;
for (int j = 0; j < theSet.myLength; ++j)
{
if (myString[i] == theSet.myString[j])
{
isFound = true;
break;
}
}
if (!isFound)
{
return i + 1;
}
}
return 0;
}
//=================================================================================================
int TCollection_ExtendedString::IntegerValue() const
{
if (myLength == 0)
{
return 0;
}
// Convert to ASCII and parse
TCollection_AsciiString anAscii(*this);
return anAscii.IntegerValue();
}
//=================================================================================================
bool TCollection_ExtendedString::IsIntegerValue() const
{
if (myLength == 0)
{
return false;
}
// Convert to ASCII and check
TCollection_AsciiString anAscii(*this);
return anAscii.IsIntegerValue();
}
//=================================================================================================
double TCollection_ExtendedString::RealValue() const
{
if (myLength == 0)
{
return 0.0;
}
// Convert to ASCII and parse
TCollection_AsciiString anAscii(*this);
return anAscii.RealValue();
}
//=================================================================================================
bool TCollection_ExtendedString::IsRealValue(bool theToCheckFull) const
{
if (myLength == 0)
{
return false;
}
// Convert to ASCII and check
TCollection_AsciiString anAscii(*this);
return anAscii.IsRealValue(theToCheckFull);
}
//=================================================================================================
bool TCollection_ExtendedString::IsSameString(const TCollection_ExtendedString& theOther,
const bool theIsCaseSensitive) const
{
if (myLength != theOther.myLength)
{
return false;
}
if (theIsCaseSensitive)
{
return memcmp(myString, theOther.myString, myLength * sizeof(char16_t)) == 0;
}
// Case-insensitive comparison (ASCII only)
for (int i = 0; i < myLength; ++i)
{
char16_t c1 = myString[i];
char16_t c2 = theOther.myString[i];
// Convert to lowercase for comparison
if (c1 >= u'A' && c1 <= u'Z')
{
c1 = static_cast<char16_t>(c1 - u'A' + u'a');
}
if (c2 >= u'A' && c2 <= u'Z')
{
c2 = static_cast<char16_t>(c2 - u'A' + u'a');
}
if (c1 != c2)
{
return false;
}
}
return true;
}