12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601 |
- #define EWCharString_CPP
- //===========================================================================//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- //***************************************************************
- /* just for this file, we want UNICODE and K_UNICODE defined and MBCS undefined */
- #ifdef UNICODE
- #define _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #else
- #define UNICODE
- #endif /* def UNICODE */
- #ifdef K_UNICODE
- #define _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #else
- #define K_UNICODE
- #endif /* def K_UNICODE */
- #ifdef MBCS
- #define _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #define _PREVIOUS_MBCS___EWCharString_CPP MBCS
- #undef MBCS
- #endif /* def MBCS */
- //***************************************************************
- #include <windows.h>
- #include <stdio.h>
- #include "EWCharString.h"
- #include <gameos.hpp>
- #ifdef UNICODE
- #include <malloc.h>
- #include <tchar.h>
- #endif
- #pragma warning( disable:4505 )
- #pragma warning( push )
- #pragma warning( disable:4100 )
- #define INT_SIZE_LENGTH 20
- extern int __ismbcodepage;
- #define _ISNOTMBCP (__ismbcodepage == 0)
- static wchar_t * __cdecl wideRev (
- wchar_t * string
- )
- {
- wchar_t *start = string;
- wchar_t *left = string;
- wchar_t ch;
- while (*string++) /* find end of string */
- ;
- string -= 2;
- while (left < string)
- {
- ch = *left;
- *left++ = *string;
- *string-- = ch;
- }
- return(start);
- }
- static wchar_t * __cdecl wideStrStr (
- const wchar_t * wcs1,
- const wchar_t * wcs2
- )
- {
- wchar_t *cp = (wchar_t *) wcs1;
- wchar_t *s1, *s2;
- while (*cp)
- {
- s1 = cp;
- s2 = (wchar_t *) wcs2;
- while ( *s1 && *s2 && !(*s1-*s2) )
- s1++, s2++;
- if (!*s2)
- return(cp);
- cp++;
- }
- return(NULL);
- }
- static int __cdecl wideToInt(
- const wchar_t *nptr
- )
- {
- char astring[20];
- WideCharToMultiByte (CP_ACP, 0, nptr, -1,
- astring, INT_SIZE_LENGTH, NULL, NULL);
- return ((int)atol(astring));
- }
- static long __cdecl atolong(
- const char *nptr
- )
- {
- int c; /* current char */
- long total; /* current total */
- int sign; /* if '-', then negative, otherwise positive */
- /* skip whitespace */
- while ( isspace((int)(unsigned char)*nptr) )
- ++nptr;
- c = (int)(unsigned char)*nptr++;
- sign = c; /* save sign indication */
- if (c == '-' || c == '+')
- c = (int)(unsigned char)*nptr++; /* skip sign */
- total = 0;
- while (isdigit(c)) {
- total = 10 * total + (c - '0'); /* accumulate digit */
- c = (int)(unsigned char)*nptr++; /* get next char */
- }
- if (sign == '-')
- return -total;
- else
- return total; /* return result, negated if necessary */
- }
- static char * __cdecl StrStr (
- const char * str1,
- const char * str2
- )
- {
- char *cp = (char *) str1;
- char *s1, *s2;
- if ( !*str2 )
- return((char *)str1);
- while (*cp)
- {
- s1 = cp;
- s2 = (char *) str2;
- while ( *s1 && *s2 && !(*s1-*s2) )
- s1++, s2++;
- if (!*s2)
- return(cp);
- cp++;
- }
- return(NULL);
- }
- static char * __cdecl StrRev (
- char * string
- )
- {
- char *start = string;
- char *left = string;
- char ch;
- while (*string++) /* find end of string */
- ;
- string -= 2;
- while (left < string)
- {
- ch = *left;
- *left++ = *string;
- *string-- = ch;
- }
- return(start);
- }
- //***************************************************************
- #ifdef UNICODE
- #define KToUpper CharUpper
- #define KToLower CharLower
- #define KReverse wideRev
- #define KStrCmp lstrcmpi
- #define klstrlen lstrlen
- #define KStrStr wideStrStr
- inline const EWCSChar* KSInc(const EWCSChar* p) { return p+1; }
- inline size_t EWCSCharLen( const EWCSChar* p ) {return 2;}
- #define KToI wideToInt
- #else
- #define KToI atolong
- #define KStrCmp lstrcmpi
- #define klstrlen lstrlen
- #define KToUpper CharUpper
- #define KToLower CharLower
- #ifdef MBCS
- #define KReverse mbrev
- #define KStrStr _mbsstr
- #define KSInc _mbsinc
- #define EWCSCharLen _mbclen
- #else // single byte
- #define KReverse StrRev
- #define KStrStr StrStr
- __inline char * __cdecl KSInc(const char * _pc) { return (char *)(_pc+1); }
- inline int EWCSCharLen(const char* x){ return 1; }
- #endif
- #endif
- const int EWCharString::INVALID_INDEX = -1;
- const int EWCharString::s_Alloc_Allign = 4;
- const int EWCharString::s_Force_Ansi = 0x10000;
- const int EWCharString::s_Force_Unicode = 0x20000;
- // keep around an empty buffer which all of our empty objects use
- EWCharString::EBuffer EWCharString::EBuffer::s_Empty_Buffer = { 0, 0, 0 };
- EWCharString::EBuffer* EWCharString::EBuffer::s_p_Empty_Buffer = &EWCharString::EBuffer::s_Empty_Buffer;
- // this must be a macro because the debug versions won't expand
- // inlines
- #define A2W(p_String) (\
- ((const char*)p_String == NULL) ? NULL : (\
- EWCharString::ToUnicode( (LPWSTR)_alloca((lstrlenA(p_String)+1)*2),\
- (const unsigned char*)p_String, (lstrlenA(p_String)+1)*2)))
- // if this doesn't want to link properly, this will have to become
- // a macro.
- /////////////////////////////////////////////////////////////////
- inline unsigned short* EWCharString::ToUnicode( unsigned short* p_Buffer,
- const unsigned char* p_Str,
- int Num_Chars )
- {
- gosASSERT( p_Buffer );
- gosASSERT( p_Str );
- p_Buffer[0] = 0;
- MultiByteToWideChar( CP_ACP, 0, (const char*)p_Str, -1, p_Buffer, Num_Chars );
- return p_Buffer;
- }
- /////////////////////////////////////////////////////////////////
- inline int EWCharString::StrSize( const EWCSChar* p_Str )
- {
- return ( p_Str == NULL ? 0 :
- #ifdef UNICODE
- wcslen( p_Str )
- #else
- lstrlen( (const char*)p_Str )
- #endif
- );
- }
- /////////////////////////////////////////////////////////////////
- void EWCharString::ChecEBufferDoRealloc()
- {
- if ( m_pBuffer->m_Ref_Count > 0 )
- {
- m_pBuffer->m_Ref_Count --;
- int Cur_Length = m_pBuffer->m_Data_Length;
- EWCSChar* p_Data = m_pBuffer->Data();
- Alloc( Cur_Length );
- memcpy( m_pBuffer + 1, p_Data, Cur_Length * sizeof( EWCSChar ) );
- m_pBuffer->m_Data_Length = Cur_Length;
- }
- }
- //***************************************************************
- //==============================================================
- // Constructors/Destructors
- //==============================================================
- ///////////////////////////////////////////////////////////////
- EWCharString::EWCharString( const EWCSChar* p_String )
- : m_pBuffer( EBuffer::s_p_Empty_Buffer )
- {
- if ( p_String != NULL )
- {
- Assign( p_String );
- }
- }
- ///////////////////////////////////////////////////////////////
- EWCharString::EWCharString( const EWCharString& Src_String )
- : m_pBuffer( Src_String.m_pBuffer )
- {
- m_pBuffer->m_Ref_Count++;
- }
- ///////////////////////////////////////////////////////////////
- EWCharString::EWCharString() : m_pBuffer( EBuffer::s_p_Empty_Buffer )
- {
- }
- ///////////////////////////////////////////////////////////////
- EWCharString::EWCharString( const EWCSChar Char )
- {
- Alloc( 2 );
- *(m_pBuffer->Data()) = Char;
- *(m_pBuffer->Data() + 1) = 0;
- m_pBuffer->m_Data_Length = 1;
- }
- ///////////////////////////////////////////////////////////////
- EWCharString::~EWCharString()
- {
- m_pBuffer->Release();
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Assign( const EWCSChar* p_String )
- {
-
- // handle NULL case
- if ( !p_String )
- {
- m_pBuffer->Release();
- m_pBuffer = EBuffer::s_p_Empty_Buffer;
- }
-
- int Len = StrSize( p_String ) + 1;
-
- // buffer big enough, we can recycle
- if ( m_pBuffer->m_Alloc_Length >= Len )
- {
- memcpy( m_pBuffer + 1, p_String, Len * sizeof( EWCSChar ) );
- m_pBuffer->m_Data_Length = Len - 1;
- }
- else if ( p_String ) // need to allocate new buffer
- {
- m_pBuffer->Release();
- Alloc( Len );
- memcpy( m_pBuffer->Data(), p_String, Len * sizeof( EWCSChar ) );
- m_pBuffer->m_Data_Length = Len - 1;
- }
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Alloc( int Min_Amount )
- {
- // we're rouding up to the nearest multiple of 4 for now
- Min_Amount = (Min_Amount/s_Alloc_Allign + 1) * s_Alloc_Allign;
- m_pBuffer = (EWCharString::EBuffer*)new BYTE[sizeof(EBuffer) +
- (Min_Amount)*sizeof(EWCSChar)];
- memset( m_pBuffer, 0, sizeof(EBuffer) + (Min_Amount)*sizeof(EWCSChar) );
-
- m_pBuffer->m_Alloc_Length = Min_Amount;
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Replace( int Start_Index, const EWCSChar* p_String )
- {
- // keep the buffer
- EBuffer* p_Tmp = m_pBuffer;
- int Cur_Len = m_pBuffer->m_Data_Length;
- // unshare any shared buffers
- ChecEBuffer();
- gosASSERT( Start_Index <= Cur_Len );
-
- // check the current buffer, not the current
- // length
- if ( Start_Index <= Cur_Len )
- {
-
- int Length = StrSize( p_String );
- int Alloc_Length = Start_Index + Length + 1;
- if ( Alloc_Length <= m_pBuffer->m_Alloc_Length )
- {
- memcpy( m_pBuffer->Data() + Start_Index,
- p_String, Length * sizeof( EWCSChar ) );
- // Add on the NULL if necessary
- if ( Start_Index + Length > Cur_Len )
- {
- *(m_pBuffer->Data() + Start_Index + Length + 1 ) = NULL;
- m_pBuffer->m_Data_Length = Length + Start_Index;
- }
- }
- else // need to reallocate here
- {
- EBuffer* p_Old_Buffer = m_pBuffer;
- m_pBuffer = EBuffer::s_p_Empty_Buffer;
- if ( Cur_Len > Alloc_Length )
- {
- Alloc_Length = Cur_Len;
- }
-
- Alloc( Alloc_Length );
-
- memcpy( m_pBuffer->Data(),
- p_Tmp->Data(),
- (Cur_Len + 1)*sizeof(EWCSChar) );
- memcpy( m_pBuffer->Data() + Start_Index,
- p_String, Length*sizeof(EWCSChar) );
- m_pBuffer->m_Data_Length = Alloc_Length;
- p_Old_Buffer->Release();
- }
- // check to see if the p_String is null
- if ( p_String == NULL )
- {
- *(m_pBuffer->Data() + Start_Index) = 0;
- }
-
- }
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Replace( int Start_Index, const EWCharString& String )
- {
- Replace( Start_Index, String.m_pBuffer->Data() );
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Insert( int Start_Index, const EWCSChar* p_String )
- {
- if ( Start_Index != INVALID_INDEX && Start_Index <= StrSize( Data() ) )
- {
- EBuffer* p_Tmp = m_pBuffer;
- EBuffer* p_Old_Buffer = NULL;
- ChecEBuffer();
- int Length = StrSize( p_String );
- // add on 2 for the 'nulls'
- if ( Length + p_Tmp->m_Data_Length + 1 > m_pBuffer->m_Alloc_Length )
- {
- p_Old_Buffer = m_pBuffer;
- Alloc( Length + p_Tmp->m_Data_Length + 1 );
- }
-
- // use memmove in case we are recycling a buffer.
- memmove( m_pBuffer->Data(), p_Tmp->Data(), Start_Index * sizeof ( EWCSChar ) );
- memmove( m_pBuffer->Data() + (Start_Index + Length), p_Tmp->Data() + (Start_Index),
- (p_Tmp->m_Data_Length - Start_Index) * sizeof (EWCSChar) );
- // write the string last in case we are writing over an old buffer
- memcpy( m_pBuffer->Data() + Start_Index, p_String, Length * sizeof( EWCSChar ) );
-
-
- m_pBuffer->m_Data_Length = Length + p_Tmp->m_Data_Length;
- // Bill added - in some cases, removing some characters then inserting fewer
- // was leaving garbage at the end of the string.
- // i.e., the trailing NULL was not being moved.
- (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
- // free the old buffer -- can't do this earlier, because we
- // need to copy out of it
- if ( p_Old_Buffer )
- {
- p_Old_Buffer->Release();
- }
- }
- }
- ///////////////////////////////////////////////////////////////
- bool EWCharString::Remove( int Start_Index, int End_Index )
- {
- // Bill changed - this function could not handle removing a single character
- // - also this didn't remove the character pointed to by End_Index
- if( Start_Index <= End_Index && End_Index < m_pBuffer->m_Data_Length)
- {
- ChecEBufferDoRealloc();
- memcpy( m_pBuffer->Data() + Start_Index, m_pBuffer->Data() + End_Index + 1,
- (StrSize(m_pBuffer->Data()) - End_Index + 1)*sizeof(EWCSChar) );
- m_pBuffer->m_Data_Length -= (End_Index - Start_Index + 1);
- // Bill added - in some cases, removing some characters then inserting fewer
- // was leaving garbage at the end of the string.
- // i.e., the trailing NULL was not being moved.
- (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
- return true;
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::Remove( EWCharString& Sub_String )
- {
- int Index = Find( Sub_String );
- if ( Index != -1 )
- {
- return Remove( Index, Index + Sub_String.StrSize( Sub_String.Data() ) - 1 );
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Swap( EWCharString& Src )
- {
- EBuffer* p_Tmp = Src.m_pBuffer;
- Src.m_pBuffer = m_pBuffer;
- m_pBuffer = p_Tmp;
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::MakeUpper()
- {
- ChecEBufferDoRealloc();
- KToUpper( m_pBuffer->Data() );
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::MakeLower()
- {
- ChecEBufferDoRealloc();
- KToLower( m_pBuffer->Data() );
- }
- ///////////////////////////////////////////////////////////////
- void EWCharString::Reverse()
- {
- ChecEBufferDoRealloc();
-
- KReverse( m_pBuffer->Data() );
- }
- // works like sprintf
- ///////////////////////////////////////////////////////////////
- void EWCharString::Format( const EWCSChar* p_Str, ... )
- {
- va_list Arg_List;
-
- va_start(Arg_List, p_Str);
- va_list Arg_List_Save = Arg_List;
- // make a guess at the maximum length of the resulting string
- int Max_Len = 0;
- for (const EWCSChar* p_Tmp = p_Str; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
- {
- // handle '%' character, but watch out for '%%'
- if (*p_Tmp != '%' || *(p_Tmp = KSInc(p_Tmp)) == '%')
- {
- Max_Len += EWCSCharLen(p_Tmp);
- continue;
- }
- int Item_Len = 0;
- // handle '%' character with format
- int Width = 0;
- for (; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
- {
- // check for valid flags
- if (*p_Tmp == '#')
- Max_Len += 2; // for '0x'
- else if (*p_Tmp == '*')
- Width = va_arg(Arg_List, int);
- else if (*p_Tmp == '-' || *p_Tmp == '+' || *p_Tmp == '0' ||
- *p_Tmp == ' ')
- ;
- else // hit non-flag character
- break;
- }
- // get width and skip it
- if ( Width == 0)
- {
- // width indicated by
- Width = KToI(p_Tmp);
- unsigned short buffer;
- for (; *p_Tmp != '\0'; )
- {
- GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
- if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
- p_Tmp = KSInc(p_Tmp);
- else
- break;
- }
- }
-
- gosASSERT( Width >= 0);
- int Precision = 0;
- if (*p_Tmp == '.')
- {
- // skip past '.' separator (width.precision)
- p_Tmp = KSInc(p_Tmp);
- // get precision and skip it
- if (*p_Tmp == '*')
- {
- Precision = va_arg(Arg_List, int);
- p_Tmp = KSInc(p_Tmp);
- }
- else
- {
- Precision = KToI(p_Tmp);
- for (; *p_Tmp != '\0'; )
- {
- unsigned short buffer;
- GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
- //if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
- if (buffer & C1_DIGIT) //mh
- p_Tmp = KSInc(p_Tmp);
- else
- break;
- }
- }
- gosASSERT( Precision >= 0);
- }
- // should be on type modifier or specifier
- int Modifier = 0;
- switch (*p_Tmp)
- {
- // modifiers that affect size
- case 'h':
- Modifier = s_Force_Ansi;
- p_Tmp = KSInc(p_Tmp);
- break;
- case 'l':
- Modifier = s_Force_Unicode;
- p_Tmp = KSInc(p_Tmp);
- break;
- // modifiers that do not affect size
- case 'F':
- case 'N':
- case 'L':
- p_Tmp = KSInc(p_Tmp);
- break;
- }
- // now should be on specifier
- switch (*p_Tmp | Modifier)
- {
- // single characters
- case 'c':
- case 'C':
- Item_Len = 2;
- va_arg(Arg_List, EWCSChar);
- break;
- case 'c'|s_Force_Ansi:
- case 'C'|s_Force_Ansi:
- Item_Len = 2;
- va_arg(Arg_List, char);
- break;
- case 'c'|s_Force_Unicode:
- case 'C'|s_Force_Unicode:
- Item_Len = 2;
- va_arg(Arg_List, short);
- break;
- // strings
- case 's':
- {
- const EWCSChar* p_Next_Arg = va_arg(Arg_List, const EWCSChar*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = StrSize(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- case 'S':
- {
- #ifndef K_UNICODE
- const unsigned short* p_Next_Arg = va_arg(Arg_List, const unsigned short*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = wcslen(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- #else
- const char* p_Next_Arg = va_arg(Arg_List, const char*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = lstrlenA(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- #endif
- break;
- }
- case 's'|s_Force_Ansi:
- case 'S'|s_Force_Ansi:
- {
- const char* p_Next_Arg = va_arg(Arg_List, const char*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = lstrlenA(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- #ifndef _MAC
- case 's'|s_Force_Unicode:
- case 'S'|s_Force_Unicode:
- {
- LPWSTR pstrNextArg = va_arg(Arg_List, LPWSTR);
- if (pstrNextArg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = wcslen(pstrNextArg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- #endif
- }
- // adjust nItemLen for strings
- if (Item_Len != 0)
- {
- Item_Len = max(Item_Len, Width);
- if (Precision != 0)
- {
- Item_Len = min(Item_Len, Precision);
- }
- }
- else
- {
- switch (*p_Tmp)
- {
- // integers
- case 'd':
- case 'i':
- case 'u':
- case 'x':
- case 'X':
- case 'o':
- va_arg(Arg_List, int);
- Item_Len = 32;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- case 'e':
- case 'f':
- case 'g':
- case 'G':
- va_arg(Arg_List, double);
- Item_Len = 128;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- case 'p':
- va_arg(Arg_List, void*);
- Item_Len = 32;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- // no output
- case 'n':
- va_arg(Arg_List, int*);
- break;
-
- case 'I': // assume INT64 skip next two chars
- p_Tmp = KSInc(p_Tmp);
- p_Tmp = KSInc(p_Tmp);
- p_Tmp = KSInc(p_Tmp);
- Item_Len = 64;
- va_arg(Arg_List, __int64);
- break;
- default:
- gosASSERT(false); // unknown formatting option
- }
- }
- // adjust nMaxLen for output nItemLen
- Max_Len += Item_Len;
- }
- // make sure noone else is using this buffer
- ChecEBuffer();
-
- if ( Max_Len > m_pBuffer->m_Alloc_Length )
- {
- m_pBuffer->Release();
- Alloc( Max_Len + 1 );
- }
- #ifdef UNICODE
- vswprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
- #else
- vsprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
- #endif
- m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
- // clean up
- va_end( Arg_List );
-
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCharString& Begin_String,
- const EWCharString& End_String )
- {
- return Begin_String + End_String.m_pBuffer->Data();
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCSChar* p_Begin_String,
- const EWCharString& End_String )
- {
- EWCharString Ret_String;
- int Length = EWCharString::StrSize( p_Begin_String );
-
- Ret_String.Alloc( End_String.m_pBuffer->m_Data_Length + Length + 1 );
- memcpy( Ret_String.m_pBuffer->Data(), p_Begin_String, Length );
- memcpy( Ret_String.m_pBuffer->Data() + Length,
- End_String.m_pBuffer->Data(),
- End_String.m_pBuffer->m_Data_Length );
- Ret_String.m_pBuffer->m_Data_Length = Length + End_String.m_pBuffer->m_Data_Length;
- return Ret_String;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCharString& Begin_String, const EWCSChar* p_End_String )
- {
- EWCharString Ret_String;
- int Length = EWCharString::StrSize( p_End_String );
-
- Ret_String.Alloc( Begin_String.m_pBuffer->m_Data_Length + Length + 1 );
- memcpy( Ret_String.m_pBuffer->Data(),
- Begin_String.m_pBuffer->Data(),
- Begin_String.m_pBuffer->m_Data_Length);
- memcpy( Ret_String.m_pBuffer->Data() + Begin_String.m_pBuffer->m_Data_Length,
- p_End_String, Length );
- Ret_String.m_pBuffer->m_Data_Length = Length + Begin_String.m_pBuffer->m_Data_Length;
- return Ret_String;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCharString& Begin_String, EWCSChar Char )
- {
- EWCSChar Tmp[2];
- Tmp[0] = Char;
- Tmp[1] = 0;
- return Begin_String + Char;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCSChar Char, const EWCharString& Begin_String )
- {
- EWCSChar Tmp[2];
- Tmp[0] = Char;
- Tmp[1] = 0;
- return Tmp + Begin_String;
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Compare( const EWCharString& Str_To_Compare, bool Case_Sensitive ) const
- {
- return Compare( Str_To_Compare.m_pBuffer->Data(), Case_Sensitive );
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Compare( const EWCSChar* p_String, bool Case_Sensitive ) const
- {
-
- int Length = StrSize( p_String );
- if ( 0 == StrSize(m_pBuffer->Data()) )
- {
- if ( Length )
- return -1;
- return 0;
- }
- if ( !Length )
- {
- return 1;
- }
-
- //if ( m_pBuffer->m_Data_Length != Length )
- //{
- // return ( m_pBuffer->m_Data_Length < Length ? -1 : 1 );
- //}
- if ( Case_Sensitive )
- {
- return ( memcmp( m_pBuffer->Data(), p_String, Length ) );
- }
- return (KStrCmp( m_pBuffer->Data(), p_String ) );
-
- }
-
- /////////////////////////////////////////////////////////////////
- int EWCharString::Size() const // number of bytes
- {
- return m_pBuffer->m_Data_Length * sizeof(EWCSChar);
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Length() const // number of characters
- {
- #ifdef UNICODE
- return wcslen( m_pBuffer->Data() );
- #else
- return lstrlen( (char*)m_pBuffer->Data() );
- #endif
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Find( EWCSChar Char, int Start_Index ) const
- {
- if ( Start_Index == -1 )
- {
- Start_Index = 0;
- }
-
- EWCSChar* p_Tmp = m_pBuffer->Data();
- // Bill added this line - this function ingored the start index
- p_Tmp += Start_Index;
- while( *p_Tmp )
- {
- if ( *p_Tmp == Char )
- {
- return p_Tmp - m_pBuffer->Data();
- }
-
- p_Tmp++;
-
- }
- return INVALID_INDEX;
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Find( const EWCharString& Str_To_Find, int Start_Index ) const
- {
- if ( -1 == Start_Index )
- {
- Start_Index = 0;
- }
-
- EWCSChar* p_Tmp = KStrStr( m_pBuffer->Data() + Start_Index,
- Str_To_Find.m_pBuffer->Data() );
- return ( p_Tmp ? p_Tmp - m_pBuffer->Data() : INVALID_INDEX );
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Find( const EWCSChar* p_Str_To_Find, int Start_Index ) const
- {
- if ( -1 == Start_Index )
- {
- Start_Index = 0;
- }
-
- EWCSChar* p_Tmp = KStrStr( m_pBuffer->Data() + Start_Index,
- p_Str_To_Find );
- return ( p_Tmp ? p_Tmp - m_pBuffer->Data() : INVALID_INDEX );
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::ReverseFind ( EWCSChar Char, int End_Index ) const
- {
- if ( -1 == End_Index )
- {
- End_Index = m_pBuffer->m_Data_Length;
- }
-
- EWCSChar* p_Tmp = m_pBuffer->Data() + End_Index;
- while( End_Index >= 0 )
- {
- if ( *p_Tmp == Char )
- {
- return End_Index;
- }
-
- p_Tmp --;
- End_Index --;
-
- }
- return INVALID_INDEX;
- }
- /////////////////////////////////////////////////////////////////
- #ifndef UNICODE
- int EWCharString::Find( unsigned short Char, int Start_Index ) const
- {
- unsigned short Tmp[2];
- *Tmp = Char;
- Tmp[2] = 0;
- return Find( (EWCSChar*)Tmp, Start_Index );
- }
- #endif // !K_UNICODE
-
- /////////////////////////////////////////////////////////////////
- EWCharString EWCharString::SubString( int Start_Index, int End_Index ) const
- {
- EWCharString Ret_String;
- // Bill changed so that it can return a single character
- // (Start == End)
- gosASSERT( Start_Index <= End_Index &&
- End_Index < m_pBuffer->m_Data_Length );
- Ret_String.Alloc( End_Index - Start_Index + 2);
- EWCSChar* p_Dest = Ret_String.m_pBuffer->Data();
- EWCSChar* p_Src = m_pBuffer->Data() + Start_Index;
- memcpy( p_Dest,
- p_Src,
- (End_Index - Start_Index + 1) * sizeof(EWCSChar) );
- *(p_Dest + End_Index - Start_Index + 1) = 0;
- Ret_String.m_pBuffer->m_Data_Length = End_Index - Start_Index + 1;
- return Ret_String;
- }
- /////////////////////////////////////////////////////////////////
- unsigned short* EWCharString::CreateUNICODE() const
- {
- #ifdef UNICODE
- unsigned short* p_Ret_String = new unsigned short[m_pBuffer->m_Data_Length + 1];
- memcpy( p_Ret_String, m_pBuffer->Data(), 2*(m_pBuffer->m_Data_Length + 1) );
- return p_Ret_String;
- #else
- unsigned short* p_Ret_String = new unsigned short[lstrlen((char*)m_pBuffer->Data()) + 1];
- ToUnicode( p_Ret_String, (unsigned char*)m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
- return p_Ret_String;
- #endif
- }
- /////////////////////////////////////////////////////////////////
- char* EWCharString::CreateMBCS() const
- {
- char* p_Ret_String = new char[m_pBuffer->m_Data_Length + 1];
- #ifdef K_UNICODE
- wcstombs( p_Ret_String, m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
- #else
- memcpy( p_Ret_String, m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
- #endif
- return p_Ret_String;
- }
-
- ///****************************************************************
- #ifdef K_UNICODE
- /////////////////////////////////////////////////////////////////
- EWCharString::EWCharString(const char* p_String )
- : m_pBuffer( EBuffer::s_p_Empty_Buffer )
- {
- if ( p_String )
- {
- Assign( A2W( p_String ) );
- }
- }
-
- /////////////////////////////////////////////////////////////////
- const EWCharString& EWCharString::operator+=( const char* p_String )
- {
- if ( p_String )
- {
- *this += A2W( p_String );
- }
- return *this;
- }
- /////////////////////////////////////////////////////////////////
- const EWCharString& EWCharString::operator+=( char Char )
- {
-
- char Tmp[2];
- Tmp[0] = Char;
- Tmp[1] = 0;
- *this += A2W( Tmp );
- return *this;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( const EWCharString& Begin_String, char* p_End_String )
- {
- EWCharString RetString( Begin_String );
-
- if ( p_End_String )
- {
- RetString += A2W( p_End_String );
- }
- return RetString;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( char* p_Begin_String, const EWCharString& End_String )
- {
- EWCharString RetString( A2W( p_Begin_String) + End_String );
- return RetString;
- }
- /////////////////////////////////////////////////////////////////
- EWCharString operator+( char Char, const EWCharString& End_String )
- {
- char Tmp[2];
- Tmp[0] = Char;
- Tmp[1] = 0;
- EWCharString RetString( A2W( Tmp ) + End_String );
-
- return RetString;
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator<( const char* p_String ) const
- {
- return operator<(A2W( p_String ) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator<( const char* p_String, const EWCharString& String )
- {
- return operator<(A2W(p_String), String );
- }
-
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator>( const char* p_String ) const
- {
- return EWCharString::operator>(A2W( p_String) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator>( const char* p_String, const EWCharString& String )
- {
- return operator>( A2W(p_String), String );
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator<=( const char* p_String) const
- {
- return EWCharString::operator<=( A2W(p_String) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator<=( const char* p_String, const EWCharString& String)
- {
- return ( A2W( p_String ) <= String );
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator>=( const char* p_String) const
- {
- return EWCharString::operator>=( A2W(p_String) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator>=( const char* p_String, const EWCharString& String)
- {
- return ( A2W( p_String ) >= String );
- }
- /////////////////////////////////////////////////////////////////
- void EWCharString::Format( const char* p_Str, ... )
- {
- // NOTE, we are assuming that the end user has
- // made ALL STRING parameters UNICODE
- va_list Arg_List;
-
- va_start(Arg_List, p_Str);
- va_list Arg_List_Save = Arg_List;
- // make a guess at the maximum length of the resulting string
- int Max_Len = 0;
- for (const char* p_Tmp = p_Str; *p_Tmp != '\0'; p_Tmp = _tcsinc(p_Tmp))
- {
- // handle '%' character, but watch out for '%%'
- if (*p_Tmp != '%' || *(p_Tmp = _tcsinc(p_Tmp)) == '%')
- {
- Max_Len += lstrlenA(p_Tmp);
- continue;
- }
- int Item_Len = 0;
- // handle '%' character with format
- int Width = 0;
- for (; *p_Tmp != '\0'; p_Tmp = _tcsinc(p_Tmp))
- {
- // check for valid flags
- if (*p_Tmp == '#')
- Max_Len += 2; // for '0x'
- else if (*p_Tmp == '*')
- Width = va_arg(Arg_List, int);
- else if (*p_Tmp == '-' || *p_Tmp == '+' || *p_Tmp == '0' ||
- *p_Tmp == ' ')
- ;
- else // hit non-flag character
- break;
- }
- // get width and skip it
- if ( Width == 0)
- {
- // width indicated by
- Width = atoi(p_Tmp);
- for (; *p_Tmp != '\0' && _istdigit(*p_Tmp); p_Tmp = _tcsinc(p_Tmp))
- ;
- }
-
- gosASSERT( Width >= 0);
- int Precision = 0;
- if (*p_Tmp == '.')
- {
- // skip past '.' separator (width.precision)
- p_Tmp = _tcsinc(p_Tmp);
- // get precision and skip it
- if (*p_Tmp == '*')
- {
- Precision = va_arg(Arg_List, int);
- p_Tmp = _tcsinc(p_Tmp);
- }
- else
- {
- Precision = atoi(p_Tmp);
- for (; *p_Tmp != '\0' && _istdigit(*p_Tmp); p_Tmp = _tcsinc(p_Tmp))
- ;
- }
- gosASSERT( Precision >= 0);
- }
- // should be on type modifier or specifier
- int Modifier = 0;
- switch (*p_Tmp)
- {
- // modifiers that affect size
- case 'h':
- Modifier = s_Force_Ansi;
- p_Tmp = _tcsinc(p_Tmp);
- break;
- case 'l':
- Modifier = s_Force_Unicode;
- p_Tmp = _tcsinc(p_Tmp);
- break;
- // modifiers that do not affect size
- case 'F':
- case 'N':
- case 'L':
- p_Tmp = _tcsinc(p_Tmp);
- break;
- }
- // now should be on specifier
- switch (*p_Tmp | Modifier)
- {
- // single characters
- case 'c':
- case 'C':
- Item_Len = 2;
- // here we are asuming regular char
- va_arg(Arg_List, char);
- break;
- case 'c'|s_Force_Ansi:
- case 'C'|s_Force_Ansi:
- Item_Len = 2;
- va_arg(Arg_List, char);
- break;
- case 'c'|s_Force_Unicode:
- case 'C'|s_Force_Unicode:
- Item_Len = 2;
- va_arg(Arg_List, short);
- break;
- // strings
- case 's':
- {
- const char* p_Next_Arg = va_arg(Arg_List, const char*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = lstrlenA(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- case 'S':
- {
- #ifndef K_UNICODE
- const unsigned short* p_Next_Arg = va_arg(Arg_List, const unsigned short*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = wcslen(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- #else
- const char* p_Next_Arg = va_arg(Arg_List, const char*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = lstrlenA(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- #endif
- break;
- }
- case 's'|s_Force_Ansi:
- case 'S'|s_Force_Ansi:
- {
- const char* p_Next_Arg = va_arg(Arg_List, const char*);
- if (p_Next_Arg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = lstrlenA(p_Next_Arg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- #ifndef _MAC
- case 's'|s_Force_Unicode:
- case 'S'|s_Force_Unicode:
- {
- LPWSTR pstrNextArg = va_arg(Arg_List, LPWSTR);
- if (pstrNextArg == NULL)
- Item_Len = 6; // "(null)"
- else
- {
- Item_Len = wcslen(pstrNextArg);
- Item_Len = max(1, Item_Len);
- }
- break;
- }
- #endif
- }
- // adjust nItemLen for strings
- if (Item_Len != 0)
- {
- Item_Len = max(Item_Len, Width);
- if (Precision != 0)
- {
- Item_Len = min(Item_Len, Precision);
- }
- }
- else
- {
- switch (*p_Tmp)
- {
- // integers
- case 'd':
- case 'i':
- case 'u':
- case 'x':
- case 'X':
- case 'o':
- va_arg(Arg_List, int);
- Item_Len = 32;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- case 'e':
- case 'f':
- case 'g':
- case 'G':
- va_arg(Arg_List, double);
- Item_Len = 128;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- case 'p':
- va_arg(Arg_List, void*);
- Item_Len = 32;
- Item_Len = max(Item_Len, Width + Precision);
- break;
- // no output
- case 'n':
- va_arg(Arg_List, int*);
- break;
- case 'I': // assume INT64 skip next two chars
- p_Tmp = _tcsinc(p_Tmp);
- p_Tmp = _tcsinc(p_Tmp);
- p_Tmp = _tcsinc(p_Tmp);
- Item_Len = 64;
- va_arg(Arg_List, __int64);
- break;
- default:
- gosASSERT(false); // unknown formatting option
- }
- }
- // adjust nMaxLen for output nItemLen
- Max_Len += Item_Len;
- }
- // make sure noone else is using this buffer
- ChecEBuffer();
-
- if ( Max_Len > m_pBuffer->m_Alloc_Length )
- {
- m_pBuffer->Release();
- Alloc( Max_Len + 1 );
- }
- char* pTmp = new char[ Max_Len + 1];
- vsprintf(pTmp, p_Str, Arg_List_Save);
- memcpy( m_pBuffer->Data(), A2W(pTmp), (Max_Len + 1)*sizeof(EWCSChar) );
- m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
- // clean up
- va_end( Arg_List );
-
-
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator==( const char* p_String )
- {
- return operator==( A2W( p_String ) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator==( const char* p_String, const EWCharString& String)
- {
- return operator==( A2W( p_String ), String );
- }
- /////////////////////////////////////////////////////////////////
- bool EWCharString::operator!=( const char* p_String) const
- {
- return operator!=( A2W(p_String) );
- }
- /////////////////////////////////////////////////////////////////
- bool operator!=( const char* p_String, const EWCharString& String )
- {
- return operator!=( A2W(p_String), String );
- }
- /////////////////////////////////////////////////////////////////
- int EWCharString::Find( char Char, int Start_Index ) const
- {
- EWCSChar Tmp;
- mbtowc( &Tmp, &Char, 1 );
-
- return Find( Tmp, Start_Index );
- }
- /////////////////////////////////////////////////////////////////
- const EWCharString& EWCharString::operator=( char Char )
- {
- EWCSChar Tmp;
- mbtowc( &Tmp, &Char, 1 );
- return operator=( Tmp );
- }
- #endif // Unicode
- //***************************************************************
- /* restore UNICODE, K_UNICODE and MBCS to their previous state */
- #ifndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #undef UNICODE
- #else
- #undef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #endif /* ndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
- #ifndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #undef K_UNICODE
- #else
- #undef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #endif /* ndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
- #ifdef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #undef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
- #define MBCS _PREVIOUS_MBCS___EWCharString_CPP
- #undef _PREVIOUS_MBCS___EWCharString_CPP
- #endif /* def _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
- //***************************************************************
- //****************************************************************
- #pragma warning( pop )
|