ECharString.cpp 37 KB

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