diff -r 4ea6f81c838a -r 0e9bb658ef58 osncore/osncore/src/ustringimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/osncore/osncore/src/ustringimpl.cpp Wed Sep 01 12:23:18 2010 +0100 @@ -0,0 +1,673 @@ +/* +* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: String class implementation +* +*/ + + +#include "ustringimpl.h" + +#include +#include +#if defined(__GNUC__) +#include +#else +#include +#endif +#include +using namespace std; + + +namespace osncore +{ + +const int KMaxUtf8Length = 6; + + +// ------------------------------------------------------------------------- +// Returns the byte count for aStr with aCharCount length +// ------------------------------------------------------------------------- +// +static long bytesFromCharacters(const Utf8* aStr, long aCharCount) + { + int byteCount = 0; + + if (aStr) + { + const char* srcEndOffset = g_utf8_offset_to_pointer(aStr,aCharCount); + byteCount = srcEndOffset - aStr; + } + + return byteCount; + } + +// ------------------------------------------------------------------------- +// Initializes the string from stack or heap depending on its length +// ------------------------------------------------------------------------- +// +void UStringImpl::initialize(const Utf8* aStr) + { + if (len < MAX_STR_LEN) + { + str = internalStr; + memcpy(internalStr, aStr, len); + } + else + { + str = (gchar*)calloc(len+1, sizeof (gchar)); + if(!str) + { + throw bad_alloc(); + } + memcpy(str,aStr,len); + isInHeap = true; + } + + str[len] = 0; + allocated_len = len+1; + } + +// ------------------------------------------------------------------------- +// Allocates memory from heap if needed, throws if allocation fails +// ------------------------------------------------------------------------- +// +void UStringImpl::checkBuffer(unsigned int aLength) + { + if (aLength < allocated_len) + { + return; + } + if (aLength >= MAX_STR_LEN) + { + if (!isInHeap) //str is in stack, move it to heap + { + gchar* temp = (gchar*)calloc(aLength + 1, sizeof(gchar)); + if (!temp) + { + throw bad_alloc(); + } + if(str) + { + memcpy(temp, str, len); + } + str = temp; + isInHeap = true; + } + else + { + gchar* tmp(0); + tmp = (gchar*)realloc(str,aLength+1); + if(!tmp) + { + throw bad_alloc(); + } + str = tmp; + } + } + else + { + // if ustring is constructed with null or "" set internal buffer to + // point to str + if (!str) + str = internalStr; + } + allocated_len = aLength+1; + + + // reset allocated space + memset(str+len, 0, allocated_len-len); + } +// ------------------------------------------------------------------------- +// Implements the actual insertion functionality +// ------------------------------------------------------------------------- +// +void UStringImpl::insertImpl(unsigned int aIndex, const char* aInsertChars, unsigned int aInsertLength) + { + // Ensure that we have enough space. + checkBuffer(len + aInsertLength); + // Move tail to make space for inserted characters. + memmove(str+aIndex+aInsertLength, str+aIndex, len-aIndex); + // Insert characters. + memcpy(str+aIndex, aInsertChars, aInsertLength); + // Update len + len += aInsertLength; + } +// ------------------------------------------------------------------------- +// Implements the actual append functionality +// ------------------------------------------------------------------------- +// +void UStringImpl::appendImpl(const char* aStr, unsigned int aLength) + { + insertImpl(len, aStr, aLength); + } +// ------------------------------------------------------------------------- +// Implements the actual erase functionality +// ------------------------------------------------------------------------- +// +void UStringImpl::eraseImpl(unsigned int aIndex, unsigned int aLength) + { + if(aIndex > len) + { + throw out_of_range("out_of_range"); + } + + if(aIndex+aLength >= len) + { + // erase from given index to end of the string + if(aIndex 0) + { + len = usedBytes; + initialize(&string[0]); + } + } + +// ------------------------------------------------------------------------- +// Copy constructor +// ------------------------------------------------------------------------- +// +UStringImpl::UStringImpl(const UStringImpl& aUStringImpl) + :str(0),len(aUStringImpl.len),allocated_len(0), isInHeap(0) + { +#ifdef _DEBUG + g_setenv("G_SLICE","always-malloc",1); +#endif + if(aUStringImpl.str) + { + initialize(aUStringImpl.str); + } + } + + +// ------------------------------------------------------------------------- +// Destructor +// ------------------------------------------------------------------------- +// +UStringImpl::~UStringImpl() + { + if (str && isInHeap) + { + delete str; + } + } +// ------------------------------------------------------------------------- +// Returns true if the string is empty +// ------------------------------------------------------------------------- +// +bool UStringImpl::empty()const + { + return (len > 0) ? false : true; + } + +// ------------------------------------------------------------------------- +// Returns true if the string is a null string +// ------------------------------------------------------------------------- +// +bool UStringImpl::null()const + { + return (str) ? false : true; + } + +// ------------------------------------------------------------------------- +// Returns the length of the string in characters +// ------------------------------------------------------------------------- +// +long UStringImpl::length()const + { + long ret(0); + if(str && (len > 0)) + { + ret = g_utf8_strlen(str, len); + } + return ret; + } + +// ------------------------------------------------------------------------- +// Returns the length of the string in bytes +// ------------------------------------------------------------------------- +// +long UStringImpl::bytes()const + { + return (long)len; + } + + +// ------------------------------------------------------------------------- +// Returns the utf8 type string +// ------------------------------------------------------------------------- +// +const Utf8* UStringImpl::utf8()const + { + return str; + } + +// ------------------------------------------------------------------------- +// Compares the string to another UString with strcmp +// ------------------------------------------------------------------------- +// +int UStringImpl::compare(const UStringImpl& aUStringImpl)const + { + int ret(1); + if(!str && !aUStringImpl.str) + { + ret = 0; + } + else if(str && aUStringImpl.str) + { + ret = strcmp(str, aUStringImpl.str); + } + else if(!str) + { + ret = -1; + } + + return ret; + } +// ------------------------------------------------------------------------- +// Compares the string to Utf8 string with strcmp +// ------------------------------------------------------------------------- +// +int UStringImpl::compare(const Utf8* aStr)const + { + int ret(1); + if(str && aStr) + { + ret = strcmp(str, aStr); + } + else if(!str && !strlen(aStr)) + { + ret = 0; + } + else if(!str) + { + ret = -1; + } + + return ret; + } + +// ------------------------------------------------------------------------- +// Compares the string to another UString using the linguistically +// correct rules for the current locale +// ------------------------------------------------------------------------- +// +int UStringImpl::compareC(const UStringImpl& aUStringImpl)const + { + int ret(1); + if(!str && !aUStringImpl.str) + { + ret = 0; + } + else if(str && aUStringImpl.str) + { + ret = g_utf8_collate(str, aUStringImpl.str); + } + else if(!str) + { + ret = -1; + } + + return ret; + } +// ------------------------------------------------------------------------- +// Compares the string to Utf8 string using the linguistically +// correct rules for the current locale +// ------------------------------------------------------------------------- +// +int UStringImpl::compareC(const Utf8* aStr)const + { + int ret(1); + if(str && aStr) + { + ret = g_utf8_collate(str, aStr); + } + else if(!str && !strlen(aStr)) + { + ret = 0; + } + else if(!str) + { + ret = -1; + } + + return ret; + } + +// ------------------------------------------------------------------------- +// Appends another UString to this string +// ------------------------------------------------------------------------- +// +void UStringImpl::append(const UStringImpl& aUStringImpl) + { + if(str && aUStringImpl.str) + { + appendImpl(aUStringImpl.str, aUStringImpl.len); + } + } +// ------------------------------------------------------------------------- +// Appends a Utf8 string to this string +// ------------------------------------------------------------------------- +// +void UStringImpl::append(const Utf8* aStr) + { + if(aStr && (strlen(aStr) !=0)) + { + appendImpl(aStr, strlen(aStr)); + } + } + +// ------------------------------------------------------------------------- +// Inserts Utf8 string to this string +// ------------------------------------------------------------------------- +// +void UStringImpl::insert( + long aPos, + const Utf8* aStr) + { + + if(aStr) + { + if (!str) + checkBuffer(0); + long dstCharCount = g_utf8_strlen(str, -1); + if(aPos < -1 || aPos > dstCharCount) + { + throw out_of_range("out_of_range"); + } + // find out byte position for given character position + long startBytePos(-1); + if(aPos >= 0) + { + if(str) + { + const char* startOffset = g_utf8_offset_to_pointer(str, aPos); + startBytePos = startOffset - str; + } + } + if(aPos == -1) + { + appendImpl(aStr, strlen(aStr)); + } + else + { + insertImpl(startBytePos, aStr, strlen(aStr)); + } + } + } + +// ------------------------------------------------------------------------- +// Inserts Utf8 string to this string with length of the Utf8 specified +// ------------------------------------------------------------------------- +// +void UStringImpl::insert( + long aPos, + const Utf8* aStr, + long aCharCount) + { + if (aCharCount < 1) + { + throw out_of_range("out_of_range"); + } + + if (aStr) + { + long srcByteLen = bytesFromCharacters(aStr, aCharCount); + if(!str) + checkBuffer(0); + + // calculate how many bytes are needed for given characters + long srcCharCount = g_utf8_strlen(aStr, srcByteLen); + long dstCharCount = g_utf8_strlen(str, -1); + long startBytePos(-1); // appends end of the string + + if(aPos < -1 || aPos > dstCharCount-1 || aCharCount > srcCharCount) + { + throw out_of_range("out_of_range"); + } + + if(aPos != -1) + { + const char* startOffset = g_utf8_offset_to_pointer(str, aPos); + startBytePos = startOffset - str; + } + const char* endOffset = g_utf8_offset_to_pointer(aStr, aCharCount); + long insertByteLength = endOffset - aStr; + + if(aPos == -1) + { + appendImpl(aStr, insertByteLength); + } + else + { + insertImpl(startBytePos, aStr, srcByteLen); + } + } + } + +// ------------------------------------------------------------------------- +// Replaces Utf8 string to this string +// ------------------------------------------------------------------------- +// +void UStringImpl::replace( + long aPos, + const Utf8* aStr) + { + if (aStr) + { + if (!str) + checkBuffer(0); + + long srcByteLen = strlen(aStr); + long srcCharCount = g_utf8_strlen(aStr,-1); + long dstCharCount = g_utf8_strlen(str, -1); + if(aPos > dstCharCount || aPos < 0) + { + throw out_of_range("out_of_range"); + } + + // calculate start byte position + if(str) + { + const char* startOffset = g_utf8_offset_to_pointer(str, aPos); + long startBytePos = startOffset - str; + + // calculate erasable character count in bytes + if(startOffset) + { + const char* endOffset = g_utf8_offset_to_pointer(startOffset, srcCharCount); + long eraseByteLength = endOffset - startOffset; + // erase existing characters + eraseImpl(startBytePos, eraseByteLength); + } + insertImpl(startBytePos, aStr, srcByteLen); + } + } + } + + +// ------------------------------------------------------------------------- +// Replaces a Utf8 string to this string with length of the Utf8 specified +// ------------------------------------------------------------------------- +// +void UStringImpl::replace( + long aPosOffset, + const Utf8* aStr, + long aCharCount) + { + if (aCharCount < 1) + { + throw out_of_range("out_of_range"); + } + + if (aStr) + { + long srcByteLen = bytesFromCharacters(aStr, aCharCount); + if(!str) + checkBuffer(0); + + long srcCharCount = g_utf8_strlen(aStr, srcByteLen); + long dstCharCount = g_utf8_strlen(str, -1); + if(aPosOffset > dstCharCount || aPosOffset < 0 || aCharCount > srcCharCount) + { + throw out_of_range("out_of_range"); + } + // calculate start byte position + if(str) + { + const char* startOffset = g_utf8_offset_to_pointer(str, aPosOffset); + long startBytePos = startOffset - str; + + // calculate erasable character count in bytes + if(startOffset) + { + const char* endOffset = g_utf8_offset_to_pointer(startOffset, srcCharCount); + long eraseByteLength = endOffset - startOffset; + // erase existing characters + eraseImpl(startBytePos, eraseByteLength); + } + insertImpl(startBytePos, aStr, srcByteLen); + } + } + } + +// ------------------------------------------------------------------------- +// Erases aCharCount characters from the string at position specified by +// aPosOffset +// ------------------------------------------------------------------------- +// +void UStringImpl::erase( + long aPosOffset, + long aCharCount) + { + + if(str) + { + long srcCharCount = g_utf8_strlen(str, -1); + + if (aPosOffset < 0 || aCharCount < 1 || aCharCount > srcCharCount) + { + throw out_of_range("out_of_range"); + } + + // calc startpos + const char* startOffset = g_utf8_offset_to_pointer(str, aPosOffset); + long startBytePos = startOffset - str; + + // calc bytes to erase + const char* endOffset = g_utf8_offset_to_pointer(startOffset, aCharCount); + long eraseByteLength = endOffset - startOffset; + + eraseImpl(startBytePos, eraseByteLength); + } + } + +// ------------------------------------------------------------------------- +// Returns unicode at aIndex position in the string +// ------------------------------------------------------------------------- +// +Unicode UStringImpl::operator[](long aIndex) + { + Unicode ret(0xF8FF); + + if(str) + { + long charCount = g_utf8_strlen(str, -1); + if(aIndex < 0 || aIndex > charCount-1) + { + throw out_of_range("out_of_range"); + } + // calc startpos + const char* uniChar = g_utf8_offset_to_pointer(str, aIndex); + + ret = g_utf8_get_char(uniChar); + } + return ret; + } + +} + +