osncore/osncore/src/ustringimpl.cpp
changeset 17 3eca7e70b1b8
parent 3 4526337fb576
equal deleted inserted replaced
3:4526337fb576 17:3eca7e70b1b8
     1 /*
       
     2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  String class implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "ustringimpl.h"
       
    20 
       
    21 #include <gstring.h>
       
    22 #include <stdexcept>
       
    23 #if defined(__GNUC__)
       
    24 #include <string.h>
       
    25 #else
       
    26 #include <string.h>
       
    27 #endif
       
    28 #include <osn/osnnew.h>
       
    29 using namespace std;
       
    30 
       
    31  
       
    32 namespace osncore
       
    33 {
       
    34 
       
    35 const int KMaxUtf8Length = 6;
       
    36 
       
    37 
       
    38 // -------------------------------------------------------------------------
       
    39 // Returns the byte count for aStr with aCharCount length
       
    40 // -------------------------------------------------------------------------
       
    41 //
       
    42 static long bytesFromCharacters(const Utf8* aStr, long aCharCount)
       
    43     {
       
    44     int byteCount = 0;
       
    45     
       
    46     if (aStr)
       
    47         {
       
    48         const char* srcEndOffset = g_utf8_offset_to_pointer(aStr,aCharCount); 
       
    49         byteCount = srcEndOffset - aStr;    
       
    50         }
       
    51     
       
    52     return byteCount;
       
    53     }
       
    54 
       
    55 // -------------------------------------------------------------------------
       
    56 // Initializes the string from stack or heap depending on its length
       
    57 // -------------------------------------------------------------------------
       
    58 //
       
    59 void UStringImpl::initialize(const Utf8* aStr)
       
    60     {
       
    61     if (len < MAX_STR_LEN)
       
    62         {
       
    63         str = internalStr;
       
    64         memcpy(internalStr, aStr, len);
       
    65         }
       
    66     else
       
    67         {
       
    68         str = (gchar*)calloc(len+1, sizeof (gchar));
       
    69     	if(!str)
       
    70     		{
       
    71     		throw bad_alloc();
       
    72     		}
       
    73     	memcpy(str,aStr,len);
       
    74     	isInHeap = true;
       
    75         }
       
    76 	
       
    77 	str[len] = 0;
       
    78 	allocated_len = len+1;    
       
    79     }
       
    80     
       
    81 // -------------------------------------------------------------------------
       
    82 // Allocates memory from heap if needed, throws if allocation fails
       
    83 // -------------------------------------------------------------------------
       
    84 //
       
    85 void UStringImpl::checkBuffer(unsigned int aLength)
       
    86 	{
       
    87 	if (aLength < allocated_len)
       
    88 		{
       
    89 		return;
       
    90 		}
       
    91     if (aLength >= MAX_STR_LEN)
       
    92         {
       
    93         if (!isInHeap) //str is in stack, move it to heap
       
    94             {
       
    95             gchar* temp = (gchar*)calloc(aLength + 1, sizeof(gchar));
       
    96             if (!temp)
       
    97                 {
       
    98         		throw bad_alloc();
       
    99                 }
       
   100             if(str)
       
   101                 {
       
   102                 memcpy(temp, str, len);
       
   103                 }
       
   104             str = temp;
       
   105             isInHeap = true;
       
   106             }
       
   107         else
       
   108             {
       
   109         	gchar* tmp(0);
       
   110         	tmp = (gchar*)realloc(str,aLength+1);
       
   111         	if(!tmp)
       
   112         		{
       
   113         		throw bad_alloc();
       
   114         		}
       
   115         	str = tmp;
       
   116             }
       
   117         }
       
   118     else
       
   119         {
       
   120         // if ustring is constructed with null or "" set internal buffer to
       
   121         // point to str
       
   122         if (!str)
       
   123             str = internalStr;
       
   124         }
       
   125 	allocated_len = aLength+1;
       
   126 
       
   127      
       
   128 	// reset allocated space
       
   129 	memset(str+len, 0, allocated_len-len);
       
   130 	}
       
   131 // -------------------------------------------------------------------------
       
   132 // Implements the actual insertion functionality
       
   133 // -------------------------------------------------------------------------
       
   134 //
       
   135 void UStringImpl::insertImpl(unsigned int aIndex, const char* aInsertChars, unsigned int aInsertLength)
       
   136 	{
       
   137     // Ensure that we have enough space.
       
   138 	checkBuffer(len + aInsertLength); 
       
   139 	// Move tail to make space for inserted characters.
       
   140     memmove(str+aIndex+aInsertLength, str+aIndex, len-aIndex);
       
   141     // Insert characters.
       
   142     memcpy(str+aIndex, aInsertChars, aInsertLength);
       
   143     // Update len
       
   144     len += aInsertLength;
       
   145 	}  
       
   146 // -------------------------------------------------------------------------
       
   147 // Implements the actual append functionality
       
   148 // -------------------------------------------------------------------------
       
   149 //
       
   150 void UStringImpl::appendImpl(const char* aStr, unsigned int aLength)
       
   151 	{
       
   152 	insertImpl(len, aStr, aLength);
       
   153 	}
       
   154 // -------------------------------------------------------------------------
       
   155 // Implements the actual erase functionality
       
   156 // -------------------------------------------------------------------------
       
   157 //
       
   158 void UStringImpl::eraseImpl(unsigned int aIndex, unsigned int aLength)
       
   159 	{
       
   160 	if(aIndex > len)
       
   161 		{
       
   162 		throw out_of_range("out_of_range");
       
   163 		}
       
   164 	
       
   165 	if(aIndex+aLength >= len)
       
   166 		{
       
   167 		// erase from given index to end of the string
       
   168 		if(aIndex<len)
       
   169 			{
       
   170 			len = aIndex;
       
   171 			}
       
   172 		memset(str+aIndex,0,len-aIndex);
       
   173 		}
       
   174 	else
       
   175 		{
       
   176 		// Move tail (remove begin or between) to given index.
       
   177 	    memmove(str+aIndex, str+aIndex+aLength, len-(aIndex+aLength));
       
   178 		len -=  aLength;
       
   179 		memset(str+len,0,allocated_len-len);
       
   180 		}
       
   181 	}
       
   182     
       
   183 // -------------------------------------------------------------------------
       
   184 // Constructor
       
   185 // -------------------------------------------------------------------------
       
   186 //
       
   187 UStringImpl::UStringImpl():str(0),len(0),allocated_len(0), isInHeap(0)
       
   188 	{
       
   189 #ifdef _DEBUG
       
   190 	g_setenv("G_SLICE","always-malloc",1);
       
   191 #endif
       
   192 	}
       
   193 // -------------------------------------------------------------------------
       
   194 // Constructs the string from aStr
       
   195 // -------------------------------------------------------------------------
       
   196 //
       
   197 UStringImpl::UStringImpl(const Utf8* aStr)
       
   198     :str(0),len(0),allocated_len(0), isInHeap(0)
       
   199     {
       
   200 #ifdef _DEBUG    
       
   201     g_setenv("G_SLICE","always-malloc",1);
       
   202 #endif    
       
   203     //NULL byte not accepted
       
   204     if (aStr)
       
   205         {
       
   206         len = strlen(aStr); 
       
   207         initialize(aStr);
       
   208         }   
       
   209     }
       
   210 
       
   211 // -------------------------------------------------------------------------
       
   212 // Constructs the string from aStr with aByteCount length
       
   213 // -------------------------------------------------------------------------
       
   214 //
       
   215 UStringImpl::UStringImpl(const Utf8* aStr, int aByteCount)
       
   216     :str(0),len(0),allocated_len(0), isInHeap(0)
       
   217     {
       
   218 #ifdef _DEBUG    
       
   219     g_setenv("G_SLICE","always-malloc",1);
       
   220 #endif    
       
   221     //NULL byte not accepted
       
   222     if (aStr)
       
   223         {
       
   224         len = aByteCount;
       
   225         initialize(aStr);
       
   226         }    
       
   227     }
       
   228 
       
   229 // -------------------------------------------------------------------------
       
   230 // Constructs the string from aCodePoint
       
   231 // -------------------------------------------------------------------------
       
   232 //
       
   233 UStringImpl::UStringImpl(Unicode aCodePoint)
       
   234     :str(0),len(0),allocated_len(0), isInHeap(0)
       
   235     {
       
   236 #ifdef _DEBUG    
       
   237     g_setenv("G_SLICE","always-malloc",1);
       
   238 #endif    
       
   239         
       
   240     char string[KMaxUtf8Length]; 
       
   241     long usedBytes = g_unichar_to_utf8((unsigned int)aCodePoint,&string[0]);
       
   242     if(usedBytes > 0)
       
   243         {
       
   244         len = usedBytes;
       
   245         initialize(&string[0]);
       
   246         }
       
   247     }
       
   248 
       
   249 // -------------------------------------------------------------------------
       
   250 // Copy constructor
       
   251 // -------------------------------------------------------------------------
       
   252 //
       
   253 UStringImpl::UStringImpl(const UStringImpl& aUStringImpl)
       
   254     :str(0),len(aUStringImpl.len),allocated_len(0), isInHeap(0)
       
   255     {
       
   256 #ifdef _DEBUG    
       
   257     g_setenv("G_SLICE","always-malloc",1);
       
   258 #endif    
       
   259     if(aUStringImpl.str)
       
   260         {
       
   261         initialize(aUStringImpl.str);
       
   262         }
       
   263     }
       
   264 
       
   265 
       
   266 // -------------------------------------------------------------------------
       
   267 // Destructor
       
   268 // -------------------------------------------------------------------------
       
   269 //
       
   270 UStringImpl::~UStringImpl()
       
   271 	{
       
   272 	if (str && isInHeap)
       
   273 	    {
       
   274 	    delete str;
       
   275 	    }
       
   276 	}	
       
   277 // -------------------------------------------------------------------------
       
   278 // Returns true if the string is empty
       
   279 // -------------------------------------------------------------------------
       
   280 //
       
   281 bool UStringImpl::empty()const
       
   282 	{
       
   283 	return (len > 0) ? false : true;
       
   284 	}
       
   285 
       
   286 // -------------------------------------------------------------------------
       
   287 // Returns true if the string is a null string
       
   288 // -------------------------------------------------------------------------
       
   289 //
       
   290 bool UStringImpl::null()const
       
   291 	{
       
   292 	return (str) ? false : true;
       
   293 	}
       
   294 	
       
   295 // -------------------------------------------------------------------------
       
   296 // Returns the length of the string in characters 
       
   297 // -------------------------------------------------------------------------
       
   298 //
       
   299 long UStringImpl::length()const
       
   300     {
       
   301     long ret(0);
       
   302     if(str && (len > 0))
       
   303         {
       
   304         ret = g_utf8_strlen(str, len);
       
   305         }
       
   306     return ret;    
       
   307     }        
       
   308 
       
   309 // -------------------------------------------------------------------------
       
   310 // Returns the length of the string in bytes
       
   311 // -------------------------------------------------------------------------
       
   312 //
       
   313 long UStringImpl::bytes()const
       
   314     {
       
   315     return (long)len;    
       
   316     }        
       
   317 
       
   318 	
       
   319 // -------------------------------------------------------------------------
       
   320 // Returns the utf8 type string
       
   321 // -------------------------------------------------------------------------
       
   322 //
       
   323 const Utf8* UStringImpl::utf8()const
       
   324     {
       
   325     return str;
       
   326     }
       
   327     
       
   328 // -------------------------------------------------------------------------
       
   329 // Compares the string to another UString with strcmp
       
   330 // -------------------------------------------------------------------------
       
   331 //
       
   332 int UStringImpl::compare(const UStringImpl& aUStringImpl)const
       
   333     {
       
   334     int ret(1);
       
   335     if(!str && !aUStringImpl.str)
       
   336         {
       
   337         ret = 0;    
       
   338         }
       
   339     else if(str && aUStringImpl.str)
       
   340         {
       
   341         ret = strcmp(str, aUStringImpl.str);
       
   342         }
       
   343     else if(!str)
       
   344         {
       
   345         ret = -1;
       
   346         }
       
   347   
       
   348     return ret;
       
   349     }	 	
       
   350 // -------------------------------------------------------------------------
       
   351 // Compares the string to Utf8 string with strcmp
       
   352 // -------------------------------------------------------------------------
       
   353 //
       
   354 int UStringImpl::compare(const Utf8* aStr)const
       
   355     {    
       
   356     int ret(1);
       
   357     if(str && aStr)
       
   358         {
       
   359         ret = strcmp(str, aStr);
       
   360         }
       
   361     else if(!str && !strlen(aStr))
       
   362         {
       
   363         ret = 0;    
       
   364         }
       
   365     else if(!str)
       
   366         {
       
   367         ret = -1;
       
   368         }
       
   369    
       
   370     return ret;
       
   371     }	 
       
   372 
       
   373 // -------------------------------------------------------------------------
       
   374 // Compares the string to another UString using the linguistically
       
   375 // correct rules for the current locale
       
   376 // -------------------------------------------------------------------------
       
   377 //
       
   378 int UStringImpl::compareC(const UStringImpl& aUStringImpl)const
       
   379     {
       
   380     int ret(1);
       
   381     if(!str && !aUStringImpl.str)
       
   382         {
       
   383         ret = 0;    
       
   384         }
       
   385     else if(str && aUStringImpl.str)
       
   386         {
       
   387         ret = g_utf8_collate(str, aUStringImpl.str);
       
   388         }
       
   389     else if(!str)
       
   390         {
       
   391         ret = -1;
       
   392         }
       
   393   
       
   394     return ret;
       
   395     }	 	
       
   396 // -------------------------------------------------------------------------
       
   397 // Compares the string to Utf8 string using the linguistically
       
   398 // correct rules for the current locale
       
   399 // -------------------------------------------------------------------------
       
   400 //
       
   401 int UStringImpl::compareC(const Utf8* aStr)const
       
   402     {    
       
   403     int ret(1);
       
   404     if(str && aStr)
       
   405         {
       
   406         ret = g_utf8_collate(str, aStr);
       
   407         }
       
   408     else if(!str && !strlen(aStr))
       
   409         {
       
   410         ret = 0;    
       
   411         }
       
   412     else if(!str)
       
   413         {
       
   414         ret = -1;
       
   415         }
       
   416    
       
   417     return ret;
       
   418     } 
       
   419 
       
   420 // -------------------------------------------------------------------------
       
   421 // Appends another UString to this string 
       
   422 // -------------------------------------------------------------------------
       
   423 //
       
   424 void UStringImpl::append(const UStringImpl& aUStringImpl)
       
   425     {
       
   426     if(str && aUStringImpl.str)
       
   427         {
       
   428         appendImpl(aUStringImpl.str, aUStringImpl.len);
       
   429         }
       
   430     }	 
       
   431 // -------------------------------------------------------------------------
       
   432 // Appends a Utf8 string to this string
       
   433 // -------------------------------------------------------------------------
       
   434 //
       
   435 void UStringImpl::append(const Utf8* aStr)
       
   436     {
       
   437     if(aStr && (strlen(aStr) !=0))
       
   438         {
       
   439         appendImpl(aStr, strlen(aStr));
       
   440         }
       
   441     }
       
   442 
       
   443 // -------------------------------------------------------------------------
       
   444 // Inserts Utf8 string to this string 
       
   445 // -------------------------------------------------------------------------
       
   446 //
       
   447 void UStringImpl::insert( 
       
   448     long aPos, 
       
   449     const Utf8* aStr)
       
   450     {
       
   451    
       
   452     if(aStr)
       
   453        {
       
   454        if (!str)
       
   455            checkBuffer(0);
       
   456        long dstCharCount = g_utf8_strlen(str, -1);
       
   457        if(aPos < -1 || aPos > dstCharCount)
       
   458            {
       
   459            throw out_of_range("out_of_range");  
       
   460            }
       
   461         // find out byte position for given character position
       
   462        long startBytePos(-1);
       
   463        if(aPos >= 0)
       
   464            {
       
   465            if(str)
       
   466                {
       
   467                const char* startOffset = g_utf8_offset_to_pointer(str, aPos);
       
   468                startBytePos = startOffset - str;
       
   469                }
       
   470            }
       
   471        if(aPos == -1)
       
   472     	   {
       
   473     	   appendImpl(aStr, strlen(aStr));
       
   474     	   }
       
   475        else
       
   476     	   {
       
   477     	   insertImpl(startBytePos, aStr, strlen(aStr));
       
   478     	   }
       
   479        }
       
   480     }
       
   481    
       
   482 // -------------------------------------------------------------------------
       
   483 // Inserts Utf8 string to this string with length of the Utf8 specified
       
   484 // -------------------------------------------------------------------------
       
   485 //
       
   486 void UStringImpl::insert( 
       
   487     long aPos, 
       
   488     const Utf8* aStr,
       
   489     long aCharCount)
       
   490     {
       
   491     if (aCharCount < 1)
       
   492         {
       
   493         throw out_of_range("out_of_range");    
       
   494         }
       
   495     
       
   496     if (aStr)
       
   497         {
       
   498         long srcByteLen = bytesFromCharacters(aStr, aCharCount);
       
   499         if(!str)
       
   500             checkBuffer(0);
       
   501         
       
   502         // calculate how many bytes are needed for given characters
       
   503         long srcCharCount = g_utf8_strlen(aStr, srcByteLen);
       
   504         long dstCharCount = g_utf8_strlen(str, -1); 
       
   505         long startBytePos(-1); // appends end of the string
       
   506 
       
   507         if(aPos < -1 || aPos > dstCharCount-1 || aCharCount > srcCharCount)
       
   508             {
       
   509             throw out_of_range("out_of_range");  
       
   510             }
       
   511            
       
   512         if(aPos != -1)
       
   513             {
       
   514             const char* startOffset = g_utf8_offset_to_pointer(str, aPos); 
       
   515             startBytePos = startOffset - str; 
       
   516             }
       
   517         const char* endOffset = g_utf8_offset_to_pointer(aStr, aCharCount);
       
   518         long insertByteLength = endOffset - aStr;   
       
   519 
       
   520         if(aPos == -1)
       
   521             {
       
   522             appendImpl(aStr, insertByteLength);
       
   523             }
       
   524         else
       
   525             {
       
   526             insertImpl(startBytePos, aStr, srcByteLen);
       
   527             }
       
   528         }
       
   529     }
       
   530 
       
   531 // -------------------------------------------------------------------------
       
   532 // Replaces Utf8 string to this string 
       
   533 // -------------------------------------------------------------------------
       
   534 //
       
   535 void UStringImpl::replace(
       
   536     long aPos, 
       
   537     const Utf8* aStr)
       
   538     {
       
   539     if (aStr)
       
   540         {
       
   541         if (!str)
       
   542             checkBuffer(0);
       
   543         
       
   544         long srcByteLen = strlen(aStr);
       
   545         long srcCharCount = g_utf8_strlen(aStr,-1); 
       
   546         long dstCharCount = g_utf8_strlen(str, -1);
       
   547         if(aPos > dstCharCount || aPos < 0)
       
   548             {
       
   549             throw out_of_range("out_of_range");    
       
   550             }
       
   551         
       
   552         // calculate start byte position
       
   553         if(str)
       
   554             {
       
   555             const char* startOffset = g_utf8_offset_to_pointer(str, aPos);
       
   556             long startBytePos = startOffset - str; 
       
   557             
       
   558             // calculate erasable character count in bytes
       
   559                 if(startOffset)
       
   560                     {
       
   561 	                const char* endOffset = g_utf8_offset_to_pointer(startOffset, srcCharCount);
       
   562 	                long eraseByteLength = endOffset - startOffset;  
       
   563 	                // erase existing characters
       
   564 	                eraseImpl(startBytePos, eraseByteLength);
       
   565                     }
       
   566             insertImpl(startBytePos, aStr, srcByteLen);
       
   567             }
       
   568         }
       
   569    }  
       
   570       
       
   571    
       
   572 // -------------------------------------------------------------------------
       
   573 // Replaces a Utf8 string to this string with length of the Utf8 specified
       
   574 // -------------------------------------------------------------------------
       
   575 //
       
   576 void UStringImpl::replace(
       
   577     long aPosOffset, 
       
   578     const Utf8* aStr,
       
   579     long aCharCount)
       
   580     {
       
   581     if (aCharCount < 1)
       
   582         {
       
   583         throw out_of_range("out_of_range");    
       
   584         }
       
   585         
       
   586     if (aStr)
       
   587         {
       
   588         long srcByteLen = bytesFromCharacters(aStr, aCharCount);
       
   589         if(!str)
       
   590             checkBuffer(0);
       
   591         
       
   592         long srcCharCount = g_utf8_strlen(aStr, srcByteLen); 
       
   593         long dstCharCount = g_utf8_strlen(str, -1);
       
   594         if(aPosOffset > dstCharCount || aPosOffset < 0 || aCharCount > srcCharCount)
       
   595             {
       
   596             throw out_of_range("out_of_range");    
       
   597             }
       
   598         // calculate start byte position
       
   599         if(str)
       
   600             {
       
   601             const char* startOffset = g_utf8_offset_to_pointer(str, aPosOffset);
       
   602             long startBytePos = startOffset - str; 
       
   603         
       
   604         // calculate erasable character count in bytes
       
   605             if(startOffset)
       
   606                 {
       
   607                 const char* endOffset = g_utf8_offset_to_pointer(startOffset, srcCharCount);
       
   608                 long eraseByteLength = endOffset - startOffset;  
       
   609                 // erase existing characters
       
   610                 eraseImpl(startBytePos, eraseByteLength);
       
   611                 }
       
   612             insertImpl(startBytePos, aStr, srcByteLen);
       
   613             }
       
   614         }
       
   615    }  
       
   616  
       
   617 // -------------------------------------------------------------------------
       
   618 // Erases aCharCount characters from the string at position specified by 
       
   619 // aPosOffset
       
   620 // -------------------------------------------------------------------------
       
   621 //
       
   622 void UStringImpl::erase(
       
   623     long aPosOffset, 
       
   624     long aCharCount)
       
   625     {
       
   626     
       
   627     if(str)
       
   628         {
       
   629         long srcCharCount = g_utf8_strlen(str, -1); 
       
   630         
       
   631         if (aPosOffset < 0 || aCharCount < 1 || aCharCount > srcCharCount)
       
   632             {
       
   633             throw out_of_range("out_of_range"); 
       
   634             }
       
   635         
       
   636         // calc startpos
       
   637         const char* startOffset = g_utf8_offset_to_pointer(str, aPosOffset); 
       
   638         long startBytePos = startOffset - str; 
       
   639         
       
   640         // calc bytes to erase
       
   641         const char* endOffset = g_utf8_offset_to_pointer(startOffset, aCharCount); 
       
   642         long eraseByteLength = endOffset - startOffset; 
       
   643        
       
   644         eraseImpl(startBytePos, eraseByteLength);
       
   645         }
       
   646    }  
       
   647 
       
   648 // -------------------------------------------------------------------------
       
   649 // Returns unicode at aIndex position in the string
       
   650 // -------------------------------------------------------------------------
       
   651 //
       
   652 Unicode UStringImpl::operator[](long aIndex)
       
   653    {
       
   654    Unicode ret(0xF8FF);
       
   655     
       
   656    if(str)
       
   657        {
       
   658        long charCount = g_utf8_strlen(str, -1);
       
   659        if(aIndex < 0 || aIndex > charCount-1)
       
   660            {
       
   661            throw out_of_range("out_of_range"); 
       
   662            }
       
   663        // calc startpos
       
   664        const char* uniChar = g_utf8_offset_to_pointer(str, aIndex); 
       
   665         
       
   666        ret = g_utf8_get_char(uniChar);        
       
   667        }
       
   668    return ret;     
       
   669    }  
       
   670 
       
   671 }
       
   672     		
       
   673