794 lines
14 KiB
C++
794 lines
14 KiB
C++
/**
|
|
*******************************************************************************
|
|
* @file etk/UString.cpp
|
|
* @brief Ewol Tool Kit : normal Unicode string management... (sources)
|
|
* @author Edouard DUPIN
|
|
* @date 14/02/2012
|
|
* @par Project
|
|
* Ewol TK
|
|
*
|
|
* @par Copyright
|
|
* Copyright 2011 Edouard DUPIN, all right reserved
|
|
*
|
|
* This software is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY.
|
|
*
|
|
* Licence summary :
|
|
* You can modify and redistribute the sources code and binaries.
|
|
* You can send me the bug-fix
|
|
*
|
|
* Term of the licence in in the file licence.txt.
|
|
*
|
|
*******************************************************************************
|
|
*/
|
|
|
|
#include <etk/UString.h>
|
|
#include <etk/Memory.h>
|
|
#include <etk/unicode.h>
|
|
|
|
int32_t strlen(const uniChar_t * data)
|
|
{
|
|
if (NULL == data) {
|
|
return 0;
|
|
}
|
|
int32_t iii=0;
|
|
while (*data != 0) {
|
|
data++;
|
|
iii++;
|
|
if (iii > 0x7FFFFFF0) {
|
|
return iii;
|
|
}
|
|
}
|
|
return iii;
|
|
}
|
|
|
|
#undef __class__
|
|
#define __class__ "etk::UString"
|
|
|
|
etk::CCout& etk::operator <<(etk::CCout &os, const etk::UString &obj)
|
|
{
|
|
etk::VectorType<char> output_UTF8;
|
|
unicode::convertUnicodeToUtf8(obj.m_data, output_UTF8);
|
|
output_UTF8.PushBack('\0');
|
|
os << &output_UTF8[0];
|
|
return os;
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::~UString(void)
|
|
{
|
|
m_data.Clear();
|
|
m_dataUtf8.Clear();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::UString(void)
|
|
{
|
|
//TK_INFO("new etk::UString()");
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::UString(const char* inputData, int32_t len)
|
|
{
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(inputData, len);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::UString(const uniChar_t* inputData, int32_t len)
|
|
{
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(inputData, len);
|
|
}
|
|
/*
|
|
etk::UString::UString(const uniChar_t inputData)
|
|
{
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(&inputData, 1);
|
|
}
|
|
*/
|
|
|
|
void etk::UString::Set(const char * inputData, int32_t len)
|
|
{
|
|
if (NULL == inputData) {
|
|
// nothing to add ...
|
|
return;
|
|
}
|
|
// overwrite the len if needed :
|
|
if ((-1) == len) {
|
|
len = strlen(inputData);
|
|
}
|
|
// convert the string
|
|
etk::VectorType<char> tmpChar;
|
|
for (int32_t iii=0; iii<len; iii++) {
|
|
tmpChar.PushBack(inputData[iii]);
|
|
}
|
|
// add it ...
|
|
if (len != 0) {
|
|
// remove the last '\0'
|
|
m_data.PopBack();
|
|
// copy the data ...
|
|
unicode::convertUtf8ToUnicode(tmpChar, m_data);
|
|
// add the last '\0'
|
|
m_data.PushBack('\0');
|
|
}
|
|
}
|
|
|
|
void etk::UString::Set(const uniChar_t * inputData, int32_t len)
|
|
{
|
|
if (NULL == inputData) {
|
|
// nothing to add ...
|
|
return;
|
|
}
|
|
// overwrite the len if needed :
|
|
if ((-1) == len) {
|
|
len = strlen(inputData);
|
|
}
|
|
|
|
if (len != 0) {
|
|
// remove the last '\0'
|
|
m_data.PopBack();
|
|
// copy the data ...
|
|
m_data.PushBack(inputData, len);
|
|
// add the last '\0'
|
|
m_data.PushBack('\0');
|
|
}
|
|
}
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::UString(char inputData)
|
|
{
|
|
char tmpVal[2];
|
|
// generate the UString :
|
|
sprintf(tmpVal, "%c", inputData);
|
|
// set the internal data :
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(tmpVal);
|
|
}
|
|
|
|
|
|
etk::UString::UString(int inputData)
|
|
{
|
|
char tmpVal[256];
|
|
// generate the UString :
|
|
sprintf(tmpVal, "%d", inputData);
|
|
// set the internal data :
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(tmpVal);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString::UString(unsigned int inputData)
|
|
{
|
|
char tmpVal[256];
|
|
// generate the UString :
|
|
sprintf(tmpVal, "%d", inputData);
|
|
// set the internal data :
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(tmpVal);
|
|
}
|
|
|
|
etk::UString::UString(float inputData)
|
|
{
|
|
char tmpVal[256];
|
|
// generate the UString :
|
|
sprintf(tmpVal, "%f", inputData);
|
|
// set the internal data :
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(tmpVal);
|
|
}
|
|
|
|
etk::UString::UString(double inputData)
|
|
{
|
|
char tmpVal[256];
|
|
// generate the UString :
|
|
sprintf(tmpVal, "%lf", inputData);
|
|
// set the internal data :
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
Set(tmpVal);
|
|
}
|
|
|
|
etk::UString::UString(const etk::UString &etkS)
|
|
{
|
|
//etk_INFO("Constructeur de recopie");
|
|
m_data = etkS.m_data;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
const etk::UString& etk::UString::operator= (const etk::UString &etkS )
|
|
{
|
|
//TK_INFO("OPERATOR de recopie");
|
|
if( this != &etkS ) {
|
|
m_data = etkS.m_data;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
const etk::UString& etk::UString::operator= (etk::VectorType<char> inputData)
|
|
{
|
|
etk::VectorType<uniChar_t> output_Unicode;
|
|
unicode::convertUtf8ToUnicode(inputData, output_Unicode);
|
|
*this = output_Unicode;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
const etk::UString& etk::UString::operator= (etk::VectorType<int8_t> inputData)
|
|
{
|
|
etk::VectorType<uniChar_t> output_Unicode;
|
|
unicode::convertUtf8ToUnicode(inputData, output_Unicode);
|
|
*this = output_Unicode;
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
const etk::UString& etk::UString::operator= (etk::VectorType<uniChar_t> inputData)
|
|
{
|
|
m_data = inputData;
|
|
if (m_data.Size()>0) {
|
|
if (m_data[m_data.Size()-1] != '\0') {
|
|
m_data.PushBack('\0');
|
|
}
|
|
}
|
|
//TK_DEBUG("m_dataLen="<<m_dataLen << " m_dataLenUTF8="<<m_dataLenUTF8 << " description=" << m_data);
|
|
return *this;
|
|
}
|
|
|
|
|
|
uniChar_t changeOrder(uniChar_t elemA)
|
|
{
|
|
if (elemA >= 'A' && elemA <= 'Z') {
|
|
return (elemA - (uniChar_t)'A')*2 + 'A';
|
|
}
|
|
if (elemA >= 'a' && elemA <= 'z') {
|
|
return (elemA - (uniChar_t)'a')*2 + 'A' + 1;
|
|
}
|
|
if (elemA >= ':' && elemA <= '@') {
|
|
return elemA + 52;
|
|
}
|
|
if (elemA >= '[' && elemA <= '`') {
|
|
return elemA +26;
|
|
}
|
|
return elemA;
|
|
}
|
|
|
|
|
|
bool etk::UString::operator> (const etk::UString& etkS) const
|
|
{
|
|
if( this != &etkS ) {
|
|
for (int32_t iii=0; iii < m_data.Size() && iii < etkS.m_data.Size(); iii++) {
|
|
//TK_DEBUG(" compare : '" << (char)m_data[iii] << "'>'" << (char)etkS.m_data[iii] << "' ==> " << changeOrder(m_data[iii]) << ">" << changeOrder(etkS.m_data[iii]) << "");
|
|
uniChar_t elemA = changeOrder(m_data[iii]);
|
|
uniChar_t elemB = changeOrder(etkS.m_data[iii]);
|
|
if (elemA != elemB) {
|
|
if (elemA > elemB) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
if (m_data.Size() > etkS.m_data.Size()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool etk::UString::operator>= (const etk::UString& etkS) const
|
|
{
|
|
if( this != &etkS ) {
|
|
for (int32_t iii=0; iii < m_data.Size() && iii < etkS.m_data.Size(); iii++) {
|
|
uniChar_t elemA = changeOrder(m_data[iii]);
|
|
uniChar_t elemB = changeOrder(etkS.m_data[iii]);
|
|
if (elemA != elemB) {
|
|
if (elemA > elemB) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
if (m_data.Size() >= etkS.m_data.Size()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool etk::UString::operator< (const etk::UString& etkS) const
|
|
{
|
|
if( this != &etkS ) {
|
|
for (int32_t iii=0; iii < m_data.Size() && iii < etkS.m_data.Size(); iii++) {
|
|
uniChar_t elemA = changeOrder(m_data[iii]);
|
|
uniChar_t elemB = changeOrder(etkS.m_data[iii]);
|
|
if (elemA != elemB) {
|
|
if (elemA < elemB) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
if (m_data.Size() < etkS.m_data.Size()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool etk::UString::operator<= (const etk::UString& etkS) const
|
|
{
|
|
if( this != &etkS ) {
|
|
for (int32_t iii=0; iii < m_data.Size() && iii < etkS.m_data.Size(); iii++) {
|
|
uniChar_t elemA = changeOrder(m_data[iii]);
|
|
uniChar_t elemB = changeOrder(etkS.m_data[iii]);
|
|
if (elemA != elemB) {
|
|
if (elemA < elemB) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
if (m_data.Size() <= etkS.m_data.Size()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
bool etk::UString::operator== (const etk::UString& etkS) const
|
|
{
|
|
if( this != &etkS ) {
|
|
if (etkS.m_data.Size() != m_data.Size()) {
|
|
//TK_DEBUG(" not the same size : " << etkS.m_data.Size() << "!=" << m_data.Size());
|
|
return false;
|
|
}
|
|
for (int32_t iii= 0; iii<m_data.Size(); iii++) {
|
|
//TK_DEBUG(" check : " << etkS.m_data[iii] << "!=" << m_data[iii]);
|
|
if (etkS.m_data[iii]!= m_data[iii]){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
bool etk::UString::operator!= (const etk::UString& etkS) const
|
|
{
|
|
return !(*this == etkS);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
const etk::UString& etk::UString::operator+= (const etk::UString &etkS)
|
|
{
|
|
if (0 < etkS.Size()) {
|
|
// remove the last '\0'
|
|
m_data.PopBack();
|
|
// copy the data ...
|
|
m_data += etkS.m_data;
|
|
// This previous include the \0 in case of the 2 UString are different...
|
|
if( this == &etkS ) {
|
|
// add the removed end UString
|
|
m_data.PushBack('\0');
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
etk::UString etk::UString::operator+ (const etk::UString &etkS)
|
|
{
|
|
etk::UString temp;
|
|
//TK_INFO(" UString(arg) : \"" << etkS.m_data << "\"");
|
|
//TK_INFO(" UString(direct) : \"" << m_data << "\"");
|
|
temp += *this;
|
|
temp += etkS;
|
|
return temp;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
bool etk::UString::IsEmpty(void) const
|
|
{
|
|
if(1 >= m_data.Size() ) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
int32_t etk::UString::Size(void) const
|
|
{
|
|
if (m_data.Size() == 0) {
|
|
return 0;
|
|
} else {
|
|
return m_data.Size() - 1;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
void etk::UString::Add(int32_t currentID, const char* inputData)
|
|
{
|
|
etk::UString tmpString(inputData);
|
|
Add(currentID, tmpString.pointer() );
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
void etk::UString::Add(int32_t currentID, const uniChar_t* inputData)
|
|
{
|
|
// get the input lenght
|
|
int32_t len = strlen(inputData);
|
|
if (0 == len) {
|
|
TK_WARNING("no data to add on the current UString");
|
|
return;
|
|
} else if (currentID < 0) {
|
|
TK_WARNING("Curent ID(" << currentID << ") < 0 ==> Add at the start");
|
|
currentID = 0;
|
|
} else if (currentID > Size() ) {
|
|
TK_ERROR("Curent ID(" << currentID << ") > maxSize ... (" << Size() << ") ==> add at the end ...");
|
|
m_data.PushBack(inputData, len);
|
|
return;
|
|
}
|
|
m_data.Insert(currentID, inputData, len);
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
void etk::UString::Add(int32_t currentID, const uniChar_t inputData)
|
|
{
|
|
uniChar_t data[2];
|
|
data[0] = inputData;
|
|
data[1] = 0;
|
|
Add(currentID, data);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* @param[in,out]
|
|
*
|
|
* @return
|
|
*
|
|
*/
|
|
void etk::UString::Remove(int32_t currentID, int32_t len)
|
|
{
|
|
if (0 >= len) {
|
|
TK_ERROR("no data to remove on the current UString");
|
|
return;
|
|
}
|
|
// TODO : check the size of the data
|
|
m_data.EraseLen(currentID, len);
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Remove all element in the UString
|
|
*
|
|
* @param ---
|
|
*
|
|
* @return ---
|
|
*
|
|
*/
|
|
void etk::UString::Clear(void)
|
|
{
|
|
m_data.Clear();
|
|
m_data.PushBack('\0');
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief find the first accurence after the position indicated
|
|
*
|
|
* @param[in] element Element that might be find in the UString
|
|
* @param[in] startPos Stert position to begin the search
|
|
*
|
|
* @return the position of the first occurence or -1 if not find...
|
|
*
|
|
*/
|
|
int32_t etk::UString::FindForward(const char element, int32_t startPos)
|
|
{
|
|
return FindForward((uniChar_t)element, startPos);
|
|
}
|
|
int32_t etk::UString::FindForward(const uniChar_t element, int32_t startPos)
|
|
{
|
|
if (startPos < 0) {
|
|
startPos = 0;
|
|
} else if (startPos >= Size() ) {
|
|
return -1;
|
|
}
|
|
for (int32_t iii=startPos; iii< Size(); iii++) {
|
|
if (m_data[iii] == element) {
|
|
return iii;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief find the first accurence before the position indicated.
|
|
*
|
|
* @param[in] element Element that might be find in the UString
|
|
* @param[in] startPos Stert position to begin the search
|
|
*
|
|
* @return the position of the first occurence begining by the end or -1 if not find...
|
|
*
|
|
*/
|
|
int32_t etk::UString::FindBack(const char element, int32_t startPos)
|
|
{
|
|
return FindBack((uniChar_t)element, startPos);
|
|
}
|
|
int32_t etk::UString::FindBack(const uniChar_t element, int32_t startPos)
|
|
{
|
|
if (startPos < 0) {
|
|
return -1;
|
|
} else if (startPos >= Size() ) {
|
|
startPos = Size();
|
|
}
|
|
for (int32_t iii=startPos; iii>=0; iii--) {
|
|
if (m_data[iii] == element) {
|
|
return iii;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Extract data from the data between two position
|
|
*
|
|
* @param[in] posStart Start position where to extract data
|
|
* @param[in] posEnd End position where to extract data
|
|
*
|
|
* @return the extracted UString
|
|
*
|
|
*/
|
|
etk::UString etk::UString::Extract(int32_t posStart, int32_t posEnd)
|
|
{
|
|
etk::UString out;
|
|
if (posStart < 0) {
|
|
posStart = 0;
|
|
} else if (posStart >= Size() ) {
|
|
return out;
|
|
}
|
|
if (posEnd < 0) {
|
|
return out;
|
|
} else if (posEnd >= Size() ) {
|
|
posEnd = Size();
|
|
}
|
|
out.m_data = m_data.Extract(posStart, posEnd);
|
|
out.m_data.PushBack('\0');
|
|
return out;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Get a basic vector in int8 data with no \0 at the end of the UString
|
|
*
|
|
* @param ---
|
|
*
|
|
* @return The desired vector with data
|
|
*
|
|
*/
|
|
etk::VectorType<uniChar_t> etk::UString::GetVector(void)
|
|
{
|
|
etk::VectorType<uniChar_t> out = m_data;
|
|
out.PopBack();
|
|
return out;
|
|
}
|
|
|
|
|
|
// Start With ...
|
|
|
|
bool etk::UString::StartWith(const etk::UString& data)
|
|
{
|
|
if (data.Size() == 0) {
|
|
return false;
|
|
}
|
|
if (data.Size() > Size()) {
|
|
return false;
|
|
}
|
|
for (int32_t iii=0; iii<data.Size(); iii++) {
|
|
if (data[iii] != m_data[iii]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool etk::UString::EndWith(const etk::UString& data)
|
|
{
|
|
if (data.Size() == 0) {
|
|
return false;
|
|
}
|
|
if (data.Size() > Size()) {
|
|
return false;
|
|
}
|
|
for( int32_t iii=Size()-1, jjj=data.Size()-1;
|
|
iii>=0 && jjj>=0;
|
|
iii--, jjj--) {
|
|
if (data[jjj] != m_data[iii]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
char * etk::UString::Utf8Data(void)
|
|
{
|
|
// UTF8 generation :
|
|
m_dataUtf8.Clear();
|
|
unicode::convertUnicodeToUtf8(m_data, m_dataUtf8);
|
|
m_dataUtf8.PushBack('\0');
|
|
|
|
return &m_dataUtf8[0];
|
|
}
|
|
|
|
|