EWCharString.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601
  1. #define EWCharString_CPP
  2. //===========================================================================//
  3. // Copyright (C) Microsoft Corporation. All rights reserved. //
  4. //===========================================================================//
  5. //***************************************************************
  6. /* just for this file, we want UNICODE and K_UNICODE defined and MBCS undefined */
  7. #ifdef UNICODE
  8. #define _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  9. #else
  10. #define UNICODE
  11. #endif /* def UNICODE */
  12. #ifdef K_UNICODE
  13. #define _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  14. #else
  15. #define K_UNICODE
  16. #endif /* def K_UNICODE */
  17. #ifdef MBCS
  18. #define _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  19. #define _PREVIOUS_MBCS___EWCharString_CPP MBCS
  20. #undef MBCS
  21. #endif /* def MBCS */
  22. //***************************************************************
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include "EWCharString.h"
  26. #include <gameos.hpp>
  27. #ifdef UNICODE
  28. #include <malloc.h>
  29. #include <tchar.h>
  30. #endif
  31. #pragma warning( disable:4505 )
  32. #pragma warning( push )
  33. #pragma warning( disable:4100 )
  34. #define INT_SIZE_LENGTH 20
  35. extern int __ismbcodepage;
  36. #define _ISNOTMBCP (__ismbcodepage == 0)
  37. static wchar_t * __cdecl wideRev (
  38. wchar_t * string
  39. )
  40. {
  41. wchar_t *start = string;
  42. wchar_t *left = string;
  43. wchar_t ch;
  44. while (*string++) /* find end of string */
  45. ;
  46. string -= 2;
  47. while (left < string)
  48. {
  49. ch = *left;
  50. *left++ = *string;
  51. *string-- = ch;
  52. }
  53. return(start);
  54. }
  55. static wchar_t * __cdecl wideStrStr (
  56. const wchar_t * wcs1,
  57. const wchar_t * wcs2
  58. )
  59. {
  60. wchar_t *cp = (wchar_t *) wcs1;
  61. wchar_t *s1, *s2;
  62. while (*cp)
  63. {
  64. s1 = cp;
  65. s2 = (wchar_t *) wcs2;
  66. while ( *s1 && *s2 && !(*s1-*s2) )
  67. s1++, s2++;
  68. if (!*s2)
  69. return(cp);
  70. cp++;
  71. }
  72. return(NULL);
  73. }
  74. static int __cdecl wideToInt(
  75. const wchar_t *nptr
  76. )
  77. {
  78. char astring[20];
  79. WideCharToMultiByte (CP_ACP, 0, nptr, -1,
  80. astring, INT_SIZE_LENGTH, NULL, NULL);
  81. return ((int)atol(astring));
  82. }
  83. static long __cdecl atolong(
  84. const char *nptr
  85. )
  86. {
  87. int c; /* current char */
  88. long total; /* current total */
  89. int sign; /* if '-', then negative, otherwise positive */
  90. /* skip whitespace */
  91. while ( isspace((int)(unsigned char)*nptr) )
  92. ++nptr;
  93. c = (int)(unsigned char)*nptr++;
  94. sign = c; /* save sign indication */
  95. if (c == '-' || c == '+')
  96. c = (int)(unsigned char)*nptr++; /* skip sign */
  97. total = 0;
  98. while (isdigit(c)) {
  99. total = 10 * total + (c - '0'); /* accumulate digit */
  100. c = (int)(unsigned char)*nptr++; /* get next char */
  101. }
  102. if (sign == '-')
  103. return -total;
  104. else
  105. return total; /* return result, negated if necessary */
  106. }
  107. static char * __cdecl StrStr (
  108. const char * str1,
  109. const char * str2
  110. )
  111. {
  112. char *cp = (char *) str1;
  113. char *s1, *s2;
  114. if ( !*str2 )
  115. return((char *)str1);
  116. while (*cp)
  117. {
  118. s1 = cp;
  119. s2 = (char *) str2;
  120. while ( *s1 && *s2 && !(*s1-*s2) )
  121. s1++, s2++;
  122. if (!*s2)
  123. return(cp);
  124. cp++;
  125. }
  126. return(NULL);
  127. }
  128. static char * __cdecl StrRev (
  129. char * string
  130. )
  131. {
  132. char *start = string;
  133. char *left = string;
  134. char ch;
  135. while (*string++) /* find end of string */
  136. ;
  137. string -= 2;
  138. while (left < string)
  139. {
  140. ch = *left;
  141. *left++ = *string;
  142. *string-- = ch;
  143. }
  144. return(start);
  145. }
  146. //***************************************************************
  147. #ifdef UNICODE
  148. #define KToUpper CharUpper
  149. #define KToLower CharLower
  150. #define KReverse wideRev
  151. #define KStrCmp lstrcmpi
  152. #define klstrlen lstrlen
  153. #define KStrStr wideStrStr
  154. inline const EWCSChar* KSInc(const EWCSChar* p) { return p+1; }
  155. inline size_t EWCSCharLen( const EWCSChar* p ) {return 2;}
  156. #define KToI wideToInt
  157. #else
  158. #define KToI atolong
  159. #define KStrCmp lstrcmpi
  160. #define klstrlen lstrlen
  161. #define KToUpper CharUpper
  162. #define KToLower CharLower
  163. #ifdef MBCS
  164. #define KReverse mbrev
  165. #define KStrStr _mbsstr
  166. #define KSInc _mbsinc
  167. #define EWCSCharLen _mbclen
  168. #else // single byte
  169. #define KReverse StrRev
  170. #define KStrStr StrStr
  171. __inline char * __cdecl KSInc(const char * _pc) { return (char *)(_pc+1); }
  172. inline int EWCSCharLen(const char* x){ return 1; }
  173. #endif
  174. #endif
  175. const int EWCharString::INVALID_INDEX = -1;
  176. const int EWCharString::s_Alloc_Allign = 4;
  177. const int EWCharString::s_Force_Ansi = 0x10000;
  178. const int EWCharString::s_Force_Unicode = 0x20000;
  179. // keep around an empty buffer which all of our empty objects use
  180. EWCharString::EBuffer EWCharString::EBuffer::s_Empty_Buffer = { 0, 0, 0 };
  181. EWCharString::EBuffer* EWCharString::EBuffer::s_p_Empty_Buffer = &EWCharString::EBuffer::s_Empty_Buffer;
  182. // this must be a macro because the debug versions won't expand
  183. // inlines
  184. #define A2W(p_String) (\
  185. ((const char*)p_String == NULL) ? NULL : (\
  186. EWCharString::ToUnicode( (LPWSTR)_alloca((lstrlenA(p_String)+1)*2),\
  187. (const unsigned char*)p_String, (lstrlenA(p_String)+1)*2)))
  188. // if this doesn't want to link properly, this will have to become
  189. // a macro.
  190. /////////////////////////////////////////////////////////////////
  191. inline unsigned short* EWCharString::ToUnicode( unsigned short* p_Buffer,
  192. const unsigned char* p_Str,
  193. int Num_Chars )
  194. {
  195. gosASSERT( p_Buffer );
  196. gosASSERT( p_Str );
  197. p_Buffer[0] = 0;
  198. MultiByteToWideChar( CP_ACP, 0, (const char*)p_Str, -1, p_Buffer, Num_Chars );
  199. return p_Buffer;
  200. }
  201. /////////////////////////////////////////////////////////////////
  202. inline int EWCharString::StrSize( const EWCSChar* p_Str )
  203. {
  204. return ( p_Str == NULL ? 0 :
  205. #ifdef UNICODE
  206. wcslen( p_Str )
  207. #else
  208. lstrlen( (const char*)p_Str )
  209. #endif
  210. );
  211. }
  212. /////////////////////////////////////////////////////////////////
  213. void EWCharString::ChecEBufferDoRealloc()
  214. {
  215. if ( m_pBuffer->m_Ref_Count > 0 )
  216. {
  217. m_pBuffer->m_Ref_Count --;
  218. int Cur_Length = m_pBuffer->m_Data_Length;
  219. EWCSChar* p_Data = m_pBuffer->Data();
  220. Alloc( Cur_Length );
  221. memcpy( m_pBuffer + 1, p_Data, Cur_Length * sizeof( EWCSChar ) );
  222. m_pBuffer->m_Data_Length = Cur_Length;
  223. }
  224. }
  225. //***************************************************************
  226. //==============================================================
  227. // Constructors/Destructors
  228. //==============================================================
  229. ///////////////////////////////////////////////////////////////
  230. EWCharString::EWCharString( const EWCSChar* p_String )
  231. : m_pBuffer( EBuffer::s_p_Empty_Buffer )
  232. {
  233. if ( p_String != NULL )
  234. {
  235. Assign( p_String );
  236. }
  237. }
  238. ///////////////////////////////////////////////////////////////
  239. EWCharString::EWCharString( const EWCharString& Src_String )
  240. : m_pBuffer( Src_String.m_pBuffer )
  241. {
  242. m_pBuffer->m_Ref_Count++;
  243. }
  244. ///////////////////////////////////////////////////////////////
  245. EWCharString::EWCharString() : m_pBuffer( EBuffer::s_p_Empty_Buffer )
  246. {
  247. }
  248. ///////////////////////////////////////////////////////////////
  249. EWCharString::EWCharString( const EWCSChar Char )
  250. {
  251. Alloc( 2 );
  252. *(m_pBuffer->Data()) = Char;
  253. *(m_pBuffer->Data() + 1) = 0;
  254. m_pBuffer->m_Data_Length = 1;
  255. }
  256. ///////////////////////////////////////////////////////////////
  257. EWCharString::~EWCharString()
  258. {
  259. m_pBuffer->Release();
  260. }
  261. ///////////////////////////////////////////////////////////////
  262. void EWCharString::Assign( const EWCSChar* p_String )
  263. {
  264. // handle NULL case
  265. if ( !p_String )
  266. {
  267. m_pBuffer->Release();
  268. m_pBuffer = EBuffer::s_p_Empty_Buffer;
  269. }
  270. int Len = StrSize( p_String ) + 1;
  271. // buffer big enough, we can recycle
  272. if ( m_pBuffer->m_Alloc_Length >= Len )
  273. {
  274. memcpy( m_pBuffer + 1, p_String, Len * sizeof( EWCSChar ) );
  275. m_pBuffer->m_Data_Length = Len - 1;
  276. }
  277. else if ( p_String ) // need to allocate new buffer
  278. {
  279. m_pBuffer->Release();
  280. Alloc( Len );
  281. memcpy( m_pBuffer->Data(), p_String, Len * sizeof( EWCSChar ) );
  282. m_pBuffer->m_Data_Length = Len - 1;
  283. }
  284. }
  285. ///////////////////////////////////////////////////////////////
  286. void EWCharString::Alloc( int Min_Amount )
  287. {
  288. // we're rouding up to the nearest multiple of 4 for now
  289. Min_Amount = (Min_Amount/s_Alloc_Allign + 1) * s_Alloc_Allign;
  290. m_pBuffer = (EWCharString::EBuffer*)new BYTE[sizeof(EBuffer) +
  291. (Min_Amount)*sizeof(EWCSChar)];
  292. memset( m_pBuffer, 0, sizeof(EBuffer) + (Min_Amount)*sizeof(EWCSChar) );
  293. m_pBuffer->m_Alloc_Length = Min_Amount;
  294. }
  295. ///////////////////////////////////////////////////////////////
  296. void EWCharString::Replace( int Start_Index, const EWCSChar* p_String )
  297. {
  298. // keep the buffer
  299. EBuffer* p_Tmp = m_pBuffer;
  300. int Cur_Len = m_pBuffer->m_Data_Length;
  301. // unshare any shared buffers
  302. ChecEBuffer();
  303. gosASSERT( Start_Index <= Cur_Len );
  304. // check the current buffer, not the current
  305. // length
  306. if ( Start_Index <= Cur_Len )
  307. {
  308. int Length = StrSize( p_String );
  309. int Alloc_Length = Start_Index + Length + 1;
  310. if ( Alloc_Length <= m_pBuffer->m_Alloc_Length )
  311. {
  312. memcpy( m_pBuffer->Data() + Start_Index,
  313. p_String, Length * sizeof( EWCSChar ) );
  314. // Add on the NULL if necessary
  315. if ( Start_Index + Length > Cur_Len )
  316. {
  317. *(m_pBuffer->Data() + Start_Index + Length + 1 ) = NULL;
  318. m_pBuffer->m_Data_Length = Length + Start_Index;
  319. }
  320. }
  321. else // need to reallocate here
  322. {
  323. EBuffer* p_Old_Buffer = m_pBuffer;
  324. m_pBuffer = EBuffer::s_p_Empty_Buffer;
  325. if ( Cur_Len > Alloc_Length )
  326. {
  327. Alloc_Length = Cur_Len;
  328. }
  329. Alloc( Alloc_Length );
  330. memcpy( m_pBuffer->Data(),
  331. p_Tmp->Data(),
  332. (Cur_Len + 1)*sizeof(EWCSChar) );
  333. memcpy( m_pBuffer->Data() + Start_Index,
  334. p_String, Length*sizeof(EWCSChar) );
  335. m_pBuffer->m_Data_Length = Alloc_Length;
  336. p_Old_Buffer->Release();
  337. }
  338. // check to see if the p_String is null
  339. if ( p_String == NULL )
  340. {
  341. *(m_pBuffer->Data() + Start_Index) = 0;
  342. }
  343. }
  344. }
  345. ///////////////////////////////////////////////////////////////
  346. void EWCharString::Replace( int Start_Index, const EWCharString& String )
  347. {
  348. Replace( Start_Index, String.m_pBuffer->Data() );
  349. }
  350. ///////////////////////////////////////////////////////////////
  351. void EWCharString::Insert( int Start_Index, const EWCSChar* p_String )
  352. {
  353. if ( Start_Index != INVALID_INDEX && Start_Index <= StrSize( Data() ) )
  354. {
  355. EBuffer* p_Tmp = m_pBuffer;
  356. EBuffer* p_Old_Buffer = NULL;
  357. ChecEBuffer();
  358. int Length = StrSize( p_String );
  359. // add on 2 for the 'nulls'
  360. if ( Length + p_Tmp->m_Data_Length + 1 > m_pBuffer->m_Alloc_Length )
  361. {
  362. p_Old_Buffer = m_pBuffer;
  363. Alloc( Length + p_Tmp->m_Data_Length + 1 );
  364. }
  365. // use memmove in case we are recycling a buffer.
  366. memmove( m_pBuffer->Data(), p_Tmp->Data(), Start_Index * sizeof ( EWCSChar ) );
  367. memmove( m_pBuffer->Data() + (Start_Index + Length), p_Tmp->Data() + (Start_Index),
  368. (p_Tmp->m_Data_Length - Start_Index) * sizeof (EWCSChar) );
  369. // write the string last in case we are writing over an old buffer
  370. memcpy( m_pBuffer->Data() + Start_Index, p_String, Length * sizeof( EWCSChar ) );
  371. m_pBuffer->m_Data_Length = Length + p_Tmp->m_Data_Length;
  372. // Bill added - in some cases, removing some characters then inserting fewer
  373. // was leaving garbage at the end of the string.
  374. // i.e., the trailing NULL was not being moved.
  375. (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
  376. // free the old buffer -- can't do this earlier, because we
  377. // need to copy out of it
  378. if ( p_Old_Buffer )
  379. {
  380. p_Old_Buffer->Release();
  381. }
  382. }
  383. }
  384. ///////////////////////////////////////////////////////////////
  385. bool EWCharString::Remove( int Start_Index, int End_Index )
  386. {
  387. // Bill changed - this function could not handle removing a single character
  388. // - also this didn't remove the character pointed to by End_Index
  389. if( Start_Index <= End_Index && End_Index < m_pBuffer->m_Data_Length)
  390. {
  391. ChecEBufferDoRealloc();
  392. memcpy( m_pBuffer->Data() + Start_Index, m_pBuffer->Data() + End_Index + 1,
  393. (StrSize(m_pBuffer->Data()) - End_Index + 1)*sizeof(EWCSChar) );
  394. m_pBuffer->m_Data_Length -= (End_Index - Start_Index + 1);
  395. // Bill added - in some cases, removing some characters then inserting fewer
  396. // was leaving garbage at the end of the string.
  397. // i.e., the trailing NULL was not being moved.
  398. (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
  399. return true;
  400. }
  401. return false;
  402. }
  403. /////////////////////////////////////////////////////////////////
  404. bool EWCharString::Remove( EWCharString& Sub_String )
  405. {
  406. int Index = Find( Sub_String );
  407. if ( Index != -1 )
  408. {
  409. return Remove( Index, Index + Sub_String.StrSize( Sub_String.Data() ) - 1 );
  410. }
  411. return false;
  412. }
  413. ///////////////////////////////////////////////////////////////
  414. void EWCharString::Swap( EWCharString& Src )
  415. {
  416. EBuffer* p_Tmp = Src.m_pBuffer;
  417. Src.m_pBuffer = m_pBuffer;
  418. m_pBuffer = p_Tmp;
  419. }
  420. ///////////////////////////////////////////////////////////////
  421. void EWCharString::MakeUpper()
  422. {
  423. ChecEBufferDoRealloc();
  424. KToUpper( m_pBuffer->Data() );
  425. }
  426. ///////////////////////////////////////////////////////////////
  427. void EWCharString::MakeLower()
  428. {
  429. ChecEBufferDoRealloc();
  430. KToLower( m_pBuffer->Data() );
  431. }
  432. ///////////////////////////////////////////////////////////////
  433. void EWCharString::Reverse()
  434. {
  435. ChecEBufferDoRealloc();
  436. KReverse( m_pBuffer->Data() );
  437. }
  438. // works like sprintf
  439. ///////////////////////////////////////////////////////////////
  440. void EWCharString::Format( const EWCSChar* p_Str, ... )
  441. {
  442. va_list Arg_List;
  443. va_start(Arg_List, p_Str);
  444. va_list Arg_List_Save = Arg_List;
  445. // make a guess at the maximum length of the resulting string
  446. int Max_Len = 0;
  447. for (const EWCSChar* p_Tmp = p_Str; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
  448. {
  449. // handle '%' character, but watch out for '%%'
  450. if (*p_Tmp != '%' || *(p_Tmp = KSInc(p_Tmp)) == '%')
  451. {
  452. Max_Len += EWCSCharLen(p_Tmp);
  453. continue;
  454. }
  455. int Item_Len = 0;
  456. // handle '%' character with format
  457. int Width = 0;
  458. for (; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
  459. {
  460. // check for valid flags
  461. if (*p_Tmp == '#')
  462. Max_Len += 2; // for '0x'
  463. else if (*p_Tmp == '*')
  464. Width = va_arg(Arg_List, int);
  465. else if (*p_Tmp == '-' || *p_Tmp == '+' || *p_Tmp == '0' ||
  466. *p_Tmp == ' ')
  467. ;
  468. else // hit non-flag character
  469. break;
  470. }
  471. // get width and skip it
  472. if ( Width == 0)
  473. {
  474. // width indicated by
  475. Width = KToI(p_Tmp);
  476. unsigned short buffer;
  477. for (; *p_Tmp != '\0'; )
  478. {
  479. GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
  480. if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
  481. p_Tmp = KSInc(p_Tmp);
  482. else
  483. break;
  484. }
  485. }
  486. gosASSERT( Width >= 0);
  487. int Precision = 0;
  488. if (*p_Tmp == '.')
  489. {
  490. // skip past '.' separator (width.precision)
  491. p_Tmp = KSInc(p_Tmp);
  492. // get precision and skip it
  493. if (*p_Tmp == '*')
  494. {
  495. Precision = va_arg(Arg_List, int);
  496. p_Tmp = KSInc(p_Tmp);
  497. }
  498. else
  499. {
  500. Precision = KToI(p_Tmp);
  501. for (; *p_Tmp != '\0'; )
  502. {
  503. unsigned short buffer;
  504. GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
  505. //if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
  506. if (buffer & C1_DIGIT) //mh
  507. p_Tmp = KSInc(p_Tmp);
  508. else
  509. break;
  510. }
  511. }
  512. gosASSERT( Precision >= 0);
  513. }
  514. // should be on type modifier or specifier
  515. int Modifier = 0;
  516. switch (*p_Tmp)
  517. {
  518. // modifiers that affect size
  519. case 'h':
  520. Modifier = s_Force_Ansi;
  521. p_Tmp = KSInc(p_Tmp);
  522. break;
  523. case 'l':
  524. Modifier = s_Force_Unicode;
  525. p_Tmp = KSInc(p_Tmp);
  526. break;
  527. // modifiers that do not affect size
  528. case 'F':
  529. case 'N':
  530. case 'L':
  531. p_Tmp = KSInc(p_Tmp);
  532. break;
  533. }
  534. // now should be on specifier
  535. switch (*p_Tmp | Modifier)
  536. {
  537. // single characters
  538. case 'c':
  539. case 'C':
  540. Item_Len = 2;
  541. va_arg(Arg_List, EWCSChar);
  542. break;
  543. case 'c'|s_Force_Ansi:
  544. case 'C'|s_Force_Ansi:
  545. Item_Len = 2;
  546. va_arg(Arg_List, char);
  547. break;
  548. case 'c'|s_Force_Unicode:
  549. case 'C'|s_Force_Unicode:
  550. Item_Len = 2;
  551. va_arg(Arg_List, short);
  552. break;
  553. // strings
  554. case 's':
  555. {
  556. const EWCSChar* p_Next_Arg = va_arg(Arg_List, const EWCSChar*);
  557. if (p_Next_Arg == NULL)
  558. Item_Len = 6; // "(null)"
  559. else
  560. {
  561. Item_Len = StrSize(p_Next_Arg);
  562. Item_Len = max(1, Item_Len);
  563. }
  564. break;
  565. }
  566. case 'S':
  567. {
  568. #ifndef K_UNICODE
  569. const unsigned short* p_Next_Arg = va_arg(Arg_List, const unsigned short*);
  570. if (p_Next_Arg == NULL)
  571. Item_Len = 6; // "(null)"
  572. else
  573. {
  574. Item_Len = wcslen(p_Next_Arg);
  575. Item_Len = max(1, Item_Len);
  576. }
  577. #else
  578. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  579. if (p_Next_Arg == NULL)
  580. Item_Len = 6; // "(null)"
  581. else
  582. {
  583. Item_Len = lstrlenA(p_Next_Arg);
  584. Item_Len = max(1, Item_Len);
  585. }
  586. #endif
  587. break;
  588. }
  589. case 's'|s_Force_Ansi:
  590. case 'S'|s_Force_Ansi:
  591. {
  592. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  593. if (p_Next_Arg == NULL)
  594. Item_Len = 6; // "(null)"
  595. else
  596. {
  597. Item_Len = lstrlenA(p_Next_Arg);
  598. Item_Len = max(1, Item_Len);
  599. }
  600. break;
  601. }
  602. #ifndef _MAC
  603. case 's'|s_Force_Unicode:
  604. case 'S'|s_Force_Unicode:
  605. {
  606. LPWSTR pstrNextArg = va_arg(Arg_List, LPWSTR);
  607. if (pstrNextArg == NULL)
  608. Item_Len = 6; // "(null)"
  609. else
  610. {
  611. Item_Len = wcslen(pstrNextArg);
  612. Item_Len = max(1, Item_Len);
  613. }
  614. break;
  615. }
  616. #endif
  617. }
  618. // adjust nItemLen for strings
  619. if (Item_Len != 0)
  620. {
  621. Item_Len = max(Item_Len, Width);
  622. if (Precision != 0)
  623. {
  624. Item_Len = min(Item_Len, Precision);
  625. }
  626. }
  627. else
  628. {
  629. switch (*p_Tmp)
  630. {
  631. // integers
  632. case 'd':
  633. case 'i':
  634. case 'u':
  635. case 'x':
  636. case 'X':
  637. case 'o':
  638. va_arg(Arg_List, int);
  639. Item_Len = 32;
  640. Item_Len = max(Item_Len, Width + Precision);
  641. break;
  642. case 'e':
  643. case 'f':
  644. case 'g':
  645. case 'G':
  646. va_arg(Arg_List, double);
  647. Item_Len = 128;
  648. Item_Len = max(Item_Len, Width + Precision);
  649. break;
  650. case 'p':
  651. va_arg(Arg_List, void*);
  652. Item_Len = 32;
  653. Item_Len = max(Item_Len, Width + Precision);
  654. break;
  655. // no output
  656. case 'n':
  657. va_arg(Arg_List, int*);
  658. break;
  659. case 'I': // assume INT64 skip next two chars
  660. p_Tmp = KSInc(p_Tmp);
  661. p_Tmp = KSInc(p_Tmp);
  662. p_Tmp = KSInc(p_Tmp);
  663. Item_Len = 64;
  664. va_arg(Arg_List, __int64);
  665. break;
  666. default:
  667. gosASSERT(false); // unknown formatting option
  668. }
  669. }
  670. // adjust nMaxLen for output nItemLen
  671. Max_Len += Item_Len;
  672. }
  673. // make sure noone else is using this buffer
  674. ChecEBuffer();
  675. if ( Max_Len > m_pBuffer->m_Alloc_Length )
  676. {
  677. m_pBuffer->Release();
  678. Alloc( Max_Len + 1 );
  679. }
  680. #ifdef UNICODE
  681. vswprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
  682. #else
  683. vsprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
  684. #endif
  685. m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
  686. // clean up
  687. va_end( Arg_List );
  688. }
  689. /////////////////////////////////////////////////////////////////
  690. EWCharString operator+( const EWCharString& Begin_String,
  691. const EWCharString& End_String )
  692. {
  693. return Begin_String + End_String.m_pBuffer->Data();
  694. }
  695. /////////////////////////////////////////////////////////////////
  696. EWCharString operator+( const EWCSChar* p_Begin_String,
  697. const EWCharString& End_String )
  698. {
  699. EWCharString Ret_String;
  700. int Length = EWCharString::StrSize( p_Begin_String );
  701. Ret_String.Alloc( End_String.m_pBuffer->m_Data_Length + Length + 1 );
  702. memcpy( Ret_String.m_pBuffer->Data(), p_Begin_String, Length );
  703. memcpy( Ret_String.m_pBuffer->Data() + Length,
  704. End_String.m_pBuffer->Data(),
  705. End_String.m_pBuffer->m_Data_Length );
  706. Ret_String.m_pBuffer->m_Data_Length = Length + End_String.m_pBuffer->m_Data_Length;
  707. return Ret_String;
  708. }
  709. /////////////////////////////////////////////////////////////////
  710. EWCharString operator+( const EWCharString& Begin_String, const EWCSChar* p_End_String )
  711. {
  712. EWCharString Ret_String;
  713. int Length = EWCharString::StrSize( p_End_String );
  714. Ret_String.Alloc( Begin_String.m_pBuffer->m_Data_Length + Length + 1 );
  715. memcpy( Ret_String.m_pBuffer->Data(),
  716. Begin_String.m_pBuffer->Data(),
  717. Begin_String.m_pBuffer->m_Data_Length);
  718. memcpy( Ret_String.m_pBuffer->Data() + Begin_String.m_pBuffer->m_Data_Length,
  719. p_End_String, Length );
  720. Ret_String.m_pBuffer->m_Data_Length = Length + Begin_String.m_pBuffer->m_Data_Length;
  721. return Ret_String;
  722. }
  723. /////////////////////////////////////////////////////////////////
  724. EWCharString operator+( const EWCharString& Begin_String, EWCSChar Char )
  725. {
  726. EWCSChar Tmp[2];
  727. Tmp[0] = Char;
  728. Tmp[1] = 0;
  729. return Begin_String + Char;
  730. }
  731. /////////////////////////////////////////////////////////////////
  732. EWCharString operator+( const EWCSChar Char, const EWCharString& Begin_String )
  733. {
  734. EWCSChar Tmp[2];
  735. Tmp[0] = Char;
  736. Tmp[1] = 0;
  737. return Tmp + Begin_String;
  738. }
  739. /////////////////////////////////////////////////////////////////
  740. int EWCharString::Compare( const EWCharString& Str_To_Compare, bool Case_Sensitive ) const
  741. {
  742. return Compare( Str_To_Compare.m_pBuffer->Data(), Case_Sensitive );
  743. }
  744. /////////////////////////////////////////////////////////////////
  745. int EWCharString::Compare( const EWCSChar* p_String, bool Case_Sensitive ) const
  746. {
  747. int Length = StrSize( p_String );
  748. if ( 0 == StrSize(m_pBuffer->Data()) )
  749. {
  750. if ( Length )
  751. return -1;
  752. return 0;
  753. }
  754. if ( !Length )
  755. {
  756. return 1;
  757. }
  758. //if ( m_pBuffer->m_Data_Length != Length )
  759. //{
  760. // return ( m_pBuffer->m_Data_Length < Length ? -1 : 1 );
  761. //}
  762. if ( Case_Sensitive )
  763. {
  764. return ( memcmp( m_pBuffer->Data(), p_String, Length ) );
  765. }
  766. return (KStrCmp( m_pBuffer->Data(), p_String ) );
  767. }
  768. /////////////////////////////////////////////////////////////////
  769. int EWCharString::Size() const // number of bytes
  770. {
  771. return m_pBuffer->m_Data_Length * sizeof(EWCSChar);
  772. }
  773. /////////////////////////////////////////////////////////////////
  774. int EWCharString::Length() const // number of characters
  775. {
  776. #ifdef UNICODE
  777. return wcslen( m_pBuffer->Data() );
  778. #else
  779. return lstrlen( (char*)m_pBuffer->Data() );
  780. #endif
  781. }
  782. /////////////////////////////////////////////////////////////////
  783. int EWCharString::Find( EWCSChar Char, int Start_Index ) const
  784. {
  785. if ( Start_Index == -1 )
  786. {
  787. Start_Index = 0;
  788. }
  789. EWCSChar* p_Tmp = m_pBuffer->Data();
  790. // Bill added this line - this function ingored the start index
  791. p_Tmp += Start_Index;
  792. while( *p_Tmp )
  793. {
  794. if ( *p_Tmp == Char )
  795. {
  796. return p_Tmp - m_pBuffer->Data();
  797. }
  798. p_Tmp++;
  799. }
  800. return INVALID_INDEX;
  801. }
  802. /////////////////////////////////////////////////////////////////
  803. int EWCharString::Find( const EWCharString& Str_To_Find, int Start_Index ) const
  804. {
  805. if ( -1 == Start_Index )
  806. {
  807. Start_Index = 0;
  808. }
  809. EWCSChar* p_Tmp = KStrStr( m_pBuffer->Data() + Start_Index,
  810. Str_To_Find.m_pBuffer->Data() );
  811. return ( p_Tmp ? p_Tmp - m_pBuffer->Data() : INVALID_INDEX );
  812. }
  813. /////////////////////////////////////////////////////////////////
  814. int EWCharString::Find( const EWCSChar* p_Str_To_Find, int Start_Index ) const
  815. {
  816. if ( -1 == Start_Index )
  817. {
  818. Start_Index = 0;
  819. }
  820. EWCSChar* p_Tmp = KStrStr( m_pBuffer->Data() + Start_Index,
  821. p_Str_To_Find );
  822. return ( p_Tmp ? p_Tmp - m_pBuffer->Data() : INVALID_INDEX );
  823. }
  824. /////////////////////////////////////////////////////////////////
  825. int EWCharString::ReverseFind ( EWCSChar Char, int End_Index ) const
  826. {
  827. if ( -1 == End_Index )
  828. {
  829. End_Index = m_pBuffer->m_Data_Length;
  830. }
  831. EWCSChar* p_Tmp = m_pBuffer->Data() + End_Index;
  832. while( End_Index >= 0 )
  833. {
  834. if ( *p_Tmp == Char )
  835. {
  836. return End_Index;
  837. }
  838. p_Tmp --;
  839. End_Index --;
  840. }
  841. return INVALID_INDEX;
  842. }
  843. /////////////////////////////////////////////////////////////////
  844. #ifndef UNICODE
  845. int EWCharString::Find( unsigned short Char, int Start_Index ) const
  846. {
  847. unsigned short Tmp[2];
  848. *Tmp = Char;
  849. Tmp[2] = 0;
  850. return Find( (EWCSChar*)Tmp, Start_Index );
  851. }
  852. #endif // !K_UNICODE
  853. /////////////////////////////////////////////////////////////////
  854. EWCharString EWCharString::SubString( int Start_Index, int End_Index ) const
  855. {
  856. EWCharString Ret_String;
  857. // Bill changed so that it can return a single character
  858. // (Start == End)
  859. gosASSERT( Start_Index <= End_Index &&
  860. End_Index < m_pBuffer->m_Data_Length );
  861. Ret_String.Alloc( End_Index - Start_Index + 2);
  862. EWCSChar* p_Dest = Ret_String.m_pBuffer->Data();
  863. EWCSChar* p_Src = m_pBuffer->Data() + Start_Index;
  864. memcpy( p_Dest,
  865. p_Src,
  866. (End_Index - Start_Index + 1) * sizeof(EWCSChar) );
  867. *(p_Dest + End_Index - Start_Index + 1) = 0;
  868. Ret_String.m_pBuffer->m_Data_Length = End_Index - Start_Index + 1;
  869. return Ret_String;
  870. }
  871. /////////////////////////////////////////////////////////////////
  872. unsigned short* EWCharString::CreateUNICODE() const
  873. {
  874. #ifdef UNICODE
  875. unsigned short* p_Ret_String = new unsigned short[m_pBuffer->m_Data_Length + 1];
  876. memcpy( p_Ret_String, m_pBuffer->Data(), 2*(m_pBuffer->m_Data_Length + 1) );
  877. return p_Ret_String;
  878. #else
  879. unsigned short* p_Ret_String = new unsigned short[lstrlen((char*)m_pBuffer->Data()) + 1];
  880. ToUnicode( p_Ret_String, (unsigned char*)m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
  881. return p_Ret_String;
  882. #endif
  883. }
  884. /////////////////////////////////////////////////////////////////
  885. char* EWCharString::CreateMBCS() const
  886. {
  887. char* p_Ret_String = new char[m_pBuffer->m_Data_Length + 1];
  888. #ifdef K_UNICODE
  889. wcstombs( p_Ret_String, m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
  890. #else
  891. memcpy( p_Ret_String, m_pBuffer->Data(), m_pBuffer->m_Data_Length + 1 );
  892. #endif
  893. return p_Ret_String;
  894. }
  895. ///****************************************************************
  896. #ifdef K_UNICODE
  897. /////////////////////////////////////////////////////////////////
  898. EWCharString::EWCharString(const char* p_String )
  899. : m_pBuffer( EBuffer::s_p_Empty_Buffer )
  900. {
  901. if ( p_String )
  902. {
  903. Assign( A2W( p_String ) );
  904. }
  905. }
  906. /////////////////////////////////////////////////////////////////
  907. const EWCharString& EWCharString::operator+=( const char* p_String )
  908. {
  909. if ( p_String )
  910. {
  911. *this += A2W( p_String );
  912. }
  913. return *this;
  914. }
  915. /////////////////////////////////////////////////////////////////
  916. const EWCharString& EWCharString::operator+=( char Char )
  917. {
  918. char Tmp[2];
  919. Tmp[0] = Char;
  920. Tmp[1] = 0;
  921. *this += A2W( Tmp );
  922. return *this;
  923. }
  924. /////////////////////////////////////////////////////////////////
  925. EWCharString operator+( const EWCharString& Begin_String, char* p_End_String )
  926. {
  927. EWCharString RetString( Begin_String );
  928. if ( p_End_String )
  929. {
  930. RetString += A2W( p_End_String );
  931. }
  932. return RetString;
  933. }
  934. /////////////////////////////////////////////////////////////////
  935. EWCharString operator+( char* p_Begin_String, const EWCharString& End_String )
  936. {
  937. EWCharString RetString( A2W( p_Begin_String) + End_String );
  938. return RetString;
  939. }
  940. /////////////////////////////////////////////////////////////////
  941. EWCharString operator+( char Char, const EWCharString& End_String )
  942. {
  943. char Tmp[2];
  944. Tmp[0] = Char;
  945. Tmp[1] = 0;
  946. EWCharString RetString( A2W( Tmp ) + End_String );
  947. return RetString;
  948. }
  949. /////////////////////////////////////////////////////////////////
  950. bool EWCharString::operator<( const char* p_String ) const
  951. {
  952. return operator<(A2W( p_String ) );
  953. }
  954. /////////////////////////////////////////////////////////////////
  955. bool operator<( const char* p_String, const EWCharString& String )
  956. {
  957. return operator<(A2W(p_String), String );
  958. }
  959. /////////////////////////////////////////////////////////////////
  960. bool EWCharString::operator>( const char* p_String ) const
  961. {
  962. return EWCharString::operator>(A2W( p_String) );
  963. }
  964. /////////////////////////////////////////////////////////////////
  965. bool operator>( const char* p_String, const EWCharString& String )
  966. {
  967. return operator>( A2W(p_String), String );
  968. }
  969. /////////////////////////////////////////////////////////////////
  970. bool EWCharString::operator<=( const char* p_String) const
  971. {
  972. return EWCharString::operator<=( A2W(p_String) );
  973. }
  974. /////////////////////////////////////////////////////////////////
  975. bool operator<=( const char* p_String, const EWCharString& String)
  976. {
  977. return ( A2W( p_String ) <= String );
  978. }
  979. /////////////////////////////////////////////////////////////////
  980. bool EWCharString::operator>=( const char* p_String) const
  981. {
  982. return EWCharString::operator>=( A2W(p_String) );
  983. }
  984. /////////////////////////////////////////////////////////////////
  985. bool operator>=( const char* p_String, const EWCharString& String)
  986. {
  987. return ( A2W( p_String ) >= String );
  988. }
  989. /////////////////////////////////////////////////////////////////
  990. void EWCharString::Format( const char* p_Str, ... )
  991. {
  992. // NOTE, we are assuming that the end user has
  993. // made ALL STRING parameters UNICODE
  994. va_list Arg_List;
  995. va_start(Arg_List, p_Str);
  996. va_list Arg_List_Save = Arg_List;
  997. // make a guess at the maximum length of the resulting string
  998. int Max_Len = 0;
  999. for (const char* p_Tmp = p_Str; *p_Tmp != '\0'; p_Tmp = _tcsinc(p_Tmp))
  1000. {
  1001. // handle '%' character, but watch out for '%%'
  1002. if (*p_Tmp != '%' || *(p_Tmp = _tcsinc(p_Tmp)) == '%')
  1003. {
  1004. Max_Len += lstrlenA(p_Tmp);
  1005. continue;
  1006. }
  1007. int Item_Len = 0;
  1008. // handle '%' character with format
  1009. int Width = 0;
  1010. for (; *p_Tmp != '\0'; p_Tmp = _tcsinc(p_Tmp))
  1011. {
  1012. // check for valid flags
  1013. if (*p_Tmp == '#')
  1014. Max_Len += 2; // for '0x'
  1015. else if (*p_Tmp == '*')
  1016. Width = va_arg(Arg_List, int);
  1017. else if (*p_Tmp == '-' || *p_Tmp == '+' || *p_Tmp == '0' ||
  1018. *p_Tmp == ' ')
  1019. ;
  1020. else // hit non-flag character
  1021. break;
  1022. }
  1023. // get width and skip it
  1024. if ( Width == 0)
  1025. {
  1026. // width indicated by
  1027. Width = atoi(p_Tmp);
  1028. for (; *p_Tmp != '\0' && _istdigit(*p_Tmp); p_Tmp = _tcsinc(p_Tmp))
  1029. ;
  1030. }
  1031. gosASSERT( Width >= 0);
  1032. int Precision = 0;
  1033. if (*p_Tmp == '.')
  1034. {
  1035. // skip past '.' separator (width.precision)
  1036. p_Tmp = _tcsinc(p_Tmp);
  1037. // get precision and skip it
  1038. if (*p_Tmp == '*')
  1039. {
  1040. Precision = va_arg(Arg_List, int);
  1041. p_Tmp = _tcsinc(p_Tmp);
  1042. }
  1043. else
  1044. {
  1045. Precision = atoi(p_Tmp);
  1046. for (; *p_Tmp != '\0' && _istdigit(*p_Tmp); p_Tmp = _tcsinc(p_Tmp))
  1047. ;
  1048. }
  1049. gosASSERT( Precision >= 0);
  1050. }
  1051. // should be on type modifier or specifier
  1052. int Modifier = 0;
  1053. switch (*p_Tmp)
  1054. {
  1055. // modifiers that affect size
  1056. case 'h':
  1057. Modifier = s_Force_Ansi;
  1058. p_Tmp = _tcsinc(p_Tmp);
  1059. break;
  1060. case 'l':
  1061. Modifier = s_Force_Unicode;
  1062. p_Tmp = _tcsinc(p_Tmp);
  1063. break;
  1064. // modifiers that do not affect size
  1065. case 'F':
  1066. case 'N':
  1067. case 'L':
  1068. p_Tmp = _tcsinc(p_Tmp);
  1069. break;
  1070. }
  1071. // now should be on specifier
  1072. switch (*p_Tmp | Modifier)
  1073. {
  1074. // single characters
  1075. case 'c':
  1076. case 'C':
  1077. Item_Len = 2;
  1078. // here we are asuming regular char
  1079. va_arg(Arg_List, char);
  1080. break;
  1081. case 'c'|s_Force_Ansi:
  1082. case 'C'|s_Force_Ansi:
  1083. Item_Len = 2;
  1084. va_arg(Arg_List, char);
  1085. break;
  1086. case 'c'|s_Force_Unicode:
  1087. case 'C'|s_Force_Unicode:
  1088. Item_Len = 2;
  1089. va_arg(Arg_List, short);
  1090. break;
  1091. // strings
  1092. case 's':
  1093. {
  1094. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  1095. if (p_Next_Arg == NULL)
  1096. Item_Len = 6; // "(null)"
  1097. else
  1098. {
  1099. Item_Len = lstrlenA(p_Next_Arg);
  1100. Item_Len = max(1, Item_Len);
  1101. }
  1102. break;
  1103. }
  1104. case 'S':
  1105. {
  1106. #ifndef K_UNICODE
  1107. const unsigned short* p_Next_Arg = va_arg(Arg_List, const unsigned short*);
  1108. if (p_Next_Arg == NULL)
  1109. Item_Len = 6; // "(null)"
  1110. else
  1111. {
  1112. Item_Len = wcslen(p_Next_Arg);
  1113. Item_Len = max(1, Item_Len);
  1114. }
  1115. #else
  1116. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  1117. if (p_Next_Arg == NULL)
  1118. Item_Len = 6; // "(null)"
  1119. else
  1120. {
  1121. Item_Len = lstrlenA(p_Next_Arg);
  1122. Item_Len = max(1, Item_Len);
  1123. }
  1124. #endif
  1125. break;
  1126. }
  1127. case 's'|s_Force_Ansi:
  1128. case 'S'|s_Force_Ansi:
  1129. {
  1130. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  1131. if (p_Next_Arg == NULL)
  1132. Item_Len = 6; // "(null)"
  1133. else
  1134. {
  1135. Item_Len = lstrlenA(p_Next_Arg);
  1136. Item_Len = max(1, Item_Len);
  1137. }
  1138. break;
  1139. }
  1140. #ifndef _MAC
  1141. case 's'|s_Force_Unicode:
  1142. case 'S'|s_Force_Unicode:
  1143. {
  1144. LPWSTR pstrNextArg = va_arg(Arg_List, LPWSTR);
  1145. if (pstrNextArg == NULL)
  1146. Item_Len = 6; // "(null)"
  1147. else
  1148. {
  1149. Item_Len = wcslen(pstrNextArg);
  1150. Item_Len = max(1, Item_Len);
  1151. }
  1152. break;
  1153. }
  1154. #endif
  1155. }
  1156. // adjust nItemLen for strings
  1157. if (Item_Len != 0)
  1158. {
  1159. Item_Len = max(Item_Len, Width);
  1160. if (Precision != 0)
  1161. {
  1162. Item_Len = min(Item_Len, Precision);
  1163. }
  1164. }
  1165. else
  1166. {
  1167. switch (*p_Tmp)
  1168. {
  1169. // integers
  1170. case 'd':
  1171. case 'i':
  1172. case 'u':
  1173. case 'x':
  1174. case 'X':
  1175. case 'o':
  1176. va_arg(Arg_List, int);
  1177. Item_Len = 32;
  1178. Item_Len = max(Item_Len, Width + Precision);
  1179. break;
  1180. case 'e':
  1181. case 'f':
  1182. case 'g':
  1183. case 'G':
  1184. va_arg(Arg_List, double);
  1185. Item_Len = 128;
  1186. Item_Len = max(Item_Len, Width + Precision);
  1187. break;
  1188. case 'p':
  1189. va_arg(Arg_List, void*);
  1190. Item_Len = 32;
  1191. Item_Len = max(Item_Len, Width + Precision);
  1192. break;
  1193. // no output
  1194. case 'n':
  1195. va_arg(Arg_List, int*);
  1196. break;
  1197. case 'I': // assume INT64 skip next two chars
  1198. p_Tmp = _tcsinc(p_Tmp);
  1199. p_Tmp = _tcsinc(p_Tmp);
  1200. p_Tmp = _tcsinc(p_Tmp);
  1201. Item_Len = 64;
  1202. va_arg(Arg_List, __int64);
  1203. break;
  1204. default:
  1205. gosASSERT(false); // unknown formatting option
  1206. }
  1207. }
  1208. // adjust nMaxLen for output nItemLen
  1209. Max_Len += Item_Len;
  1210. }
  1211. // make sure noone else is using this buffer
  1212. ChecEBuffer();
  1213. if ( Max_Len > m_pBuffer->m_Alloc_Length )
  1214. {
  1215. m_pBuffer->Release();
  1216. Alloc( Max_Len + 1 );
  1217. }
  1218. char* pTmp = new char[ Max_Len + 1];
  1219. vsprintf(pTmp, p_Str, Arg_List_Save);
  1220. memcpy( m_pBuffer->Data(), A2W(pTmp), (Max_Len + 1)*sizeof(EWCSChar) );
  1221. m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
  1222. // clean up
  1223. va_end( Arg_List );
  1224. }
  1225. /////////////////////////////////////////////////////////////////
  1226. bool EWCharString::operator==( const char* p_String )
  1227. {
  1228. return operator==( A2W( p_String ) );
  1229. }
  1230. /////////////////////////////////////////////////////////////////
  1231. bool operator==( const char* p_String, const EWCharString& String)
  1232. {
  1233. return operator==( A2W( p_String ), String );
  1234. }
  1235. /////////////////////////////////////////////////////////////////
  1236. bool EWCharString::operator!=( const char* p_String) const
  1237. {
  1238. return operator!=( A2W(p_String) );
  1239. }
  1240. /////////////////////////////////////////////////////////////////
  1241. bool operator!=( const char* p_String, const EWCharString& String )
  1242. {
  1243. return operator!=( A2W(p_String), String );
  1244. }
  1245. /////////////////////////////////////////////////////////////////
  1246. int EWCharString::Find( char Char, int Start_Index ) const
  1247. {
  1248. EWCSChar Tmp;
  1249. mbtowc( &Tmp, &Char, 1 );
  1250. return Find( Tmp, Start_Index );
  1251. }
  1252. /////////////////////////////////////////////////////////////////
  1253. const EWCharString& EWCharString::operator=( char Char )
  1254. {
  1255. EWCSChar Tmp;
  1256. mbtowc( &Tmp, &Char, 1 );
  1257. return operator=( Tmp );
  1258. }
  1259. #endif // Unicode
  1260. //***************************************************************
  1261. /* restore UNICODE, K_UNICODE and MBCS to their previous state */
  1262. #ifndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1263. #undef UNICODE
  1264. #else
  1265. #undef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1266. #endif /* ndef _UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
  1267. #ifndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1268. #undef K_UNICODE
  1269. #else
  1270. #undef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1271. #endif /* ndef _K_UNICODE_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
  1272. #ifdef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1273. #undef _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP
  1274. #define MBCS _PREVIOUS_MBCS___EWCharString_CPP
  1275. #undef _PREVIOUS_MBCS___EWCharString_CPP
  1276. #endif /* def _MBCS_WAS_PREVIOUSLY_DEFINED___EWCharString_CPP */
  1277. //***************************************************************
  1278. //****************************************************************
  1279. #pragma warning( pop )