EString.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575
  1. #define EString_CPP
  2. //===========================================================================//
  3. // Copyright (C) Microsoft Corporation. All rights reserved. //
  4. //===========================================================================//
  5. #include <windows.h>
  6. #include "EString.h"
  7. #include <gameos.hpp>
  8. #include <stdio.h>
  9. #ifdef UNICODE
  10. #define K_UNICODE
  11. #include <malloc.h>
  12. #include <tchar.h>
  13. #endif
  14. #pragma warning( disable:4505 )
  15. #pragma warning( push )
  16. #pragma warning( disable:4100 )
  17. #define INT_SIZE_LENGTH 20
  18. extern int __ismbcodepage;
  19. #define _ISNOTMBCP (__ismbcodepage == 0)
  20. static wchar_t * __cdecl wideRev (
  21. wchar_t * string
  22. )
  23. {
  24. wchar_t *start = string;
  25. wchar_t *left = string;
  26. wchar_t ch;
  27. while (*string++) /* find end of string */
  28. ;
  29. string -= 2;
  30. while (left < string)
  31. {
  32. ch = *left;
  33. *left++ = *string;
  34. *string-- = ch;
  35. }
  36. return(start);
  37. }
  38. static wchar_t * __cdecl wideStrStr (
  39. const wchar_t * wcs1,
  40. const wchar_t * wcs2
  41. )
  42. {
  43. wchar_t *cp = (wchar_t *) wcs1;
  44. wchar_t *s1, *s2;
  45. while (*cp)
  46. {
  47. s1 = cp;
  48. s2 = (wchar_t *) wcs2;
  49. while ( *s1 && *s2 && !(*s1-*s2) )
  50. s1++, s2++;
  51. if (!*s2)
  52. return(cp);
  53. cp++;
  54. }
  55. return(NULL);
  56. }
  57. static int __cdecl wideToInt(
  58. const wchar_t *nptr
  59. )
  60. {
  61. char astring[20];
  62. WideCharToMultiByte (CP_ACP, 0, nptr, -1,
  63. astring, INT_SIZE_LENGTH, NULL, NULL);
  64. return ((int)atol(astring));
  65. }
  66. static long __cdecl atolong(
  67. const char *nptr
  68. )
  69. {
  70. int c; /* current char */
  71. long total; /* current total */
  72. int sign; /* if '-', then negative, otherwise positive */
  73. /* skip whitespace */
  74. while ( isspace((int)(unsigned char)*nptr) )
  75. ++nptr;
  76. c = (int)(unsigned char)*nptr++;
  77. sign = c; /* save sign indication */
  78. if (c == '-' || c == '+')
  79. c = (int)(unsigned char)*nptr++; /* skip sign */
  80. total = 0;
  81. while (isdigit(c)) {
  82. total = 10 * total + (c - '0'); /* accumulate digit */
  83. c = (int)(unsigned char)*nptr++; /* get next char */
  84. }
  85. if (sign == '-')
  86. return -total;
  87. else
  88. return total; /* return result, negated if necessary */
  89. }
  90. static char * __cdecl StrStr (
  91. const char * str1,
  92. const char * str2
  93. )
  94. {
  95. char *cp = (char *) str1;
  96. char *s1, *s2;
  97. if ( !*str2 )
  98. return((char *)str1);
  99. while (*cp)
  100. {
  101. s1 = cp;
  102. s2 = (char *) str2;
  103. while ( *s1 && *s2 && !(*s1-*s2) )
  104. s1++, s2++;
  105. if (!*s2)
  106. return(cp);
  107. cp++;
  108. }
  109. return(NULL);
  110. }
  111. static char * __cdecl StrRev (
  112. char * string
  113. )
  114. {
  115. char *start = string;
  116. char *left = string;
  117. char ch;
  118. while (*string++) /* find end of string */
  119. ;
  120. string -= 2;
  121. while (left < string)
  122. {
  123. ch = *left;
  124. *left++ = *string;
  125. *string-- = ch;
  126. }
  127. return(start);
  128. }
  129. //***************************************************************
  130. #ifdef UNICODE
  131. #define KToUpper CharUpper
  132. #define KToLower CharLower
  133. #define KReverse wideRev
  134. #define KStrCmp lstrcmpi
  135. #define klstrlen lstrlen
  136. #define KStrStr wideStrStr
  137. inline const EChar* KSInc(const EChar* p) { return p+1; }
  138. inline size_t ECharLen( const EChar* p ) {return 2;}
  139. #define KToI wideToInt
  140. #else
  141. #define KToI atolong
  142. #define KStrCmp lstrcmpi
  143. #define klstrlen lstrlen
  144. #define KToUpper CharUpper
  145. #define KToLower CharLower
  146. #ifdef MBCS
  147. #define KReverse mbrev
  148. #define KStrStr _mbsstr
  149. #define KSInc _mbsinc
  150. #define ECharLen _mbclen
  151. #else // single byte
  152. #define KReverse StrRev
  153. #define KStrStr StrStr
  154. __inline char * __cdecl KSInc(const char * _pc) { return (char *)(_pc+1); }
  155. inline int ECharLen(const char* x){ return 1; }
  156. #endif
  157. #endif
  158. const int EString::INVALID_INDEX = -1;
  159. const int EString::s_Alloc_Allign = 4;
  160. const int EString::s_Force_Ansi = 0x10000;
  161. const int EString::s_Force_Unicode = 0x20000;
  162. // keep around an empty buffer which all of our empty objects use
  163. EString::EBuffer EString::EBuffer::s_Empty_Buffer = { 0, 0, 0 };
  164. EString::EBuffer* EString::EBuffer::s_p_Empty_Buffer = &EString::EBuffer::s_Empty_Buffer;
  165. // this must be a macro because the debug versions won't expand
  166. // inlines
  167. #define A2W(p_String) (\
  168. ((const char*)p_String == NULL) ? NULL : (\
  169. EString::ToUnicode( (LPWSTR)_alloca((lstrlenA(p_String)+1)*2),\
  170. (const unsigned char*)p_String, (lstrlenA(p_String)+1)*2)))
  171. // if this doesn't want to link properly, this will have to become
  172. // a macro.
  173. /////////////////////////////////////////////////////////////////
  174. inline unsigned short* EString::ToUnicode( unsigned short* p_Buffer,
  175. const unsigned char* p_Str,
  176. int Num_Chars )
  177. {
  178. gosASSERT( p_Buffer );
  179. gosASSERT( p_Str );
  180. p_Buffer[0] = 0;
  181. MultiByteToWideChar( CP_ACP, 0, (const char*)p_Str, -1, p_Buffer, Num_Chars );
  182. return p_Buffer;
  183. }
  184. /////////////////////////////////////////////////////////////////
  185. inline int EString::StrSize( const EChar* p_Str )
  186. {
  187. return ( p_Str == NULL ? 0 :
  188. #ifdef UNICODE
  189. wcslen( p_Str )
  190. #else
  191. lstrlen( (const char*)p_Str )
  192. #endif
  193. );
  194. }
  195. /////////////////////////////////////////////////////////////////
  196. void EString::ChecEBufferDoRealloc()
  197. {
  198. if ( m_pBuffer->m_Ref_Count > 0 )
  199. {
  200. m_pBuffer->m_Ref_Count --;
  201. int Cur_Length = m_pBuffer->m_Data_Length;
  202. EChar* p_Data = m_pBuffer->Data();
  203. Alloc( Cur_Length );
  204. memcpy( m_pBuffer + 1, p_Data, Cur_Length * sizeof( EChar ) );
  205. m_pBuffer->m_Data_Length = Cur_Length;
  206. }
  207. }
  208. //***************************************************************
  209. //==============================================================
  210. // Constructors/Destructors
  211. //==============================================================
  212. ///////////////////////////////////////////////////////////////
  213. EString::EString( const EChar* p_String )
  214. : m_pBuffer( EBuffer::s_p_Empty_Buffer )
  215. {
  216. if ( p_String != NULL )
  217. {
  218. Assign( p_String );
  219. }
  220. }
  221. ///////////////////////////////////////////////////////////////
  222. EString::EString( const EString& Src_String )
  223. : m_pBuffer( Src_String.m_pBuffer )
  224. {
  225. m_pBuffer->m_Ref_Count++;
  226. }
  227. ///////////////////////////////////////////////////////////////
  228. EString::EString() : m_pBuffer( EBuffer::s_p_Empty_Buffer )
  229. {
  230. }
  231. ///////////////////////////////////////////////////////////////
  232. EString::EString( const EChar Char )
  233. {
  234. Alloc( 2 );
  235. *(m_pBuffer->Data()) = Char;
  236. *(m_pBuffer->Data() + 1) = 0;
  237. m_pBuffer->m_Data_Length = 1;
  238. }
  239. ///////////////////////////////////////////////////////////////
  240. EString::~EString()
  241. {
  242. m_pBuffer->Release();
  243. }
  244. ///////////////////////////////////////////////////////////////
  245. void EString::Assign( const EChar* p_String )
  246. {
  247. // handle NULL case
  248. if ( !p_String )
  249. {
  250. m_pBuffer->Release();
  251. m_pBuffer = EBuffer::s_p_Empty_Buffer;
  252. }
  253. int Len = StrSize( p_String ) + 1;
  254. // buffer big enough, we can recycle
  255. if ( m_pBuffer->m_Alloc_Length >= Len )
  256. {
  257. memcpy( m_pBuffer + 1, p_String, Len * sizeof( EChar ) );
  258. m_pBuffer->m_Data_Length = Len - 1;
  259. }
  260. else if ( p_String ) // need to allocate new buffer
  261. {
  262. m_pBuffer->Release();
  263. Alloc( Len );
  264. memcpy( m_pBuffer->Data(), p_String, Len * sizeof( EChar ) );
  265. m_pBuffer->m_Data_Length = Len - 1;
  266. }
  267. }
  268. ///////////////////////////////////////////////////////////////
  269. void EString::Alloc( int Min_Amount )
  270. {
  271. // we're rouding up to the nearest multiple of 4 for now
  272. Min_Amount = (Min_Amount/s_Alloc_Allign + 1) * s_Alloc_Allign;
  273. m_pBuffer = (EString::EBuffer*)malloc(sizeof(EBuffer) +
  274. (Min_Amount)*sizeof(EChar));
  275. memset( m_pBuffer, 0, sizeof(EBuffer) + (Min_Amount)*sizeof(EChar) );
  276. m_pBuffer->m_Alloc_Length = Min_Amount;
  277. }
  278. void EString::SetBufferSize( int size )
  279. {
  280. EBuffer* p_Old_Buffer = m_pBuffer;
  281. Alloc( size );
  282. p_Old_Buffer->Release();
  283. }
  284. ///////////////////////////////////////////////////////////////
  285. void EString::Replace( int Start_Index, const EChar* p_String )
  286. {
  287. // keep the buffer
  288. EBuffer* p_Tmp = m_pBuffer;
  289. int Cur_Len = m_pBuffer->m_Data_Length;
  290. // unshare any shared buffers
  291. ChecEBuffer();
  292. gosASSERT( Start_Index <= Cur_Len );
  293. // check the current buffer, not the current
  294. // length
  295. if ( Start_Index <= Cur_Len )
  296. {
  297. int Length = StrSize( p_String );
  298. int Alloc_Length = Start_Index + Length + 1;
  299. if ( Alloc_Length <= m_pBuffer->m_Alloc_Length )
  300. {
  301. memcpy( m_pBuffer->Data() + Start_Index,
  302. p_String, Length * sizeof( EChar ) );
  303. // Add on the NULL if necessary
  304. if ( Start_Index + Length > Cur_Len )
  305. {
  306. *(m_pBuffer->Data() + Start_Index + Length + 1 ) = NULL;
  307. m_pBuffer->m_Data_Length = Length + Start_Index;
  308. }
  309. }
  310. else // need to reallocate here
  311. {
  312. EBuffer* p_Old_Buffer = m_pBuffer;
  313. m_pBuffer = EBuffer::s_p_Empty_Buffer;
  314. if ( Cur_Len > Alloc_Length )
  315. {
  316. Alloc_Length = Cur_Len;
  317. }
  318. Alloc( Alloc_Length );
  319. memcpy( m_pBuffer->Data(),
  320. p_Tmp->Data(),
  321. (Cur_Len + 1)*sizeof(EChar) );
  322. memcpy( m_pBuffer->Data() + Start_Index,
  323. p_String, Length*sizeof(EChar) );
  324. m_pBuffer->m_Data_Length = Alloc_Length;
  325. p_Old_Buffer->Release();
  326. }
  327. // check to see if the p_String is null
  328. if ( p_String == NULL )
  329. {
  330. *(m_pBuffer->Data() + Start_Index) = 0;
  331. }
  332. }
  333. }
  334. ///////////////////////////////////////////////////////////////
  335. void EString::Replace( int Start_Index, const EString& String )
  336. {
  337. Replace( Start_Index, String.m_pBuffer->Data() );
  338. }
  339. ///////////////////////////////////////////////////////////////
  340. void EString::Insert( int Start_Index, const EChar* p_String )
  341. {
  342. if ( Start_Index != INVALID_INDEX && Start_Index <= StrSize( Data() ) )
  343. {
  344. EBuffer* p_Tmp = m_pBuffer;
  345. EBuffer* p_Old_Buffer = NULL;
  346. ChecEBuffer();
  347. int Length = StrSize( p_String );
  348. // add on 2 for the 'nulls'
  349. if ( Length + p_Tmp->m_Data_Length + 1 > m_pBuffer->m_Alloc_Length )
  350. {
  351. p_Old_Buffer = m_pBuffer;
  352. Alloc( Length + p_Tmp->m_Data_Length + 1 );
  353. }
  354. // use memmove in case we are recycling a buffer.
  355. memmove( m_pBuffer->Data(), p_Tmp->Data(), Start_Index * sizeof ( EChar ) );
  356. memmove( m_pBuffer->Data() + (Start_Index + Length), p_Tmp->Data() + (Start_Index),
  357. (p_Tmp->m_Data_Length - Start_Index) * sizeof (EChar) );
  358. // write the string last in case we are writing over an old buffer
  359. memcpy( m_pBuffer->Data() + Start_Index, p_String, Length * sizeof( EChar ) );
  360. m_pBuffer->m_Data_Length = Length + p_Tmp->m_Data_Length;
  361. // Bill added - in some cases, removing some characters then inserting fewer
  362. // was leaving garbage at the end of the string.
  363. // i.e., the trailing NULL was not being moved.
  364. (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
  365. // free the old buffer -- can't do this earlier, because we
  366. // need to copy out of it
  367. if ( p_Old_Buffer )
  368. {
  369. p_Old_Buffer->Release();
  370. }
  371. }
  372. }
  373. ///////////////////////////////////////////////////////////////
  374. bool EString::Remove( int Start_Index, int End_Index )
  375. {
  376. // Bill changed - this function could not handle removing a single character
  377. // - also this didn't remove the character pointed to by End_Index
  378. if( Start_Index <= End_Index && End_Index < m_pBuffer->m_Data_Length)
  379. {
  380. ChecEBufferDoRealloc();
  381. memmove( m_pBuffer->Data() + Start_Index, m_pBuffer->Data() + End_Index + 1,
  382. (StrSize(m_pBuffer->Data()) - End_Index - 1)*sizeof(EChar) );
  383. m_pBuffer->m_Data_Length -= (End_Index - Start_Index + 1);
  384. // Bill added - in some cases, removing some characters then inserting fewer
  385. // was leaving garbage at the end of the string.
  386. // i.e., the trailing NULL was not being moved.
  387. (*(m_pBuffer->Data() + m_pBuffer->m_Data_Length)) = 0;
  388. return true;
  389. }
  390. return false;
  391. }
  392. /////////////////////////////////////////////////////////////////
  393. bool EString::Remove( EString& Sub_String )
  394. {
  395. int Index = Find( Sub_String );
  396. if ( Index != -1 )
  397. {
  398. return Remove( Index, Index + Sub_String.StrSize( Sub_String.Data() ) - 1 );
  399. }
  400. return false;
  401. }
  402. ///////////////////////////////////////////////////////////////
  403. void EString::Swap( EString& Src )
  404. {
  405. EBuffer* p_Tmp = Src.m_pBuffer;
  406. Src.m_pBuffer = m_pBuffer;
  407. m_pBuffer = p_Tmp;
  408. }
  409. ///////////////////////////////////////////////////////////////
  410. void EString::MakeUpper()
  411. {
  412. ChecEBufferDoRealloc();
  413. KToUpper( m_pBuffer->Data() );
  414. }
  415. ///////////////////////////////////////////////////////////////
  416. void EString::MakeLower()
  417. {
  418. ChecEBufferDoRealloc();
  419. KToLower( m_pBuffer->Data() );
  420. }
  421. ///////////////////////////////////////////////////////////////
  422. void EString::Reverse()
  423. {
  424. ChecEBufferDoRealloc();
  425. KReverse( m_pBuffer->Data() );
  426. }
  427. // works like sprintf
  428. ///////////////////////////////////////////////////////////////
  429. void EString::Format( const EChar* p_Str, ... )
  430. {
  431. va_list Arg_List;
  432. va_start(Arg_List, p_Str);
  433. va_list Arg_List_Save = Arg_List;
  434. // make a guess at the maximum length of the resulting string
  435. int Max_Len = 0;
  436. for (const EChar* p_Tmp = p_Str; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
  437. {
  438. // handle '%' character, but watch out for '%%'
  439. if (*p_Tmp != '%' || *(p_Tmp = KSInc(p_Tmp)) == '%')
  440. {
  441. Max_Len += ECharLen(p_Tmp);
  442. continue;
  443. }
  444. int Item_Len = 0;
  445. // handle '%' character with format
  446. int Width = 0;
  447. for (; *p_Tmp != '\0'; p_Tmp = KSInc(p_Tmp))
  448. {
  449. // check for valid flags
  450. if (*p_Tmp == '#')
  451. Max_Len += 2; // for '0x'
  452. else if (*p_Tmp == '*')
  453. Width = va_arg(Arg_List, int);
  454. else if (*p_Tmp == '-' || *p_Tmp == '+' || *p_Tmp == '0' ||
  455. *p_Tmp == ' ')
  456. ;
  457. else // hit non-flag character
  458. break;
  459. }
  460. // get width and skip it
  461. if ( Width == 0)
  462. {
  463. // width indicated by
  464. Width = KToI(p_Tmp);
  465. unsigned short buffer;
  466. for (; *p_Tmp != '\0'; )
  467. {
  468. GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
  469. if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
  470. p_Tmp = KSInc(p_Tmp);
  471. else
  472. break;
  473. }
  474. }
  475. gosASSERT( Width >= 0);
  476. int Precision = 0;
  477. if (*p_Tmp == '.')
  478. {
  479. // skip past '.' separator (width.precision)
  480. p_Tmp = KSInc(p_Tmp);
  481. // get precision and skip it
  482. if (*p_Tmp == '*')
  483. {
  484. Precision = va_arg(Arg_List, int);
  485. p_Tmp = KSInc(p_Tmp);
  486. }
  487. else
  488. {
  489. Precision = KToI(p_Tmp);
  490. for (; *p_Tmp != '\0'; )
  491. {
  492. unsigned short buffer;
  493. GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, p_Tmp, 1, &buffer);
  494. //if (buffer == C1_DIGIT || buffer == C1_XDIGIT)
  495. if (buffer & C1_DIGIT) //mh
  496. p_Tmp = KSInc(p_Tmp);
  497. else
  498. break;
  499. }
  500. }
  501. gosASSERT( Precision >= 0);
  502. }
  503. // should be on type modifier or specifier
  504. int Modifier = 0;
  505. switch (*p_Tmp)
  506. {
  507. // modifiers that affect size
  508. case 'h':
  509. Modifier = s_Force_Ansi;
  510. p_Tmp = KSInc(p_Tmp);
  511. break;
  512. case 'l':
  513. Modifier = s_Force_Unicode;
  514. p_Tmp = KSInc(p_Tmp);
  515. break;
  516. // modifiers that do not affect size
  517. case 'F':
  518. case 'N':
  519. case 'L':
  520. p_Tmp = KSInc(p_Tmp);
  521. break;
  522. }
  523. // now should be on specifier
  524. switch (*p_Tmp | Modifier)
  525. {
  526. // single characters
  527. case 'c':
  528. case 'C':
  529. Item_Len = 2;
  530. va_arg(Arg_List, EChar);
  531. break;
  532. case 'c'|s_Force_Ansi:
  533. case 'C'|s_Force_Ansi:
  534. Item_Len = 2;
  535. va_arg(Arg_List, char);
  536. break;
  537. case 'c'|s_Force_Unicode:
  538. case 'C'|s_Force_Unicode:
  539. Item_Len = 2;
  540. va_arg(Arg_List, short);
  541. break;
  542. // strings
  543. case 's':
  544. {
  545. const EChar* p_Next_Arg = va_arg(Arg_List, const EChar*);
  546. if (p_Next_Arg == NULL)
  547. Item_Len = 6; // "(null)"
  548. else
  549. {
  550. Item_Len = StrSize(p_Next_Arg);
  551. Item_Len = max(1, Item_Len);
  552. }
  553. break;
  554. }
  555. case 'S':
  556. {
  557. #ifndef K_UNICODE
  558. const unsigned short* p_Next_Arg = va_arg(Arg_List, const unsigned short*);
  559. if (p_Next_Arg == NULL)
  560. Item_Len = 6; // "(null)"
  561. else
  562. {
  563. Item_Len = wcslen(p_Next_Arg);
  564. Item_Len = max(1, Item_Len);
  565. }
  566. #else
  567. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  568. if (p_Next_Arg == NULL)
  569. Item_Len = 6; // "(null)"
  570. else
  571. {
  572. Item_Len = lstrlenA(p_Next_Arg);
  573. Item_Len = max(1, Item_Len);
  574. }
  575. #endif
  576. break;
  577. }
  578. case 's'|s_Force_Ansi:
  579. case 'S'|s_Force_Ansi:
  580. {
  581. const char* p_Next_Arg = va_arg(Arg_List, const char*);
  582. if (p_Next_Arg == NULL)
  583. Item_Len = 6; // "(null)"
  584. else
  585. {
  586. Item_Len = lstrlenA(p_Next_Arg);
  587. Item_Len = max(1, Item_Len);
  588. }
  589. break;
  590. }
  591. #ifndef _MAC
  592. case 's'|s_Force_Unicode:
  593. case 'S'|s_Force_Unicode:
  594. {
  595. LPWSTR pstrNextArg = va_arg(Arg_List, LPWSTR);
  596. if (pstrNextArg == NULL)
  597. Item_Len = 6; // "(null)"
  598. else
  599. {
  600. Item_Len = wcslen(pstrNextArg);
  601. Item_Len = max(1, Item_Len);
  602. }
  603. break;
  604. }
  605. #endif
  606. }
  607. // adjust nItemLen for strings
  608. if (Item_Len != 0)
  609. {
  610. Item_Len = max(Item_Len, Width);
  611. if (Precision != 0)
  612. {
  613. Item_Len = min(Item_Len, Precision);
  614. }
  615. }
  616. else
  617. {
  618. switch (*p_Tmp)
  619. {
  620. // integers
  621. case 'd':
  622. case 'i':
  623. case 'u':
  624. case 'x':
  625. case 'X':
  626. case 'o':
  627. va_arg(Arg_List, int);
  628. Item_Len = 32;
  629. Item_Len = max(Item_Len, Width + Precision);
  630. break;
  631. case 'e':
  632. case 'f':
  633. case 'g':
  634. case 'G':
  635. va_arg(Arg_List, double);
  636. Item_Len = 128;
  637. Item_Len = max(Item_Len, Width + Precision);
  638. break;
  639. case 'p':
  640. va_arg(Arg_List, void*);
  641. Item_Len = 32;
  642. Item_Len = max(Item_Len, Width + Precision);
  643. break;
  644. // no output
  645. case 'n':
  646. va_arg(Arg_List, int*);
  647. break;
  648. case 'I': // assume INT64 skip next two chars
  649. p_Tmp = KSInc(p_Tmp);
  650. p_Tmp = KSInc(p_Tmp);
  651. p_Tmp = KSInc(p_Tmp);
  652. Item_Len = 64;
  653. va_arg(Arg_List, __int64);
  654. break;
  655. default:
  656. gosASSERT(false); // unknown formatting option
  657. }
  658. }
  659. // adjust nMaxLen for output nItemLen
  660. Max_Len += Item_Len;
  661. }
  662. // make sure noone else is using this buffer
  663. ChecEBuffer();
  664. if ( Max_Len > m_pBuffer->m_Alloc_Length )
  665. {
  666. m_pBuffer->Release();
  667. Alloc( Max_Len + 1 );
  668. }
  669. #ifdef UNICODE
  670. vswprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
  671. #else
  672. vsprintf(m_pBuffer->Data(), p_Str, Arg_List_Save);
  673. #endif
  674. m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
  675. // clean up
  676. va_end( Arg_List );
  677. }
  678. /////////////////////////////////////////////////////////////////
  679. EString operator+( const EString& Begin_String,
  680. const EString& End_String )
  681. {
  682. return Begin_String + (const EChar*)(End_String.m_pBuffer->Data());
  683. }
  684. /////////////////////////////////////////////////////////////////
  685. EString operator+( const EChar* p_Begin_String,
  686. const EString& End_String )
  687. {
  688. EString Ret_String;
  689. int Length = EString::StrSize( p_Begin_String );
  690. Ret_String.Alloc( End_String.m_pBuffer->m_Data_Length + Length + 1 );
  691. memcpy( Ret_String.m_pBuffer->Data(), p_Begin_String, Length );
  692. memcpy( Ret_String.m_pBuffer->Data() + Length,
  693. End_String.m_pBuffer->Data(),
  694. End_String.m_pBuffer->m_Data_Length );
  695. Ret_String.m_pBuffer->m_Data_Length = Length + End_String.m_pBuffer->m_Data_Length;
  696. return Ret_String;
  697. }
  698. /////////////////////////////////////////////////////////////////
  699. EString operator+( const EString& Begin_String, const EChar* p_End_String )
  700. {
  701. EString Ret_String;
  702. int Length = EString::StrSize( p_End_String );
  703. Ret_String.Alloc( Begin_String.m_pBuffer->m_Data_Length + Length + 1 );
  704. memcpy( Ret_String.m_pBuffer->Data(),
  705. Begin_String.m_pBuffer->Data(),
  706. Begin_String.m_pBuffer->m_Data_Length);
  707. memcpy( Ret_String.m_pBuffer->Data() + Begin_String.m_pBuffer->m_Data_Length,
  708. p_End_String, Length );
  709. Ret_String.m_pBuffer->m_Data_Length = Length + Begin_String.m_pBuffer->m_Data_Length;
  710. return Ret_String;
  711. }
  712. /////////////////////////////////////////////////////////////////
  713. EString operator+( const EString& Begin_String, EChar Char )
  714. {
  715. EChar Tmp[2];
  716. Tmp[0] = Char;
  717. Tmp[1] = 0;
  718. return Begin_String + Char;
  719. }
  720. /////////////////////////////////////////////////////////////////
  721. EString operator+( const EChar Char, const EString& Begin_String )
  722. {
  723. EChar Tmp[2];
  724. Tmp[0] = Char;
  725. Tmp[1] = 0;
  726. return Tmp + Begin_String;
  727. }
  728. /////////////////////////////////////////////////////////////////
  729. int EString::Compare( const EString& Str_To_Compare, bool Case_Sensitive ) const
  730. {
  731. return Compare( Str_To_Compare.m_pBuffer->Data(), Case_Sensitive );
  732. }
  733. /////////////////////////////////////////////////////////////////
  734. int EString::Compare( const EChar* p_String, bool Case_Sensitive ) const
  735. {
  736. int Length = StrSize( p_String );
  737. int myLength = StrSize(m_pBuffer->Data());
  738. if ( 0 == myLength )
  739. {
  740. if ( Length )
  741. return -1;
  742. return 0;
  743. }
  744. if ( !Length )
  745. {
  746. return 1;
  747. }
  748. //if ( m_pBuffer->m_Data_Length != Length )
  749. //{
  750. // return ( m_pBuffer->m_Data_Length < Length ? -1 : 1 );
  751. //}
  752. if ( Case_Sensitive )
  753. {
  754. if ( 0 == memcmp( m_pBuffer->Data(), p_String, Length ) )
  755. {
  756. if ( Length == myLength )
  757. return 0;
  758. else if ( myLength > Length )
  759. return 1;
  760. else
  761. return -1;
  762. }
  763. }
  764. return (KStrCmp( m_pBuffer->Data(), p_String ) );
  765. }
  766. /////////////////////////////////////////////////////////////////
  767. int EString::Size() const // number of bytes
  768. {
  769. return m_pBuffer->m_Data_Length * sizeof(EChar);
  770. }
  771. /////////////////////////////////////////////////////////////////
  772. int EString::Length() const // number of characters
  773. {
  774. if ( !m_pBuffer->Data() )
  775. return 0;
  776. #ifdef UNICODE
  777. return wcslen( m_pBuffer->Data() );
  778. #else
  779. return lstrlen( (char*)m_pBuffer->Data() );
  780. #endif
  781. }
  782. /////////////////////////////////////////////////////////////////
  783. int EString::Find( EChar Char, int Start_Index ) const
  784. {
  785. if ( Start_Index == -1 )
  786. {
  787. Start_Index = 0;
  788. }
  789. EChar* 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 EString::Find( const EString& Str_To_Find, int Start_Index ) const
  804. {
  805. if ( -1 == Start_Index )
  806. {
  807. Start_Index = 0;
  808. }
  809. EChar* 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 EString::Find( const EChar* p_Str_To_Find, int Start_Index ) const
  815. {
  816. if ( -1 == Start_Index )
  817. {
  818. Start_Index = 0;
  819. }
  820. EChar* 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 EString::ReverseFind ( EChar Char, int End_Index ) const
  826. {
  827. if ( -1 == End_Index )
  828. {
  829. End_Index = m_pBuffer->m_Data_Length;
  830. }
  831. EChar* 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 EString::Find( unsigned short Char, int Start_Index ) const
  846. {
  847. unsigned short Tmp[2];
  848. *Tmp = Char;
  849. Tmp[2] = 0;
  850. return Find( (EChar*)Tmp, Start_Index );
  851. }
  852. #endif // !K_UNICODE
  853. /////////////////////////////////////////////////////////////////
  854. EString EString::SubString( int Start_Index, int End_Index ) const
  855. {
  856. EString 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. EChar* p_Dest = Ret_String.m_pBuffer->Data();
  863. EChar* p_Src = m_pBuffer->Data() + Start_Index;
  864. memcpy( p_Dest,
  865. p_Src,
  866. (End_Index - Start_Index + 1) * sizeof(EChar) );
  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* EString::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* EString::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. EString::EString(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 EString& EString::operator+=( const char* p_String )
  908. {
  909. if ( p_String )
  910. {
  911. *this += A2W( p_String );
  912. }
  913. return *this;
  914. }
  915. /////////////////////////////////////////////////////////////////
  916. const EString& EString::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. EString operator+( const EString& Begin_String, char* p_End_String )
  926. {
  927. EString RetString( Begin_String );
  928. if ( p_End_String )
  929. {
  930. RetString += A2W( p_End_String );
  931. }
  932. return RetString;
  933. }
  934. /////////////////////////////////////////////////////////////////
  935. EString operator+( char* p_Begin_String, const EString& End_String )
  936. {
  937. EString RetString( A2W( p_Begin_String) + End_String );
  938. return RetString;
  939. }
  940. /////////////////////////////////////////////////////////////////
  941. EString operator+( char Char, const EString& End_String )
  942. {
  943. char Tmp[2];
  944. Tmp[0] = Char;
  945. Tmp[1] = 0;
  946. EString RetString( A2W( Tmp ) + End_String );
  947. return RetString;
  948. }
  949. /////////////////////////////////////////////////////////////////
  950. bool EString::operator<( const char* p_String ) const
  951. {
  952. return operator<(A2W( p_String ) );
  953. }
  954. /////////////////////////////////////////////////////////////////
  955. bool operator<( const char* p_String, const EString& String )
  956. {
  957. return operator<(A2W(p_String), String );
  958. }
  959. /////////////////////////////////////////////////////////////////
  960. bool EString::operator>( const char* p_String ) const
  961. {
  962. return EString::operator>(A2W( p_String) );
  963. }
  964. /////////////////////////////////////////////////////////////////
  965. bool operator>( const char* p_String, const EString& String )
  966. {
  967. return operator>( A2W(p_String), String );
  968. }
  969. /////////////////////////////////////////////////////////////////
  970. bool EString::operator<=( const char* p_String) const
  971. {
  972. return EString::operator<=( A2W(p_String) );
  973. }
  974. /////////////////////////////////////////////////////////////////
  975. bool operator<=( const char* p_String, const EString& String)
  976. {
  977. return ( A2W( p_String ) <= String );
  978. }
  979. /////////////////////////////////////////////////////////////////
  980. bool EString::operator>=( const char* p_String) const
  981. {
  982. return EString::operator>=( A2W(p_String) );
  983. }
  984. /////////////////////////////////////////////////////////////////
  985. bool operator>=( const char* p_String, const EString& String)
  986. {
  987. return ( A2W( p_String ) >= String );
  988. }
  989. /////////////////////////////////////////////////////////////////
  990. void EString::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(EChar) );
  1221. m_pBuffer->m_Data_Length = StrSize( m_pBuffer->Data() );
  1222. // clean up
  1223. va_end( Arg_List );
  1224. }
  1225. /////////////////////////////////////////////////////////////////
  1226. bool EString::operator==( const char* p_String )
  1227. {
  1228. return operator==( A2W( p_String ) );
  1229. }
  1230. /////////////////////////////////////////////////////////////////
  1231. bool operator==( const char* p_String, const EString& String)
  1232. {
  1233. return operator==( A2W( p_String ), String );
  1234. }
  1235. /////////////////////////////////////////////////////////////////
  1236. bool EString::operator!=( const char* p_String) const
  1237. {
  1238. return operator!=( A2W(p_String) );
  1239. }
  1240. /////////////////////////////////////////////////////////////////
  1241. bool operator!=( const char* p_String, const EString& String )
  1242. {
  1243. return operator!=( A2W(p_String), String );
  1244. }
  1245. /////////////////////////////////////////////////////////////////
  1246. int EString::Find( char Char, int Start_Index ) const
  1247. {
  1248. EChar Tmp;
  1249. mbtowc( &Tmp, &Char, 1 );
  1250. return Find( Tmp, Start_Index );
  1251. }
  1252. /////////////////////////////////////////////////////////////////
  1253. const EString& EString::operator=( char Char )
  1254. {
  1255. EChar Tmp;
  1256. mbtowc( &Tmp, &Char, 1 );
  1257. return operator=( Tmp );
  1258. }
  1259. #endif // Unicode
  1260. //****************************************************************
  1261. #pragma warning( pop )