TestSprintf.cpp 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include <EAStdC/EASprintf.h>
  5. #include <EAStdC/EASprintfOrdered.h>
  6. #include <EAStdC/EAString.h>
  7. #include <EAStdC/EADateTime.h>
  8. #include <EAStdCTest/EAStdCTest.h>
  9. #include <EASTL/string.h>
  10. #include <EASTL/unique_ptr.h>
  11. #include <EATest/EATest.h>
  12. #include <float.h>
  13. #include <string.h>
  14. #include <stdarg.h>
  15. static void TestCRTVsnprintf(char8_t* pDestination, size_t n, const char8_t* pFormat, ...)
  16. {
  17. va_list vList;
  18. va_start(vList, pFormat);
  19. EA::StdC::Vsnprintf(pDestination, n, pFormat, vList);
  20. va_end(vList);
  21. }
  22. static void TestCRTVsnprintf(char16_t* pDestination, size_t n, const char16_t* pFormat, ...)
  23. {
  24. va_list vList;
  25. va_start(vList, pFormat);
  26. EA::StdC::Vsnprintf(pDestination, n, pFormat, vList);
  27. va_end(vList);
  28. }
  29. static void TestCRTVsnprintf(char32_t* pDestination, size_t n, const char32_t* pFormat, ...)
  30. {
  31. va_list vList;
  32. va_start(vList, pFormat);
  33. EA::StdC::Vsnprintf(pDestination, n, pFormat, vList);
  34. va_end(vList);
  35. }
  36. #if EASTDC_VSNPRINTF8_ENABLED
  37. static void TestCRTVsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, ...)
  38. {
  39. va_list vList;
  40. va_start(vList, pFormat);
  41. EA::StdC::Vsnprintf8(pDestination, n, pFormat, vList);
  42. va_end(vList);
  43. }
  44. static void TestCRTVsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, ...)
  45. {
  46. va_list vList;
  47. va_start(vList, pFormat);
  48. EA::StdC::Vsnprintf16(pDestination, n, pFormat, vList);
  49. va_end(vList);
  50. }
  51. static void TestCRTVsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, ...)
  52. {
  53. va_list vList;
  54. va_start(vList, pFormat);
  55. EA::StdC::Vsnprintf32(pDestination, n, pFormat, vList);
  56. va_end(vList);
  57. }
  58. #endif
  59. static float FloatFromBitRepr(uint32_t bits)
  60. {
  61. union { float f; uint32_t u; } typepun;
  62. typepun.u = bits;
  63. return typepun.f;
  64. }
  65. static double DoubleFromBitRepr(uint64_t bits)
  66. {
  67. union { double d; uint64_t u; } typepun;
  68. typepun.u = bits;
  69. return (double)typepun.d;
  70. }
  71. static int TestSprintf8(int unused = 0, ...)
  72. {
  73. using namespace EA::StdC;
  74. int nErrorCount(0);
  75. // int Snprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  76. {
  77. char8_t sn18[128];
  78. Snprintf(sn18, 128, "%5s%-4d%03i", "abc", -12, 3);
  79. EATEST_VERIFY(!Strcmp(" abc-12 003", sn18));
  80. Snprintf(sn18, 128, "%.2f", 3.1415);
  81. EATEST_VERIFY(!Strcmp("3.14", sn18));
  82. }
  83. // int Vsnprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  84. {
  85. char8_t sn18[128];
  86. TestCRTVsnprintf(sn18, 128, "%5s%-5d%04i", "abc", -12, 3);
  87. EATEST_VERIFY(!Strcmp(" abc-12 0003", sn18));
  88. TestCRTVsnprintf(sn18, 128, "%.2f", 3.1415);
  89. EATEST_VERIFY(!Strcmp("3.14", sn18));
  90. }
  91. #if EASTDC_VSNPRINTF8_ENABLED
  92. {
  93. char8_t sn18[128];
  94. TestCRTVsnprintf8(sn18, 128, "%5s%-5d%04i", "abc", -12, 3);
  95. EATEST_VERIFY(!Strcmp(" abc-12 0003", sn18));
  96. TestCRTVsnprintf8(sn18, 128, "%.2f", 3.1415);
  97. EATEST_VERIFY(!Strcmp("3.14", sn18));
  98. }
  99. #endif
  100. // int Vscprintf(const char_t* pFormat, va_list arguments);
  101. {
  102. va_list arguments;
  103. va_start(arguments, unused);
  104. int result = Vscprintf("abc", arguments);
  105. EATEST_VERIFY(result == 3);
  106. va_end(arguments);
  107. }
  108. // template <typename String>
  109. // int StringVcprintf(String& s, const char8_t* EA_RESTRICT pFormat, va_list arguments)
  110. {
  111. va_list arguments;
  112. va_start(arguments, unused);
  113. eastl::string8 s8;
  114. int result = StringVcprintf(s8, "hello", arguments);
  115. EATEST_VERIFY((result == 5) && (s8 == "hello"));
  116. va_end(arguments);
  117. }
  118. // template <typename String>
  119. // int StringPrintf(String& s, const typename String::value_type* EA_RESTRICT pFormat, ...)
  120. {
  121. eastl::string8 s8;
  122. int result = StringPrintf(s8, "%s", "hello");
  123. EATEST_VERIFY((result == 5) && (s8 == "hello"));
  124. }
  125. {
  126. char buffer[128];
  127. Sprintf(buffer, "%Lf", 42.0l);
  128. EATEST_VERIFY(Strcmp(buffer, "42.000000") == 0);
  129. }
  130. {
  131. // Test for parsing of PRI constants in format strings
  132. char8_t buffer[128];
  133. Sprintf(buffer, "%" PRIxPTR, (intptr_t) 0xDEADBEEF);
  134. EATEST_VERIFY(Strcmp(buffer, "deadbeef") == 0);
  135. }
  136. // Sprintf
  137. {
  138. char8_t buffer[128];
  139. const int kHexValue = 0x12;
  140. Sprintf(buffer, "%.4x", kHexValue);
  141. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  142. Sprintf(buffer, "%04x", kHexValue);
  143. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  144. Sprintf(buffer, "%4.4x", kHexValue);
  145. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  146. Sprintf(buffer, "%04.4x", kHexValue);
  147. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  148. Sprintf(buffer, "%4.3x", kHexValue);
  149. EATEST_VERIFY(Strcmp(buffer, " 012") == 0);
  150. Sprintf(buffer, "%04.3x", kHexValue);
  151. EATEST_VERIFY(Strcmp(buffer, " 012") == 0);
  152. Sprintf(buffer, "%.*x", 4, kHexValue);
  153. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  154. Sprintf(buffer, "%0*x", 4, kHexValue);
  155. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  156. Sprintf(buffer, "%*.*x", 4, 4, kHexValue);
  157. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  158. Sprintf(buffer, "%0*.*x", 4, 4, kHexValue);
  159. EATEST_VERIFY(Strcmp(buffer, "0012") == 0);
  160. }
  161. {
  162. char8_t buffer[128];
  163. Sprintf(buffer, "decimal negative: \"%d\"\n", -2345);
  164. EATEST_VERIFY(Strcmp(buffer, "decimal negative: \"-2345\"\n") == 0);
  165. Sprintf(buffer, "octal negative: \"%o\"\n", -2345);
  166. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  167. EATEST_VERIFY(Strcmp(buffer, "octal negative: \"37777773327\"\n") == 0);
  168. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  169. EATEST_VERIFY(Strcmp(buffer, "octal negative: \"1777777777777777773327\"\n") == 0);
  170. Sprintf(buffer, "hex negative: \"%x\"\n", -2345);
  171. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  172. EATEST_VERIFY(Strcmp(buffer, "hex negative: \"fffff6d7\"\n") == 0);
  173. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  174. EATEST_VERIFY(Strcmp(buffer, "hex negative: \"fffffffffffff6d7\"\n") == 0);
  175. Sprintf(buffer, "long decimal number: \"%ld\"\n", -123456L);
  176. EATEST_VERIFY(Strcmp(buffer, "long decimal number: \"-123456\"\n") == 0);
  177. Sprintf(buffer, "long octal negative: \"%lo\"\n", -2345L);
  178. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  179. EATEST_VERIFY(Strcmp(buffer, "long octal negative: \"37777773327\"\n") == 0);
  180. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  181. EATEST_VERIFY(Strcmp(buffer, "long octal negative: \"1777777777777777773327\"\n") == 0);
  182. Sprintf(buffer, "long unsigned decimal number: \"%lu\"\n", -123456L);
  183. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  184. EATEST_VERIFY(Strcmp(buffer, "long unsigned decimal number: \"4294843840\"\n") == 0);
  185. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  186. EATEST_VERIFY(Strcmp(buffer, "long unsigned decimal number: \"18446744073709428160\"\n") == 0);
  187. Sprintf(buffer, "zero-padded LDN: \"%010ld\"\n", -123456L);
  188. EATEST_VERIFY(Strcmp(buffer, "zero-padded LDN: \"-000123456\"\n") == 0);
  189. Sprintf(buffer, "left-adjusted ZLDN: \"%-010ld\"\n", -123456L);
  190. EATEST_VERIFY(Strcmp(buffer, "left-adjusted ZLDN: \"-123456 \"\n") == 0);
  191. Sprintf(buffer, "space-padded LDN: \"%10ld\"\n", -123456L);
  192. EATEST_VERIFY(Strcmp(buffer, "space-padded LDN: \" -123456\"\n") == 0);
  193. Sprintf(buffer, "left-adjusted SLDN: \"%-10ld\"\n", -123456L);
  194. EATEST_VERIFY(Strcmp(buffer, "left-adjusted SLDN: \"-123456 \"\n") == 0);
  195. }
  196. {
  197. char8_t buffer[1024];
  198. char8_t str1[] = "abc de";
  199. char8_t str2[] = "abd def ghi jkl mno pqr stu vwz yz.";
  200. // The C99 standard specifies that leading zeros only put zeroes in front of numerical types. Spaces for others.
  201. Sprintf(buffer, "zero-padded string: \"%010s\"\n", str1);
  202. EATEST_VERIFY(Strcmp(buffer, "zero-padded string: \" abc de\"\n") == 0); // VC++ fails this, as it puts zeroes in front.
  203. Sprintf(buffer, "left-adjusted Z string: \"%-010s\"\n", str1);
  204. EATEST_VERIFY(Strcmp(buffer, "left-adjusted Z string: \"abc de \"\n") == 0);
  205. Sprintf(buffer, "space-padded string: \"%10s\"\n", str1);
  206. EATEST_VERIFY(Strcmp(buffer, "space-padded string: \" abc de\"\n") == 0);
  207. Sprintf(buffer, "left-adjusted S string: \"%-10s\"\n", str1);
  208. EATEST_VERIFY(Strcmp(buffer, "left-adjusted S string: \"abc de \"\n") == 0);
  209. Sprintf(buffer, "limited string: \"%.22s\"\n", str2);
  210. EATEST_VERIFY(Strcmp(buffer, "limited string: \"abd def ghi jkl mno pq\"\n") == 0);
  211. Sprintf(buffer, "null string: \"%s\"\n", (char8_t*)NULL);
  212. EATEST_VERIFY(Strcmp(buffer, "null string: \"(null)\"\n") == 0);
  213. Sprintf(buffer, "%10s\n", (char8_t*)NULL);
  214. EATEST_VERIFY(Strcmp(buffer, " (null)\n") == 0);
  215. Sprintf(buffer, "%-10s\n", (char8_t*)NULL);
  216. EATEST_VERIFY(Strcmp(buffer, "(null) \n") == 0);
  217. Sprintf(buffer, "%*s%*s%*s", -1, "one", -20, "two", -30, "three");
  218. EATEST_VERIFY(Strcmp(buffer, "onetwo three ") == 0);
  219. int i;
  220. memset(buffer, '_', sizeof(buffer));
  221. Sprintf(buffer, "x%1000s", " ");
  222. EATEST_VERIFY(buffer[0] == 'x');
  223. for(i = 0; i < 1000; i++)
  224. {
  225. if(buffer[1 + i] != ' ')
  226. break;
  227. }
  228. if(i != 1000)
  229. EATEST_VERIFY(i == 1000);
  230. else
  231. EATEST_VERIFY(buffer[1 + 1000] == 0);
  232. }
  233. { // String tests
  234. // We accept %hc, %c, %lc, %I8c, %I16c, %I32c (regular, regular, wide, char8_t, char16_t, char32_t)
  235. // We accept %hC, %C, %lC, %I8C, %I16C, %I32C (regular, wide, wide, char8_t, char16_t, char32_t)
  236. // We accept %hs, %s, %ls, %I8s, %I16s, %I32s (regular, regular, wide, char8_t, char16_t, char32_t)
  237. // We accept %hS, %S, %lS, %I8s, %I16s, %I32s (regular, wide, wide, char8_t, char16_t, char32_t)
  238. char8_t buffer[32];
  239. char8_t dStr8[2] = { 'd', 0 };
  240. char16_t eStr16[2] = { 'e', 0 };
  241. char32_t fStr32[2] = { 'f', 0 };
  242. Sprintf(buffer, "%hc %c %lc %I8c %I16c %I32c", 'a', 'b', EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  243. EATEST_VERIFY(Strcmp(buffer, "a b c d e f") == 0);
  244. Sprintf(buffer, "%hC %C %lC %I8C %I16C %I32C", 'a', EA_WCHAR('b'), EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  245. EATEST_VERIFY(Strcmp(buffer, "a b c d e f") == 0);
  246. Sprintf(buffer, "%hs %s %ls %I8s %I16s %I32s", "a", "b", EA_WCHAR("c"), dStr8, eStr16, fStr32);
  247. EATEST_VERIFY(Strcmp(buffer, "a b c d e f") == 0);
  248. Sprintf(buffer, "%hS %S %lS %I8S %I16S %I32S", "a", EA_WCHAR("b"), EA_WCHAR("c"), dStr8, eStr16, fStr32);
  249. EATEST_VERIFY(Strcmp(buffer, "a b c d e f") == 0);
  250. }
  251. { // NaN/Inf functionality tests
  252. char8_t buffer[256];
  253. const float kFloat32PositiveInfinity = FloatFromBitRepr(UINT32_C(0x7f800000));
  254. const float kFloat32NegativeInfinity = FloatFromBitRepr(UINT32_C(0xff800000));
  255. const double kFloat64PositiveInfinity = DoubleFromBitRepr(UINT64_C(0x7ff0000000000000));
  256. const double kFloat64NegativeInfinity = DoubleFromBitRepr(UINT64_C(0xfff0000000000000));
  257. const float kFloat32PositiveNaN = FloatFromBitRepr(UINT32_C(0x7fffffff));
  258. const float kFloat32NegativeNaN = FloatFromBitRepr(UINT32_C(0xffffffff));
  259. const double kFloat64PositiveNaN = DoubleFromBitRepr(UINT64_C(0x7fffffffffffffff));
  260. const double kFloat64NegativeNaN = DoubleFromBitRepr(UINT64_C(0xffffffffffffffff));
  261. Sprintf(buffer, "%e %f %g", kFloat32PositiveInfinity, kFloat32PositiveInfinity, kFloat32PositiveInfinity);
  262. EATEST_VERIFY(Strcmp(buffer, "inf inf inf") == 0);
  263. Sprintf(buffer, "%e %f %g", kFloat32NegativeInfinity, kFloat32NegativeInfinity, kFloat32NegativeInfinity);
  264. EATEST_VERIFY(Strcmp(buffer, "-inf -inf -inf") == 0);
  265. Sprintf(buffer, "%e %f %g", kFloat32PositiveNaN, kFloat32PositiveNaN, kFloat32PositiveNaN);
  266. EATEST_VERIFY(Strcmp(buffer, "nan nan nan") == 0);
  267. // The ARM instruction fcvtds (convert single to double point precision) does not maintain the sign of NaN.
  268. // (Float is always promoted to double in variable length arguments)
  269. // This seems to work on the Android
  270. // To consider: Disable this test altogether, as it seems to be too FPU-specific to spend our time with.
  271. #if defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64) || defined(EA_PROCESSOR_POWERPC)
  272. Sprintf(buffer, "%e %f %g", kFloat32NegativeNaN, kFloat32NegativeNaN, kFloat32NegativeNaN);
  273. EATEST_VERIFY(Strcmp(buffer, "-nan -nan -nan") == 0);
  274. #else
  275. EA_UNUSED(kFloat32NegativeNaN);
  276. #endif
  277. Sprintf(buffer, "%e %f %g", kFloat64PositiveInfinity, kFloat64PositiveInfinity, kFloat64PositiveInfinity);
  278. EATEST_VERIFY(Strcmp(buffer, "inf inf inf") == 0);
  279. Sprintf(buffer, "%e %f %g", kFloat64NegativeInfinity, kFloat64NegativeInfinity, kFloat64NegativeInfinity);
  280. EATEST_VERIFY(Strcmp(buffer, "-inf -inf -inf") == 0);
  281. Sprintf(buffer, "%e %f %g", kFloat64PositiveNaN, kFloat64PositiveNaN, kFloat64PositiveNaN);
  282. EATEST_VERIFY(Strcmp(buffer, "nan nan nan") == 0);
  283. Sprintf(buffer, "%e %f %g", kFloat64NegativeNaN, kFloat64NegativeNaN, kFloat64NegativeNaN);
  284. EATEST_VERIFY(Strcmp(buffer, "-nan -nan -nan") == 0);
  285. #if !defined(EA_PLATFORM_CAPILANO)
  286. // This test should theoretically work on Capilano. But currently it must be disabled or it
  287. // will cause the runtime to assert. A bug has been logged with MS so hopefully the issue
  288. // will be resolved in the future. We should try to enable the test later if it is resolved.
  289. //
  290. // Link to issue;
  291. // https://forums.xboxlive.com/questions/48008/is-there-a-bug-in-string-formatting-functions-in-t.html
  292. const double kSmallestDoubleNum = DoubleFromBitRepr(0x0000000000000001ull);
  293. Sprintf(buffer, "%f", kSmallestDoubleNum);
  294. EATEST_VERIFY_F(Strcmp(buffer, "0.000000") == 0, "Result was %s", buffer);
  295. #endif
  296. }
  297. { // Extended functionality tests
  298. char8_t buffer[256];
  299. Sprintf(buffer, "%08x %032b", 0xaaaaaaaa, 0xaaaaaaaa);
  300. EATEST_VERIFY(Strcmp(buffer, "aaaaaaaa 10101010101010101010101010101010") == 0);
  301. Sprintf(buffer, "%I8u %I8d %I16u %I16d %I32u %I32d %I64u %I64d", 0xff, 0xff, 0xffff, 0xffff, 0xffffffff, 0xffffffff, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
  302. EATEST_VERIFY(Strcmp(buffer, "255 -1 65535 -1 4294967295 -1 18446744073709551615 -1") == 0);
  303. Sprintf(buffer, "%s %10s", NULL, NULL);
  304. EATEST_VERIFY(Strcmp(buffer, "(null) (null)") == 0);
  305. }
  306. {
  307. char8_t buffer[1024];
  308. int i;
  309. Sprintf(buffer, "e-style >= 1: \"%e\"\n", 12.34);
  310. EATEST_VERIFY(Strcmp(buffer, "e-style >= 1: \"1.234000e+01\"\n") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  311. Sprintf(buffer, "e-style >= .1: \"%e\"\n", 0.1234);
  312. EATEST_VERIFY(Strcmp(buffer, "e-style >= .1: \"1.234000e-01\"\n") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  313. Sprintf(buffer, "e-style < .1: \"%e\"\n", 0.001234);
  314. EATEST_VERIFY(Strcmp(buffer, "e-style < .1: \"1.234000e-03\"\n") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  315. Sprintf(buffer, "e-style big: \"%.60e\"\n", 1e20);
  316. EATEST_VERIFY(Strcmp(buffer, "e-style big: \"1.000000000000000000000000000000000000000000000000000000000000e+20\"\n") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  317. Sprintf(buffer, "e-style == .1: \"%e\"\n", 0.1);
  318. EATEST_VERIFY(Strcmp(buffer, "e-style == .1: \"1.000000e-01\"\n") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  319. Sprintf(buffer, "f-style >= 1: \"%f\"\n", 12.34);
  320. EATEST_VERIFY(Strcmp(buffer, "f-style >= 1: \"12.340000\"\n") == 0);
  321. Sprintf(buffer, "f-style >= 1: \"%.3f\"\n", 12.34);
  322. EATEST_VERIFY(Strcmp(buffer, "f-style >= 1: \"12.340\"\n") == 0);
  323. Sprintf(buffer, "f-style >= .1: \"%f\"\n", 0.1234);
  324. EATEST_VERIFY(Strcmp(buffer, "f-style >= .1: \"0.123400\"\n") == 0);
  325. Sprintf(buffer, "f-style < .1: \"%f\"\n", 0.001234);
  326. EATEST_VERIFY(Strcmp(buffer, "f-style < .1: \"0.001234\"\n") == 0);
  327. Sprintf(buffer, "g-style >= 1: \"%.0g\"\n", 1.234);
  328. EATEST_VERIFY(Strcmp(buffer, "g-style >= 1: \"1.2\"\n") == 0);//%g takes precision to be 1, even if set to be 0
  329. Sprintf(buffer, "g-style >= 1: \"%.1g\"\n", 1.234);
  330. EATEST_VERIFY(Strcmp(buffer, "g-style >= 1: \"1.2\"\n") == 0);
  331. Sprintf(buffer, "g-style >= 1: \"%.2g\"\n", 1.234);
  332. EATEST_VERIFY(Strcmp(buffer, "g-style >= 1: \"1.23\"\n") == 0);
  333. Sprintf(buffer, "g-style >= 1: \"%g\"\n", 12.34);
  334. EATEST_VERIFY(Strcmp(buffer, "g-style >= 1: \"12.34\"\n") == 0);
  335. Sprintf(buffer, "g-style >= .1: \"%g\"\n", 0.1234);
  336. EATEST_VERIFY(Strcmp(buffer, "g-style >= .1: \"0.1234\"\n") == 0);
  337. Sprintf(buffer, "g-style < .1: \"%g\"\n", 0.001234);
  338. EATEST_VERIFY(Strcmp(buffer, "g-style < .1: \"0.001234\"\n") == 0);
  339. Sprintf(buffer, "g-style < .1: \"%g\"\n", 0.001234678);
  340. EATEST_VERIFY(Strcmp(buffer, "g-style < .1: \"0.001235\"\n") == 0);
  341. Sprintf(buffer, "g-style big: \"%.60g\"\n", 1e20);
  342. EATEST_VERIFY(Strcmp(buffer, "g-style big: \"100000000000000000000\"\n") == 0);
  343. //Sprintf(buffer, "%#.4g\n", 0.0); // The C99 committee has decided in a defect analysis that this is how it should work.
  344. //EATEST_VERIFY(Strcmp(buffer, "0\n") == 0);
  345. Sprintf(buffer, " %6.5f\n", .099999999860301614);
  346. EATEST_VERIFY(Strcmp(buffer, " 0.10000\n") == 0);
  347. Sprintf(buffer, " %6.5f\n", .1);
  348. EATEST_VERIFY(Strcmp(buffer, " 0.10000\n") == 0);
  349. Sprintf(buffer, "x%5.4fx\n", .5);
  350. EATEST_VERIFY(Strcmp(buffer, "x0.5000x\n") == 0);
  351. Sprintf(buffer, "%#03x\n", 1);
  352. EATEST_VERIFY(Strcmp(buffer, "0x1\n") == 0);
  353. memset(buffer, '_', sizeof(buffer));
  354. Sprintf(buffer, "%.300f", 1.0);
  355. EATEST_VERIFY((buffer[0] == '1') && (buffer[1] == '.'));
  356. for(i = 0; i < 300; i++)
  357. {
  358. if(buffer[2 + i] != '0')
  359. break;
  360. }
  361. if(i != 300)
  362. EATEST_VERIFY(i == 300);
  363. else
  364. EATEST_VERIFY(buffer[2 + 300] == 0);
  365. double d = static_cast<double>(FLT_MIN); // We are intentionally using FLT_MIN and not DBL_MIN.
  366. d /= 2.0;
  367. Sprintf(buffer, "%.17e", d); // It should be something like 5.87747175411143___e-39 where count and values of the _ digits vary by hardware.
  368. buffer[16] = buffer[17] = buffer[18] = '_'; // Replace the uncertain digits with '_' characters, as they are system-dependent.
  369. EATEST_VERIFY(Strcmp(buffer, "5.87747175411143___e-39") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  370. Sprintf(buffer, "%15.5e\n", 4.9406564584124654e-307);
  371. EATEST_VERIFY(Strcmp(buffer, " 4.94066e-307\n") == 0);
  372. // Exercise bug report on PS3 platform which results in a crash when printing DBL_MAX.
  373. i = Sprintf(buffer, "%15.8g", DBL_MAX);
  374. EATEST_VERIFY(i > 0);
  375. i = Sprintf(buffer, "%15.8g", FLT_MAX);
  376. EATEST_VERIFY(i > 0);
  377. }
  378. {
  379. char8_t buffer[256];
  380. const char8_t* pExpected;
  381. // VC++ sprintf would fail these tests, as the Standard says to print no more
  382. // than 2 unless necessary, yet VC++ sprintf prints 3 digits exponents.
  383. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 0.0, 0.0, 0.0);
  384. EATEST_VERIFY(Strcmp(buffer, "| 0.0000| 0.0000e+00| 0|") == 0);
  385. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 1.0, 1.0, 1.0);
  386. EATEST_VERIFY(Strcmp(buffer, "| 1.0000| 1.0000e+00| 1|") == 0);
  387. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", -1.0, -1.0, -1.0);
  388. EATEST_VERIFY(Strcmp(buffer, "| -1.0000| -1.0000e+00| -1|") == 0);
  389. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 100.0, 100.0, 100.0);
  390. EATEST_VERIFY(Strcmp(buffer, "| 100.0000| 1.0000e+02| 100|") == 0);
  391. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 1000.0, 1000.0, 1000.0);
  392. EATEST_VERIFY(Strcmp(buffer, "| 1000.0000| 1.0000e+03| 1000|") == 0);
  393. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 10000.0, 10000.0, 10000.0);
  394. EATEST_VERIFY(Strcmp(buffer, "| 10000.0000| 1.0000e+04| 1e+04|") == 0);
  395. // %g picks one of %f or %e, though uses precision differently.
  396. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 12346.0, 12346.0, 12346.0);
  397. pExpected = "| 12346.0000| 1.2346e+04| 1.235e+04|";
  398. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  399. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 100000.0, 100000.0, 100000.0);
  400. pExpected = "| 100000.0000| 1.0000e+05| 1e+05|";
  401. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  402. Sprintf(buffer, "|%12.4f|%12.4e|%12.4g|", 123467.0, 123467.0, 123467.0);
  403. pExpected = "| 123467.0000| 1.2347e+05| 1.235e+05|";
  404. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  405. }
  406. {
  407. char8_t buffer[256];
  408. // Verify that snprintf follows the C99 convention of returning the number of characters
  409. // required. This is as opposed to the non-standard way that some libraries just return
  410. // -1 if the buffer isn't big enough.
  411. const int kBuf1Capacity = 20;
  412. char8_t buf1[kBuf1Capacity];
  413. int n1 = Snprintf(buf1, kBuf1Capacity, "%30s", "foo");
  414. Sprintf(buffer, "snprintf(\"%%30s\", \"foo\") == %d, \"%.*s\"\n", n1, kBuf1Capacity, buf1);
  415. EATEST_VERIFY(Strcmp(buffer, "snprintf(\"%30s\", \"foo\") == 30, \" \"\n") == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  416. const int kBuf2Capacity = 512;
  417. char8_t buf2[kBuf2Capacity];
  418. int n2 = Snprintf(buf2, kBuf2Capacity, "%.1000u", 10);
  419. Sprintf(buffer, "snprintf(\"%%.1000u\", 10) == %d\n", n2);
  420. EATEST_VERIFY(Strcmp(buffer, "snprintf(\"%.1000u\", 10) == 1000\n") == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  421. const int kBuf3Capacity = 512;
  422. char8_t buf3[kBuf3Capacity];
  423. char8_t* pString = new char8_t[100000];
  424. memset(pString, '_', 100000 * sizeof(char8_t));
  425. pString[100000 - 1] = 0;
  426. int n3 = Snprintf(buf3, kBuf2Capacity, "%s", pString);
  427. Sprintf(buffer, "snprintf(\"%%s\", pString) == %d\n", n3);
  428. EATEST_VERIFY(Strcmp(buffer, "snprintf(\"%s\", pString) == 99999\n") == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  429. delete[] pString;
  430. int n4 = Snprintf(NULL, 0, "%s", "abc");
  431. Sprintf(buffer, "snprintf(NULL, \"abc\") == %d\n", n4);
  432. EATEST_VERIFY(Strcmp(buffer, "snprintf(NULL, \"abc\") == 3\n") == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  433. int n5 = Snprintf(NULL, 100, "%s", "abc");
  434. Sprintf(buffer, "snprintf(NULL, \"abc\") == %d\n", n5);
  435. EATEST_VERIFY(Strcmp(buffer, "snprintf(NULL, \"abc\") == 3\n") == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  436. }
  437. {
  438. char8_t buffer[16][256];
  439. int n = 0, i, j, k, m;
  440. for(i = 0; i < 2; i++)
  441. {
  442. for(j = 0; j < 2; j++)
  443. {
  444. for(k = 0; k < 2; k++)
  445. {
  446. for(m = 0; m < 2; m++)
  447. {
  448. char8_t prefix[7];
  449. char8_t format[128];
  450. Strcpy(prefix, "%");
  451. if(i == 0)
  452. Strcat(prefix, "-");
  453. if(j == 0)
  454. Strcat(prefix, "+");
  455. if(k == 0)
  456. Strcat(prefix, "#");
  457. if(m == 0)
  458. Strcat(prefix, "0");
  459. #define DEC -123
  460. #define INT 255
  461. #define UNS (~0)
  462. Sprintf(format, "%%5s |%s6d |%s6o |%s6x |%s6X |%s6u |", prefix, prefix, prefix, prefix, prefix);
  463. Sprintf(buffer[n], format, prefix, DEC, INT, INT, INT, UNS);
  464. n++;
  465. }
  466. }
  467. }
  468. }
  469. EATEST_VERIFY(Strcmp(buffer[ 0], "%-+#0 |-123 |0377 |0xff |0XFF |4294967295 |") == 0);
  470. EATEST_VERIFY(Strcmp(buffer[ 1], " %-+# |-123 |0377 |0xff |0XFF |4294967295 |") == 0);
  471. EATEST_VERIFY(Strcmp(buffer[ 2], " %-+0 |-123 |377 |ff |FF |4294967295 |") == 0);
  472. EATEST_VERIFY(Strcmp(buffer[ 3], " %-+ |-123 |377 |ff |FF |4294967295 |") == 0);
  473. EATEST_VERIFY(Strcmp(buffer[ 4], " %-#0 |-123 |0377 |0xff |0XFF |4294967295 |") == 0);
  474. EATEST_VERIFY(Strcmp(buffer[ 5], " %-# |-123 |0377 |0xff |0XFF |4294967295 |") == 0);
  475. EATEST_VERIFY(Strcmp(buffer[ 6], " %-0 |-123 |377 |ff |FF |4294967295 |") == 0);
  476. EATEST_VERIFY(Strcmp(buffer[ 7], " %- |-123 |377 |ff |FF |4294967295 |") == 0);
  477. EATEST_VERIFY(Strcmp(buffer[ 8], " %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |") == 0);
  478. EATEST_VERIFY(Strcmp(buffer[ 9], " %+# | -123 | 0377 | 0xff | 0XFF |4294967295 |") == 0);
  479. EATEST_VERIFY(Strcmp(buffer[10], " %+0 |-00123 |000377 |0000ff |0000FF |4294967295 |") == 0);
  480. EATEST_VERIFY(Strcmp(buffer[11], " %+ | -123 | 377 | ff | FF |4294967295 |") == 0);
  481. EATEST_VERIFY(Strcmp(buffer[12], " %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |") == 0);
  482. EATEST_VERIFY(Strcmp(buffer[13], " %# | -123 | 0377 | 0xff | 0XFF |4294967295 |") == 0);
  483. EATEST_VERIFY(Strcmp(buffer[14], " %0 |-00123 |000377 |0000ff |0000FF |4294967295 |") == 0);
  484. EATEST_VERIFY(Strcmp(buffer[15], " % | -123 | 377 | ff | FF |4294967295 |") == 0);
  485. }
  486. {
  487. char8_t buffer[256];
  488. const char8_t* pExpected;
  489. Sprintf(buffer, "%e", 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  490. pExpected = "1.234568e+06";
  491. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  492. Sprintf(buffer, "%f", 1234567.8);
  493. pExpected = "1234567.800000";
  494. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  495. Sprintf(buffer, "%g", 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  496. pExpected = "1.23457e+06";
  497. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  498. Sprintf(buffer, "%g", 123.456);
  499. pExpected = "123.456";
  500. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  501. Sprintf(buffer, "%g", 1000000.0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  502. pExpected = "1e+06";
  503. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  504. Sprintf(buffer, "%g", 10.0);
  505. pExpected = "10";
  506. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  507. Sprintf(buffer, "%g", 0.02);
  508. pExpected = "0.02";
  509. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  510. Sprintf(buffer, "%.1f", 0.09523f);
  511. pExpected = "0.1";
  512. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  513. Sprintf(buffer, "%.1f", 0.9523f);
  514. pExpected = "1.0";
  515. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  516. Sprintf(buffer, "%.1f", -0.9523f);
  517. pExpected = "-1.0";
  518. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  519. Sprintf(buffer, "%.1e", 0.9523f);
  520. pExpected = "9.5e-01";
  521. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  522. #if EASTDC_NATIVE_FCVT && defined(_MSC_VER)
  523. Sprintf(buffer, "%.0e", 0.9523f);
  524. pExpected = "1e+00";
  525. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  526. #else
  527. // Note that this test result is incorrect! It should be "1e+00" and not "1.0e00".
  528. // We have a bug and it needs to be fixed. At least the numerical value is still correct.
  529. // The problem is that GCC's standard library fcvt and our custom fcvt generate a string
  530. // of "10" instead of "1" for the case of calling fcvt(0.9523, 0, ...).
  531. Sprintf(buffer, "%.0e", 0.9523f);
  532. pExpected = "1.0e+00";
  533. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  534. #endif
  535. }
  536. { // Test the ' extension, which cases numbers to be printed with a thousands separator.
  537. char8_t buffer[64];
  538. const char8_t* pExpected;
  539. Sprintf(buffer, "%'u", 123456789);
  540. EATEST_VERIFY(Strcmp(buffer, "123,456,789") == 0);
  541. Sprintf(buffer, "%'d", -123456789);
  542. EATEST_VERIFY(Strcmp(buffer, "-123,456,789") == 0);
  543. Sprintf(buffer, "%'I8u", 123);
  544. EATEST_VERIFY(Strcmp(buffer, "123") == 0);
  545. Sprintf(buffer, "%'I16u", 12345);
  546. EATEST_VERIFY(Strcmp(buffer, "12,345") == 0);
  547. Sprintf(buffer, "%'I16d", -12345);
  548. EATEST_VERIFY(Strcmp(buffer, "-12,345") == 0);
  549. Sprintf(buffer, "%'I32u", 12345678);
  550. EATEST_VERIFY(Strcmp(buffer, "12,345,678") == 0);
  551. Sprintf(buffer, "%'I32d", -12345678);
  552. EATEST_VERIFY(Strcmp(buffer, "-12,345,678") == 0);
  553. Sprintf(buffer, "%20I32d", -12345678);
  554. EATEST_VERIFY(Strcmp(buffer, " -12345678") == 0);
  555. Sprintf(buffer, "%'20I32d", -12345678); // Verify that the , chars count towards the field width.
  556. EATEST_VERIFY(Strcmp(buffer, " -12,345,678") == 0);
  557. Sprintf(buffer, "%'I32x", 0x12345678); // ' has no effect on hex formatting.
  558. EATEST_VERIFY(Strcmp(buffer, "12345678") == 0);
  559. Sprintf(buffer, "%'I64u", UINT64_C(1234999995678));
  560. EATEST_VERIFY(Strcmp(buffer, "1,234,999,995,678") == 0);
  561. Sprintf(buffer, "%'I64d", INT64_C(-1234599999678));
  562. EATEST_VERIFY(Strcmp(buffer, "-1,234,599,999,678") == 0);
  563. Sprintf(buffer, "%'I64x", UINT64_C(0x1234567812345678)); // ' has no effect on hex formatting.
  564. EATEST_VERIFY(Strcmp(buffer, "1234567812345678") == 0);
  565. Sprintf(buffer, "%'f", 123456.234);
  566. EATEST_VERIFY(Strcmp(buffer, "123,456.234000") == 0);
  567. Sprintf(buffer, "%'e", 1234567.8); // ' has no effect on %e formatting.
  568. EATEST_VERIFY(Strcmp(buffer, "1.234568e+06") == 0);
  569. Sprintf(buffer, "%'g", 1234.54); // In some cases %g acts like %f.
  570. pExpected = "1,234.54";
  571. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  572. Sprintf(buffer, "%'g", 1234567.8); // In some cases %g acts like %f.
  573. pExpected = "1.23457e+06";
  574. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I8s\n Actual: %I8s", pExpected, buffer);
  575. }
  576. {
  577. char8_t buffer[256];
  578. Sprintf(buffer, "%hhu", UCHAR_MAX + 2);
  579. EATEST_VERIFY(Strcmp(buffer, "1") == 0); // VC++ fails this, as it doesn't implement the C99 standard %hh modifier.
  580. Sprintf(buffer, "%hu", USHRT_MAX + 2);
  581. EATEST_VERIFY(Strcmp(buffer, "1") == 0);
  582. }
  583. {
  584. char8_t buffer[128];
  585. Sprintf(buffer, "%5.s", "xyz");
  586. EATEST_VERIFY(Strcmp(buffer, " ") == 0);
  587. Sprintf(buffer, "%5.f", 33.3);
  588. EATEST_VERIFY(Strcmp(buffer, " 33") == 0);
  589. Sprintf(buffer, "%8.e", 33.3e7);
  590. EATEST_VERIFY(Strcmp(buffer, " 3e+08") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  591. Sprintf(buffer, "%8.E", 33.3e7);
  592. EATEST_VERIFY(Strcmp(buffer, " 3E+08") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  593. Sprintf(buffer, "%.g", 33.3);
  594. EATEST_VERIFY(Strcmp(buffer, "3e+01") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  595. Sprintf(buffer, "%.G", 33.3);
  596. EATEST_VERIFY(Strcmp(buffer, "3E+01") == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  597. }
  598. {
  599. char8_t buffer[128];
  600. int precision;
  601. //for %g, precision 0 is not valid, if specified 0, it is taken as 1
  602. precision = 0;
  603. Sprintf(buffer, "%.*g", precision, 3.3);
  604. EATEST_VERIFY(Strcmp(buffer, "3.3") == 0);
  605. precision = 0;
  606. Sprintf(buffer, "%.*G", precision, 3.3);
  607. EATEST_VERIFY(Strcmp(buffer, "3.3") == 0);
  608. precision = 0;
  609. Sprintf(buffer, "%7.*G", precision, 3.33);
  610. EATEST_VERIFY(Strcmp(buffer, " 3.3") == 0);
  611. precision = 3;
  612. Sprintf(buffer, "%04.*o", precision, 33);
  613. EATEST_VERIFY(Strcmp(buffer, " 041") == 0);
  614. precision = 7;
  615. Sprintf(buffer, "%09.*u", precision, 33);
  616. EATEST_VERIFY(Strcmp(buffer, " 0000033") == 0);
  617. precision = 3;
  618. Sprintf(buffer, "%04.*x", precision, 33);
  619. EATEST_VERIFY(Strcmp(buffer, " 021") == 0);
  620. precision = 3;
  621. Sprintf(buffer, "%04.*X", precision, 33);
  622. EATEST_VERIFY(Strcmp(buffer, " 021") == 0);
  623. }
  624. { // EAC tests
  625. char8_t dest1[1024], dest3[1024];
  626. // Test #1
  627. Sprintf(dest1, "Hello. Test.");
  628. EATEST_VERIFY(Strcmp(dest1, "Hello. Test.") == 0);
  629. // Test #2
  630. Sprintf(dest1,"Hello.\\ \\ a\n\n\tTest.");
  631. EATEST_VERIFY(Strcmp(dest1, "Hello.\\ \\ a\n\n\tTest.") == 0);
  632. // Test #3
  633. Sprintf(dest1, "Int. %d %d %d blah%d%d", -1, 1, 0, 392832993, -32903298);
  634. EATEST_VERIFY(Strcmp(dest1, "Int. -1 1 0 blah392832993-32903298") == 0);
  635. // Test #4
  636. Sprintf(dest1,"Float. %f %f %f\n", -0.01f, 10.0f, 0.0f);
  637. EATEST_VERIFY(Strcmp(dest1, "Float. -0.010000 10.000000 0.000000\n") == 0);
  638. // Test #5
  639. Sprintf(dest1, "Str/char8_t: %s %c %c", "test", 'b', 0341);
  640. EATEST_VERIFY(Strcmp(dest1, "Str/char8_t: test b \341") == 0);
  641. // Test #6
  642. Sprintf(dest1,"Hex: %x %X",3829,-392);
  643. EATEST_VERIFY(Strcmp(dest1, "Hex: ef5 FFFFFE78") == 0);
  644. // Test #7
  645. //for(int32_t i = 0; i < 7; i++) We'd need to modify the tests below to deal with this.
  646. //{
  647. Sprintf(dest3, "Precision: %%.%df", 0);
  648. EATEST_VERIFY(Strcmp(dest3, "Precision: %.0f") == 0);
  649. Sprintf(dest1, dest3, 34.56f);
  650. EATEST_VERIFY(Strcmp(dest1, "Precision: 35") == 0);
  651. //}
  652. // Test #8
  653. Sprintf(dest1, "Align. %9s %8d %5s %10.2f", "test", 10293, "testtesttest", 10.8f);
  654. EATEST_VERIFY(Strcmp(dest1, "Align. test 10293 testtesttest 10.80") == 0);
  655. // Test #9
  656. Sprintf(dest1, "Align. %-9s %-8d %-5s %-10.2f", "test", 10293, "testtesttest", 10.8f);
  657. EATEST_VERIFY(Strcmp(dest1, "Align. test 10293 testtesttest 10.80 ") == 0);
  658. // Test #10
  659. Sprintf(dest1, "Str: %S", EA_WCHAR("test"));
  660. EATEST_VERIFY(Strcmp(dest1, "Str: test") == 0);
  661. // Test #11
  662. Sprintf(dest1, "Str: %9S", EA_WCHAR("test"));
  663. EATEST_VERIFY(Strcmp(dest1, "Str: test") == 0);
  664. // Test #12
  665. Sprintf(dest1, "Str: %-9S", EA_WCHAR("test"));
  666. EATEST_VERIFY(Strcmp(dest1, "Str: test ") == 0);
  667. // Test #13
  668. Sprintf(dest1, "0x%08x", 0x876543);
  669. EATEST_VERIFY(Strcmp(dest1, "0x00876543") == 0);
  670. // Test #14
  671. Sprintf(dest1, "%08d", -15);
  672. EATEST_VERIFY(Strcmp(dest1, "-0000015") == 0);
  673. // Test #15
  674. Sprintf(dest1, "Int. %i %i %i blah%i%i", -1, 1, 0, 392832993, -32903298);
  675. EATEST_VERIFY(Strcmp(dest1, "Int. -1 1 0 blah392832993-32903298") == 0);
  676. // Test #16
  677. Sprintf(dest1, "%p", 0x38e340);
  678. EATEST_VERIFY(Strcmp(dest1, "38e340") == 0);
  679. // Test #17
  680. Sprintf(dest1, "%u", -372834);
  681. EATEST_VERIFY(Strcmp(dest1, "4294594462") == 0);
  682. // Test #18
  683. int tv1, tv2;
  684. Sprintf(dest1, "Testing%n%dTests%nabc", &tv1, 4738, &tv2);
  685. EATEST_VERIFY(Strcmp(dest1, "Testing4738Testsabc") == 0);
  686. EATEST_VERIFY((tv1 == 7) && (tv2 == 16));
  687. // Test #19
  688. Sprintf(dest1, "%o", -372834);
  689. EATEST_VERIFY(Strcmp(dest1, "37776447636") == 0);
  690. // Test #20
  691. Sprintf(dest1, "%%%s", "Hello");
  692. EATEST_VERIFY(Strcmp(dest1, "%Hello") == 0);
  693. // Test #21
  694. Sprintf(dest1, "%I64d", INT64_C(-12345678901234));
  695. EATEST_VERIFY(Strcmp(dest1, "-12345678901234") == 0);
  696. // Test #22
  697. Sprintf(dest1, "%I64u", INT64_C(-12345678901234));
  698. EATEST_VERIFY(Strcmp(dest1, "18446731728030650382") == 0);
  699. // Test #23
  700. Sprintf(dest1, "%I64x", INT64_C(0x1234567890123a));
  701. EATEST_VERIFY(Strcmp(dest1, "1234567890123a") == 0);
  702. // Test #24
  703. Sprintf(dest1, "%I64X", INT64_C(0x1234567890123A));
  704. EATEST_VERIFY(Strcmp(dest1, "1234567890123A") == 0);
  705. }
  706. { // EAC FPU tests
  707. const float list1f[]={0.832f,0.00832f,8.32f,0.0f,-0.15f};
  708. const char8_t* list1[]={"0.832000","0.008320","8.320000","0.000000","-0.150000"};
  709. const float list2f[]={0.0000000000123f,0.000000000123f,0.00000000123f,0.0000000123f
  710. ,0.000000123f,0.00000123f,0.0000123f,0.000123f,0.00123f,0.0123f,0.123f,1.23f
  711. ,12.3f,123.0f,1230.0f,12300.0f,123000.0f,1230000.0f,12300000.0f,123000000.0f,12300000000.0f};
  712. const char8_t* list2[]={"0.000000","0.000000","0.000000","0.000000"
  713. ,"0.000000","0.000001","0.000012","0.000123","0.001230","0.012300","0.123000","1.230000"
  714. ,"12.300000","123.000000","1230.000000","12300.000000","123000.000000","1230000.000000",
  715. "12300000.000000","123000000.000000","12300000000.000000"};
  716. const char8_t* list22D[]={"0.00","0.00","0.00","0.00"
  717. ,"0.00","0.00","0.00","0.00","0.00","0.01","0.12","1.23"
  718. ,"12.30","123.00","1230.00","12300.00","123000.00","1230000.00","12300000.00",
  719. "123000000.00","12300000000.00"};
  720. const char8_t* list23DSL[]={"1.230e-11","1.230e-10","1.230e-09","1.230e-08"
  721. ,"1.230e-07","1.230e-06","1.230e-05","1.230e-04","1.230e-03","1.230e-02","1.230e-01","1.230e+00"
  722. ,"1.230e+01","1.230e+02","1.230e+03","1.230e+04","1.230e+05","1.230e+06","1.230e+07","1.230e+08"
  723. ,"1.230e+10"};
  724. const char8_t* list24DSL[]={"1.230E-11","1.230E-10","1.230E-09","1.230E-08"
  725. ,"1.230E-07","1.230E-06","1.230E-05","1.230E-04","1.230E-03","1.230E-02","1.230E-01","1.230E+00"
  726. ,"1.230E+01","1.230E+02","1.230E+03","1.230E+04","1.230E+05","1.230E+06","1.230E+07","1.230E+08"
  727. ,"1.230E+10"};
  728. const char8_t* list31DSL[]={"1.23e-11","1.23e-10","1.23e-09","1.23e-08"
  729. ,"1.23e-07","1.23e-06","1.23e-05","0","0.001","0.012","0.123","1.23"
  730. ,"12.3","123","1.23e+03","1.23e+04","1.23e+05","1.23e+06","1.23e+07","1.23e+08"
  731. ,"1.23e+10"};
  732. const char8_t* list32DSL[]={"1.23E-11","1.23E-10","1.23E-09","1.23E-08"
  733. ,"1.23E-07","1.23E-06","1.23E-05","0","0.001","0.012","0.123","1.23"
  734. ,"12.3","123","1.23E+03","1.23E+04","1.23E+05","1.23E+06","1.23E+07","1.23E+08"
  735. ,"1.23E+10"};
  736. int32_t list1size = sizeof(list1f)/sizeof(list1f[0]);
  737. int32_t list2size = sizeof(list2f)/sizeof(list2f[0]);
  738. int32_t i, error;
  739. char8_t str[256];
  740. error = 0;
  741. for(i = 0; i < list1size; i++)
  742. {
  743. Sprintf(str, "%f", list1f[i]);
  744. if(Strcmp(str, list1[i]) != 0)
  745. {
  746. error++;
  747. EA::UnitTest::Report("\nMismatch(A): %s/%s (Halt if > 2/section A)", str, list1[i]);
  748. }
  749. }
  750. EATEST_VERIFY(error <= 2);
  751. error = 0;
  752. for(i = 0; i < list2size - 4; i++) // purposely take out the last 4 due to precision of float
  753. {
  754. Sprintf(str, "%f", list2f[i]);
  755. if(Strcmp(str, list2[i]) != 0)
  756. {
  757. error++;
  758. EA::UnitTest::Report("\nMismatch(B): %s/%s (Halt if > 3/section B)", str, list2[i]);
  759. }
  760. }
  761. EATEST_VERIFY(error <= 3);
  762. error = 0;
  763. for(i = 0; i < list2size - 2; i++) // purposely take out the last 2 due to precision of float
  764. {
  765. Sprintf(str, "%.2f", list2f[i]);
  766. if(Strcmp(str, list22D[i]) != 0)
  767. {
  768. error++;
  769. EA::UnitTest::Report("\nMismatch(C): %s/%s (Halt if > 3/section C)", str, list22D[i]);
  770. }
  771. }
  772. EATEST_VERIFY(error <= 3);
  773. error = 0;
  774. for(i=0; i < list2size; i++)
  775. {
  776. Sprintf(str, "%.3e", list2f[i]);
  777. if(Strcmp(str, list23DSL[i]) != 0)
  778. {
  779. error++;
  780. EA::UnitTest::Report("\nMismatch(D): %s/%s (Halt if > 3/section D)", str, list23DSL[i]);
  781. }
  782. }
  783. EATEST_VERIFY(error <= 2);
  784. error = 0;
  785. for(i = 0; i < list2size; i++)
  786. {
  787. Sprintf(str,"%.3E", list2f[i]);
  788. if(Strcmp(str, list24DSL[i]) != 0)
  789. {
  790. error++;
  791. EA::UnitTest::Report("\nMismatch(E): %s/%s (Halt if > 3/section E)", str, list24DSL[i]);
  792. }
  793. }
  794. EATEST_VERIFY(error <= 2);
  795. error = 0;
  796. for(i = 0; i < list2size; i++)
  797. {
  798. Sprintf(str,"%.3g", list2f[i]);
  799. if(Strcmp(str, list31DSL[i]) != 0)
  800. {
  801. error++;
  802. EA::UnitTest::Report("\nMismatch(F): %s/%s (Halt if > 0/section F)", str, list23DSL[i]);
  803. }
  804. }
  805. EATEST_VERIFY(error == 0);
  806. error=0;
  807. for (i=0;i<list2size;i++)
  808. {
  809. Sprintf(str, "%.3G", list2f[i]);
  810. if(Strcmp(str, list32DSL[i]) != 0)
  811. {
  812. error++;
  813. EA::UnitTest::Report("\nMismatch(G): %s/%s (Halt if > 0/section G)", str, list24DSL[i]);
  814. }
  815. }
  816. EATEST_VERIFY(error == 0);
  817. }
  818. { // Regression for user-reported bug.
  819. const size_t kBufferSize = 2048;
  820. char format[16];
  821. EA::StdC::Snprintf(format, sizeof(format), "%%.%us%%c123", kBufferSize - 1);
  822. EATEST_VERIFY(Strcmp(format, "%.2047s%c123") == 0);
  823. auto unique_buffer = eastl::make_unique<char8_t[]>(kBufferSize);
  824. auto unique_expect = eastl::make_unique<char8_t[]>(kBufferSize + 16);
  825. auto unique_actual = eastl::make_unique<char8_t[]>(kBufferSize + 16);
  826. char8_t* buffer = unique_buffer.get();
  827. char8_t* expectedOutput = unique_expect.get();
  828. char8_t* actualOutput = unique_actual.get();
  829. memset(buffer, '?', kBufferSize);
  830. buffer[kBufferSize - 1] = 0;
  831. char c = 'A';
  832. EA::StdC::Snprintf(actualOutput, kBufferSize + 16, format, buffer, c);
  833. memset(expectedOutput, '?', 2047);
  834. expectedOutput[2047] = 0;
  835. strcat(expectedOutput, "A123");
  836. EATEST_VERIFY(Strcmp(actualOutput, expectedOutput) == 0);
  837. }
  838. {
  839. static const int kSourceSize = 1024 * 5;
  840. static const int kOutputSize = kSourceSize + 100;
  841. char16_t value[kSourceSize];
  842. char8_t destination[kOutputSize];
  843. char8_t comparison[kOutputSize];
  844. for(int i = 0; i < kSourceSize - 1; ++i)
  845. {
  846. value[i] = '0' + (i % 10);
  847. comparison[i] = '0' + (i % 10);
  848. }
  849. value[kSourceSize - 1] = 0;
  850. comparison[kSourceSize - 1] = 0;
  851. EA::StdC::Snprintf(destination, kOutputSize, "%I16s", value);
  852. EATEST_VERIFY(Strcmp(destination, comparison) == 0);
  853. EA::StdC::Snprintf(destination, kOutputSize, "%.10I16s", value);
  854. EATEST_VERIFY(Strcmp(destination, "0123456789") == 0);
  855. }
  856. /* Copied from rwstdc but not completed.
  857. // Compare with Sprintf
  858. {
  859. char8_t buffer1[128];
  860. char8_t buffer2[128];
  861. char8_t* test = "test %d %5.2f %s \n \t\t\\\\ %X";
  862. Sprintf(buffer1, test, -3923, 0.38293, "test", 4568);
  863. Snprintf(buffer2, 128, test, -3923, 0.38293, "test", 4568);
  864. EATEST_VERIFY(strcmp(buffer1, buffer2) == 0);
  865. }
  866. // Compare with standard sprintf
  867. {
  868. char8_t buffer1[128];
  869. char8_t buffer2[128];
  870. char* test = "test %d %5.2f %s \n \t\t\\\\ %X";
  871. sprintf(buffer1, test, -3923, 0.38293, "test", 4568);
  872. Snprintf(buffer2, 128, test, -3923, 0.38293, "test", 4568);
  873. EATEST_VERIFY(strcmp(buffer1, buffer2) == 0);
  874. }
  875. {
  876. float sum = 1035.32432f;
  877. float ave = 34.3f;
  878. float min = 343.34f;
  879. float max = 576.3f;
  880. char test[] = "NumberEvents: %5d, TotalDuration: %12.4f ms\nAve: %12.4f ms = %6.2f Hz\nMin: %12.4f ms = %6.2f Hz\nMax: %12.4f ms = %6.2f Hz\n";
  881. int res = Snprintf(snprintfString, bufferLength,
  882. "NumberEvents: %5d, TotalDuration: %12.4f ms\nAve: %12.4f ms = %6.2f Hz\nMin: %12.4f ms = %6.2f Hz\nMax: %12.4f ms = %6.2f Hz\n",
  883. bufferLength, sum, ave, 1000.0f/ave, min, 1000.0f/min, max, 1000.0f/max);
  884. // Full String
  885. char testString[384];
  886. sprintf(testString, test, 384, sum, ave, 1000.0f/ave, min, 1000.0f/min, max, 1000.0f/max);
  887. EATEST_VERIFY(strcmp(snprintfString, testString) == 0);
  888. // Truncated string.
  889. const size_t origStringSize = strlen(snprintfString);
  890. for(size_t i = 0; i < origStringSize; i++)
  891. {
  892. res = Snprintf(snprintfString, i, test, 384, sum, ave, 1000.0f/ave, min, 1000.0f/min, max, 1000.0f/max);
  893. EATEST_VERIFY(res == origStringSize);
  894. }
  895. }
  896. {
  897. int testData = 123;
  898. char* test = "'%d' '%10d' '%-10d'";
  899. sprintf(expectedString, test, testData, testData, testData);
  900. Snprintf(snprintfString, bufferLength, test, testData, testData, testData);
  901. EATEST_VERIFY(strcmp(expectedString, snprintfString) == 0);
  902. }
  903. */
  904. return nErrorCount;
  905. }
  906. static int TestSprintf16(int unused = 0, ...)
  907. {
  908. using namespace EA::StdC;
  909. int nErrorCount(0);
  910. // int Snprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  911. {
  912. char16_t sn18[128];
  913. Snprintf(sn18, 128, EA_CHAR16("%5s%-4d%03i"), EA_WCHAR("abc"), -12, 3);
  914. EATEST_VERIFY(!Strcmp(EA_CHAR16(" abc-12 003"), sn18));
  915. Snprintf(sn18, 128, EA_CHAR16("%.2f"), 3.1415);
  916. EATEST_VERIFY(!Strcmp(EA_CHAR16("3.14"), sn18));
  917. }
  918. // int Vsnprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  919. {
  920. char16_t sn18[128];
  921. TestCRTVsnprintf(sn18, 128, EA_CHAR16("%5s%-5d%04i"), EA_WCHAR("abc"), -12, 3);
  922. EATEST_VERIFY(!Strcmp(EA_CHAR16(" abc-12 0003"), sn18));
  923. TestCRTVsnprintf(sn18, 128, EA_CHAR16("%.2f"), 3.1415);
  924. EATEST_VERIFY(!Strcmp(EA_CHAR16("3.14"), sn18));
  925. }
  926. #if EASTDC_VSNPRINTF8_ENABLED
  927. {
  928. char16_t sn18[128];
  929. TestCRTVsnprintf16(sn18, 128, EA_CHAR16("%5s%-5d%04i"), EA_WCHAR("abc"), -12, 3);
  930. EATEST_VERIFY(!Strcmp(EA_CHAR16(" abc-12 0003"), sn18));
  931. TestCRTVsnprintf16(sn18, 128, EA_CHAR16("%.2f"), 3.1415);
  932. EATEST_VERIFY(!Strcmp(EA_CHAR16("3.14"), sn18));
  933. }
  934. #endif
  935. // int Vscprintf(const char_t* pFormat, va_list arguments);
  936. {
  937. va_list arguments;
  938. va_start(arguments, unused);
  939. int result = Vscprintf(EA_CHAR16("abc"), arguments);
  940. EATEST_VERIFY(result == 3);
  941. va_end(arguments);
  942. }
  943. // template <typename String>
  944. // int StringVcprintf(String& s, const char8_t* EA_RESTRICT pFormat, va_list arguments)
  945. {
  946. va_list arguments;
  947. va_start(arguments, unused);
  948. eastl::string16 s16;
  949. int result = StringVcprintf(s16, EA_CHAR16("hello"), arguments);
  950. EATEST_VERIFY((result == 5) && (s16 == EA_CHAR16("hello")));
  951. va_end(arguments);
  952. }
  953. // template <typename String>
  954. // int StringPrintf(String& s, const typename String::value_type* EA_RESTRICT pFormat, ...)
  955. {
  956. eastl::string16 s16;
  957. int result = StringPrintf(s16, EA_CHAR16("%s"), EA_WCHAR("hello"));
  958. EATEST_VERIFY((result == 5) && (s16 == EA_CHAR16("hello")));
  959. }
  960. {
  961. char16_t buffer[128];
  962. const int kHexValue = 0x12;
  963. Sprintf(buffer, EA_CHAR16("%.4x"), kHexValue);
  964. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  965. Sprintf(buffer, EA_CHAR16("%04x"), kHexValue);
  966. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  967. Sprintf(buffer, EA_CHAR16("%4.4x"), kHexValue);
  968. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  969. Sprintf(buffer, EA_CHAR16("%04.4x"), kHexValue);
  970. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  971. Sprintf(buffer, EA_CHAR16("%4.3x"), kHexValue);
  972. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 012")) == 0);
  973. Sprintf(buffer, EA_CHAR16("%04.3x"), kHexValue);
  974. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 012")) == 0);
  975. Sprintf(buffer, EA_CHAR16("%.*x"), 4, kHexValue);
  976. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  977. Sprintf(buffer, EA_CHAR16("%0*x"), 4, kHexValue);
  978. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  979. Sprintf(buffer, EA_CHAR16("%*.*x"), 4, 4, kHexValue);
  980. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  981. Sprintf(buffer, EA_CHAR16("%0*.*x"), 4, 4, kHexValue);
  982. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0012")) == 0);
  983. }
  984. {
  985. char16_t buffer[128];
  986. Sprintf(buffer, EA_CHAR16("decimal negative: \"%d\"\n"), -2345);
  987. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("decimal negative: \"-2345\"\n")) == 0);
  988. Sprintf(buffer, EA_CHAR16("octal negative: \"%o\"\n"), -2345);
  989. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  990. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("octal negative: \"37777773327\"\n")) == 0);
  991. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  992. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("octal negative: \"1777777777777777773327\"\n")) == 0);
  993. Sprintf(buffer, EA_CHAR16("hex negative: \"%x\"\n"), -2345);
  994. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  995. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("hex negative: \"fffff6d7\"\n")) == 0);
  996. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  997. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("hex negative: \"fffffffffffff6d7\"\n")) == 0);
  998. Sprintf(buffer, EA_CHAR16("long decimal number: \"%ld\"\n"), -123456L);
  999. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("long decimal number: \"-123456\"\n")) == 0);
  1000. Sprintf(buffer, EA_CHAR16("long octal negative: \"%lo\"\n"), -2345L);
  1001. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1002. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("long octal negative: \"37777773327\"\n")) == 0);
  1003. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1004. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("long octal negative: \"1777777777777777773327\"\n")) == 0);
  1005. Sprintf(buffer, EA_CHAR16("long unsigned decimal number: \"%lu\"\n"), -123456L);
  1006. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1007. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("long unsigned decimal number: \"4294843840\"\n")) == 0);
  1008. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1009. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("long unsigned decimal number: \"18446744073709428160\"\n")) == 0);
  1010. Sprintf(buffer, EA_CHAR16("zero-padded LDN: \"%010ld\"\n"), -123456L);
  1011. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("zero-padded LDN: \"-000123456\"\n")) == 0);
  1012. Sprintf(buffer, EA_CHAR16("left-adjusted ZLDN: \"%-010ld\"\n"), -123456L);
  1013. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("left-adjusted ZLDN: \"-123456 \"\n")) == 0);
  1014. Sprintf(buffer, EA_CHAR16("space-padded LDN: \"%10ld\"\n"), -123456L);
  1015. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("space-padded LDN: \" -123456\"\n")) == 0);
  1016. Sprintf(buffer, EA_CHAR16("left-adjusted SLDN: \"%-10ld\"\n"), -123456L);
  1017. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("left-adjusted SLDN: \"-123456 \"\n")) == 0);
  1018. }
  1019. {
  1020. char16_t buffer[1024];
  1021. wchar_t str1[64]; Strlcpy(str1, EA_WCHAR("abc de"), EAArrayCount(str1)); // Can't do str1[64] = EA_CHAR16("abc de") because some compilers don't support 16 bit string literals.
  1022. wchar_t str2[64]; Strlcpy(str2, EA_WCHAR("abd def ghi jkl mno pqr stu vwz yz."), EAArrayCount(str2));
  1023. // The C99 standard specifies that leading zeros only put zeroes in front of numerical types. Spaces for others.
  1024. Sprintf(buffer, EA_CHAR16("zero-padded string: \"%010s\"\n"), str1);
  1025. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("zero-padded string: \" abc de\"\n")) == 0); // VC++ fails this, as it puts zeroes in front.
  1026. Sprintf(buffer, EA_CHAR16("left-adjusted Z string: \"%-010s\"\n"), str1);
  1027. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("left-adjusted Z string: \"abc de \"\n")) == 0);
  1028. Sprintf(buffer, EA_CHAR16("space-padded string: \"%10s\"\n"), str1);
  1029. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("space-padded string: \" abc de\"\n")) == 0);
  1030. Sprintf(buffer, EA_CHAR16("left-adjusted S string: \"%-10s\"\n"), str1);
  1031. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("left-adjusted S string: \"abc de \"\n")) == 0);
  1032. Sprintf(buffer, EA_CHAR16("limited string: \"%.22s\"\n"), str2);
  1033. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("limited string: \"abd def ghi jkl mno pq\"\n")) == 0);
  1034. Sprintf(buffer, EA_CHAR16("null string: \"%s\"\n"), (wchar_t*)NULL);
  1035. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("null string: \"(null)\"\n")) == 0);
  1036. Sprintf(buffer, EA_CHAR16("%10s\n"), (wchar_t*)NULL);
  1037. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" (null)\n")) == 0);
  1038. Sprintf(buffer, EA_CHAR16("%-10s\n"), (wchar_t*)NULL);
  1039. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("(null) \n")) == 0);
  1040. Sprintf(buffer, EA_CHAR16("%*s%*s%*s"), -1, EA_WCHAR("one"), -20, EA_WCHAR("two"), -30, EA_WCHAR("three"));
  1041. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("onetwo three ")) == 0);
  1042. int i;
  1043. memset(buffer, '_', sizeof(buffer));
  1044. Sprintf(buffer, EA_CHAR16("x%1000ls"), EA_WCHAR(" "));
  1045. EATEST_VERIFY(buffer[0] == 'x');
  1046. for(i = 0; i < 1000; i++)
  1047. {
  1048. if(buffer[1 + i] != ' ')
  1049. break;
  1050. }
  1051. if(i != 1000)
  1052. EATEST_VERIFY(i == 1000);
  1053. else
  1054. EATEST_VERIFY(buffer[1 + 1000] == EA_CHAR16('\0'));
  1055. }
  1056. { // String tests
  1057. // We accept %hc, %c, %lc, %I8c, %I16c, %I32c (regular, regular, wide, char8_t, char16_t, char32_t)
  1058. // We accept %hC, %C, %lC, %I8C, %I16C, %I32C (regular, wide, wide, char8_t, char16_t, char32_t)
  1059. // We accept %hs, %s, %ls, %I8s, %I16s, %I32s (regular, regular, wide, char8_t, char16_t, char32_t)
  1060. // We accept %hS, %S, %lS, %I8s, %I16s, %I32s (regular, wide, wide, char8_t, char16_t, char32_t)
  1061. char16_t buffer[32];
  1062. char8_t dStr8[2] = { 'd', 0 };
  1063. char16_t eStr16[2] = { 'e', 0 };
  1064. char32_t fStr32[2] = { 'f', 0 };
  1065. #if EASPRINTF_MS_STYLE_S_FORMAT // Microsoft style means that the meanings of S and s are reversed for non-char8_t Sprintf.
  1066. Sprintf(buffer, EA_CHAR16("%hc %c %lc %I8c %I16c %I32c"), 'a', EA_WCHAR('b'), EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1067. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1068. Sprintf(buffer, EA_CHAR16("%hC %C %lC %I8C %I16C %I32C"), 'a', 'b', EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1069. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1070. Sprintf(buffer, EA_CHAR16("%hs %s %ls %I8s %I16s %I32s"), "a", EA_WCHAR("b"), EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1071. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1072. Sprintf(buffer, EA_CHAR16("%hS %S %lS %I8S %I16S %I32S"), "a", "b", EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1073. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1074. #else
  1075. Sprintf(buffer, EA_CHAR16("%hc %c %lc %I8c %I16c %I32c"), 'a', 'b', EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1076. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1077. Sprintf(buffer, EA_CHAR16("%hC %C %lC %I8C %I16C %I32C"), 'a', EA_WCHAR('b'), EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1078. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f)") == 0);
  1079. Sprintf(buffer, EA_CHAR16("%hs %s %ls %I8s %I16s %I32s"), "a", "b", EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1080. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1081. Sprintf(buffer, EA_CHAR16("%hS %S %lS %I8S %I16S %I32S"), "a", EA_WCHAR("b"), EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1082. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("a b c d e f")) == 0);
  1083. #endif
  1084. }
  1085. {
  1086. char16_t buffer[1024];
  1087. int i;
  1088. Sprintf(buffer, EA_CHAR16("e-style >= 1: \"%e\"\n"), 12.34);
  1089. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("e-style >= 1: \"1.234000e+01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1090. Sprintf(buffer, EA_CHAR16("e-style >= .1: \"%e\"\n"), 0.1234);
  1091. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("e-style >= .1: \"1.234000e-01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1092. Sprintf(buffer, EA_CHAR16("e-style < .1: \"%e\"\n"), 0.001234);
  1093. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("e-style < .1: \"1.234000e-03\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1094. Sprintf(buffer, EA_CHAR16("e-style big: \"%.60e\"\n"), 1e20);
  1095. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("e-style big: \"1.000000000000000000000000000000000000000000000000000000000000e+20\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1096. Sprintf(buffer, EA_CHAR16("e-style == .1: \"%e\"\n"), 0.1);
  1097. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("e-style == .1: \"1.000000e-01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1098. Sprintf(buffer, EA_CHAR16("f-style >= 1: \"%f\"\n"), 12.34);
  1099. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("f-style >= 1: \"12.340000\"\n")) == 0);
  1100. Sprintf(buffer, EA_CHAR16("f-style >= .1: \"%f\"\n"), 0.1234);
  1101. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("f-style >= .1: \"0.123400\"\n")) == 0);
  1102. Sprintf(buffer, EA_CHAR16("f-style < .1: \"%f\"\n"), 0.001234);
  1103. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("f-style < .1: \"0.001234\"\n")) == 0);
  1104. Sprintf(buffer, EA_CHAR16("g-style >= 1: \"%g\"\n"), 12.34);
  1105. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("g-style >= 1: \"12.34\"\n")) == 0);
  1106. Sprintf(buffer, EA_CHAR16("g-style >= .1: \"%g\"\n"), 0.1234);
  1107. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("g-style >= .1: \"0.1234\"\n")) == 0);
  1108. Sprintf(buffer, EA_CHAR16("g-style < .1: \"%g\"\n"), 0.001234);
  1109. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("g-style < .1: \"0.001234\"\n")) == 0);
  1110. Sprintf(buffer, EA_CHAR16("g-style big: \"%.60g\"\n"), 1e20);
  1111. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("g-style big: \"100000000000000000000\"\n")) == 0);
  1112. //Sprintf(buffer, EA_CHAR16("%#.4g\n"), 0.0); // The C99 committee has decided in a defect analysis that this is how it should work.
  1113. //EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0\n")) == 0);
  1114. Sprintf(buffer, EA_CHAR16(" %6.5f\n"), .099999999860301614);
  1115. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 0.10000\n")) == 0);
  1116. Sprintf(buffer, EA_CHAR16(" %6.5f\n"), .1);
  1117. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 0.10000\n")) == 0);
  1118. Sprintf(buffer, EA_CHAR16("x%5.4fx\n"), .5);
  1119. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("x0.5000x\n")) == 0);
  1120. Sprintf(buffer, EA_CHAR16("%#03x\n"), 1);
  1121. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("0x1\n")) == 0);
  1122. memset(buffer, '_', sizeof(buffer));
  1123. Sprintf(buffer, EA_CHAR16("%.300f"), 1.0);
  1124. EATEST_VERIFY((buffer[0] == '1') && (buffer[1] == '.'));
  1125. for(i = 0; i < 300; i++)
  1126. {
  1127. if(buffer[2 + i] != '0')
  1128. break;
  1129. }
  1130. if(i != 300)
  1131. EATEST_VERIFY(i == 300);
  1132. else
  1133. EATEST_VERIFY(buffer[2 + 300] == EA_CHAR16('\0'));
  1134. // Operations on FLT_MIN are undefined on Neon
  1135. double d = static_cast<double>(FLT_MIN); // We are intentionally using FLT_MIN and not DBL_MIN.
  1136. d /= 2.0;
  1137. Sprintf(buffer, EA_CHAR16("%.17e"), d); // It should be something like 5.87747175411143___e-39 where count and values of the _ digits vary by hardware.
  1138. buffer[16] = buffer[17] = buffer[18] = '_'; // Replace the uncertain digits with '_' characters, as they are system-dependent.
  1139. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("5.87747175411143___e-39")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1140. Sprintf(buffer, EA_CHAR16("%15.5e\n"), 4.9406564584124654e-307);
  1141. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 4.94066e-307\n")) == 0);
  1142. }
  1143. {
  1144. char16_t buffer[256];
  1145. const char16_t* pExpected;
  1146. // VC++ sprintf would fail these tests, as the Standard says to print no more
  1147. // than 2 unless necessary, yet VC++ sprintf prints 3 digits exponents.
  1148. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 0.0, 0.0, 0.0);
  1149. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("| 0.0000| 0.0000e+00| 0|")) == 0);
  1150. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 1.0, 1.0, 1.0);
  1151. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("| 1.0000| 1.0000e+00| 1|")) == 0);
  1152. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), -1.0, -1.0, -1.0);
  1153. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("| -1.0000| -1.0000e+00| -1|")) == 0);
  1154. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 100.0, 100.0, 100.0);
  1155. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("| 100.0000| 1.0000e+02| 100|")) == 0);
  1156. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 1000.0, 1000.0, 1000.0);
  1157. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("| 1000.0000| 1.0000e+03| 1000|")) == 0);
  1158. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 10000.0, 10000.0, 10000.0);
  1159. EATEST_VERIFY(Strcmp(buffer,EA_CHAR16("| 10000.0000| 1.0000e+04| 1e+04|")) == 0);
  1160. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 12346.0, 12346.0, 12346.0);
  1161. pExpected = EA_CHAR16("| 12346.0000| 1.2346e+04| 1.235e+04|");
  1162. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1163. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 100000.0, 100000.0, 100000.0);
  1164. pExpected = EA_CHAR16("| 100000.0000| 1.0000e+05| 1e+05|");
  1165. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1166. Sprintf(buffer, EA_CHAR16("|%12.4f|%12.4e|%12.4g|"), 123467.0, 123467.0, 123467.0);
  1167. pExpected = EA_CHAR16("| 123467.0000| 1.2347e+05| 1.235e+05|");
  1168. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1169. }
  1170. {
  1171. char16_t buffer[256];
  1172. // Verify that snprintf follows the C99 convention of returning the number of characters
  1173. // required. This is as opposed to the non-standard way that some libraries just return
  1174. // -1 if the buffer isn't big enough.
  1175. const int kBuf1Capacity = 20;
  1176. wchar_t buf1[kBuf1Capacity];
  1177. int n1 = Snprintf(buf1, kBuf1Capacity, EA_WCHAR("%30I16s"), EA_CHAR16("foo"));
  1178. Sprintf(buffer, EA_CHAR16("snprintf(\"%%30s\", \"foo\") == %d, \"%.*s\"\n"), n1, kBuf1Capacity, buf1);
  1179. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("snprintf(\"%30s\", \"foo\") == 30, \" \"\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1180. const int kBuf2Capacity = 512;
  1181. char16_t buf2[kBuf2Capacity];
  1182. int n2 = Snprintf(buf2, kBuf2Capacity, EA_CHAR16("%.1000u"), 10);
  1183. Sprintf(buffer, EA_CHAR16("snprintf(\"%%.1000u\", 10) == %d\n"), n2);
  1184. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("snprintf(\"%.1000u\", 10) == 1000\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1185. const int kBuf3Capacity = 512;
  1186. char16_t buf3[kBuf3Capacity];
  1187. char16_t* pString = new char16_t[100000];
  1188. memset(pString, '_', 100000 * sizeof(char16_t));
  1189. pString[100000 - 1] = 0;
  1190. int n3 = Snprintf(buf3, kBuf2Capacity, EA_CHAR16("%I16s"), pString);
  1191. Sprintf(buffer, EA_CHAR16("snprintf(\"%%s\", pString) == %d\n"), n3);
  1192. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("snprintf(\"%s\", pString) == 99999\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1193. delete[] pString;
  1194. int n4 = Snprintf(NULL, 0, EA_CHAR16("%I16s"), EA_CHAR16("abc"));
  1195. Sprintf(buffer, EA_CHAR16("snprintf(NULL, \"abc\") == %d\n"), n4);
  1196. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("snprintf(NULL, \"abc\") == 3\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1197. int n5 = Snprintf(NULL, 100, EA_CHAR16("%I16s"), EA_CHAR16("abc"));
  1198. Sprintf(buffer, EA_CHAR16("snprintf(NULL, \"abc\") == %d\n"), n5);
  1199. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("snprintf(NULL, \"abc\") == 3\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1200. }
  1201. {
  1202. char16_t buffer[16][256];
  1203. int n = 0, i, j, k, m;
  1204. for(i = 0; i < 2; i++)
  1205. {
  1206. for(j = 0; j < 2; j++)
  1207. {
  1208. for(k = 0; k < 2; k++)
  1209. {
  1210. for(m = 0; m < 2; m++)
  1211. {
  1212. wchar_t prefix[7];
  1213. char16_t format[128];
  1214. Strcpy(prefix, EA_WCHAR("%"));
  1215. if(i == 0)
  1216. Strcat(prefix, EA_WCHAR("-"));
  1217. if(j == 0)
  1218. Strcat(prefix, EA_WCHAR("+"));
  1219. if(k == 0)
  1220. Strcat(prefix, EA_WCHAR("#"));
  1221. if(m == 0)
  1222. Strcat(prefix, EA_WCHAR("0"));
  1223. #define DEC -123
  1224. #define INT 255
  1225. #define UNS (~0)
  1226. Sprintf(format, EA_CHAR16("%%5s |%s6d |%s6o |%s6x |%s6X |%s6u |"), prefix, prefix, prefix, prefix, prefix);
  1227. Sprintf(buffer[n], format, prefix, DEC, INT, INT, INT, UNS);
  1228. n++;
  1229. }
  1230. }
  1231. }
  1232. }
  1233. EATEST_VERIFY(Strcmp(buffer[ 0], EA_CHAR16("%-+#0 |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1234. EATEST_VERIFY(Strcmp(buffer[ 1], EA_CHAR16(" %-+# |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1235. EATEST_VERIFY(Strcmp(buffer[ 2], EA_CHAR16(" %-+0 |-123 |377 |ff |FF |4294967295 |")) == 0);
  1236. EATEST_VERIFY(Strcmp(buffer[ 3], EA_CHAR16(" %-+ |-123 |377 |ff |FF |4294967295 |")) == 0);
  1237. EATEST_VERIFY(Strcmp(buffer[ 4], EA_CHAR16(" %-#0 |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1238. EATEST_VERIFY(Strcmp(buffer[ 5], EA_CHAR16(" %-# |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1239. EATEST_VERIFY(Strcmp(buffer[ 6], EA_CHAR16(" %-0 |-123 |377 |ff |FF |4294967295 |")) == 0);
  1240. EATEST_VERIFY(Strcmp(buffer[ 7], EA_CHAR16(" %- |-123 |377 |ff |FF |4294967295 |")) == 0);
  1241. EATEST_VERIFY(Strcmp(buffer[ 8], EA_CHAR16(" %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |")) == 0);
  1242. EATEST_VERIFY(Strcmp(buffer[ 9], EA_CHAR16(" %+# | -123 | 0377 | 0xff | 0XFF |4294967295 |")) == 0);
  1243. EATEST_VERIFY(Strcmp(buffer[10], EA_CHAR16(" %+0 |-00123 |000377 |0000ff |0000FF |4294967295 |")) == 0);
  1244. EATEST_VERIFY(Strcmp(buffer[11], EA_CHAR16(" %+ | -123 | 377 | ff | FF |4294967295 |")) == 0);
  1245. EATEST_VERIFY(Strcmp(buffer[12], EA_CHAR16(" %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |")) == 0);
  1246. EATEST_VERIFY(Strcmp(buffer[13], EA_CHAR16(" %# | -123 | 0377 | 0xff | 0XFF |4294967295 |")) == 0);
  1247. EATEST_VERIFY(Strcmp(buffer[14], EA_CHAR16(" %0 |-00123 |000377 |0000ff |0000FF |4294967295 |")) == 0);
  1248. EATEST_VERIFY(Strcmp(buffer[15], EA_CHAR16(" % | -123 | 377 | ff | FF |4294967295 |")) == 0);
  1249. }
  1250. {
  1251. char16_t buffer[256];
  1252. const char16_t* pExpected;
  1253. Sprintf(buffer, EA_CHAR16("%e"), 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1254. pExpected = EA_CHAR16("1.234568e+06");
  1255. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1256. Sprintf(buffer, EA_CHAR16("%f"), 1234567.8);
  1257. pExpected = EA_CHAR16("1234567.800000");
  1258. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1259. Sprintf(buffer, EA_CHAR16("%g"), 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1260. pExpected = EA_CHAR16("1.23457e+06");
  1261. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1262. Sprintf(buffer, EA_CHAR16("%g"), 123.456);
  1263. pExpected = EA_CHAR16("123.456");
  1264. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1265. Sprintf(buffer, EA_CHAR16("%g"), 1000000.0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1266. pExpected = EA_CHAR16("1e+06");
  1267. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1268. Sprintf(buffer, EA_CHAR16("%g"), 10.0);
  1269. pExpected = EA_CHAR16("10");
  1270. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1271. Sprintf(buffer, EA_CHAR16("%g"), 0.02);
  1272. pExpected = EA_CHAR16("0.02");
  1273. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1274. }
  1275. { // Test the ' extension, that prints numbers with a thousands separator.
  1276. char16_t buffer[64];
  1277. const char16_t* pExpected;
  1278. Sprintf(buffer, EA_CHAR16("%'u"), 123456789);
  1279. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("123,456,789")) == 0);
  1280. Sprintf(buffer, EA_CHAR16("%'d"), -123456789);
  1281. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("-123,456,789")) == 0);
  1282. Sprintf(buffer, EA_CHAR16("%'I8u"), 123);
  1283. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("123")) == 0);
  1284. Sprintf(buffer, EA_CHAR16("%'I16u"), 12345);
  1285. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("12,345")) == 0);
  1286. Sprintf(buffer, EA_CHAR16("%'I16d"), -12345);
  1287. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("-12,345")) == 0);
  1288. Sprintf(buffer, EA_CHAR16("%'I32u"), 12345678);
  1289. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("12,345,678")) == 0);
  1290. Sprintf(buffer, EA_CHAR16("%'I32d"), -12345678);
  1291. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("-12,345,678")) == 0);
  1292. Sprintf(buffer, EA_CHAR16("%20I32d"), -12345678);
  1293. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" -12345678")) == 0);
  1294. Sprintf(buffer, EA_CHAR16("%'20I32d"), -12345678); // Verify that the , chars count towards the field width.
  1295. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" -12,345,678")) == 0);
  1296. Sprintf(buffer, EA_CHAR16("%'I32x"), 0x12345678); // ' has no effect on hex formatting.
  1297. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("12345678")) == 0);
  1298. Sprintf(buffer, EA_CHAR16("%'I64u"), UINT64_C(1234999995678));
  1299. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("1,234,999,995,678")) == 0);
  1300. Sprintf(buffer, EA_CHAR16("%'I64d"), INT64_C(-1234599999678));
  1301. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("-1,234,599,999,678")) == 0);
  1302. Sprintf(buffer, EA_CHAR16("%'I64x"), UINT64_C(0x1234567812345678)); // ' has no effect on hex formatting.
  1303. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("1234567812345678")) == 0);
  1304. Sprintf(buffer, EA_CHAR16("%'f"), 123456.234);
  1305. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("123,456.234000")) == 0);
  1306. Sprintf(buffer, EA_CHAR16("%'e"), 1234567.8); // ' has no effect on %e formatting.
  1307. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("1.234568e+06")) == 0);
  1308. Sprintf(buffer, EA_CHAR16("%'g"), 1234.54); // In some cases %g acts like %f.
  1309. pExpected = EA_CHAR16("1,234.54");
  1310. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1311. Sprintf(buffer, EA_CHAR16("%'g"), 1234567.8); // In some cases %g acts like %f.
  1312. pExpected = EA_CHAR16("1.23457e+06");
  1313. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1314. }
  1315. {
  1316. char16_t buffer[256];
  1317. Sprintf(buffer, EA_CHAR16("%hhu"), UCHAR_MAX + 2);
  1318. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("1")) == 0); // VC++ fails this, as it doesn't implement the C99 standard %hh modifier.
  1319. Sprintf(buffer, EA_CHAR16("%hu"), USHRT_MAX + 2);
  1320. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("1")) == 0);
  1321. }
  1322. {
  1323. char16_t buffer[128];
  1324. const char16_t* pExpected;
  1325. Sprintf(buffer, EA_CHAR16("%5.s"), EA_WCHAR("xyz"));
  1326. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" ")) == 0);
  1327. Sprintf(buffer, EA_CHAR16("%5.f"), 33.3);
  1328. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 33")) == 0);
  1329. Sprintf(buffer, EA_CHAR16("%8.e"), 33.3e7); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1330. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 3e+08")) == 0);
  1331. Sprintf(buffer, EA_CHAR16("%8.E"), 33.3e7); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1332. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 3E+08")) == 0);
  1333. Sprintf(buffer, EA_CHAR16("%.g"), 33.3); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1334. pExpected = EA_CHAR16("3e+01");
  1335. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1336. Sprintf(buffer, EA_CHAR16("%.G"), 33.3); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1337. pExpected = EA_CHAR16("3E+01");
  1338. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I16s\n Actual: %I16s", pExpected, buffer);
  1339. }
  1340. {
  1341. char16_t buffer[128];
  1342. int precision;
  1343. precision = 0;
  1344. Sprintf(buffer, EA_CHAR16("%.*g"), precision, 3.3);
  1345. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("3")) == 0);
  1346. precision = 0;
  1347. Sprintf(buffer, EA_CHAR16("%.*G"), precision, 3.3);
  1348. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16("3")) == 0);
  1349. precision = 0;
  1350. Sprintf(buffer, EA_CHAR16("%7.*G"), precision, 3.33);
  1351. EATEST_VERIFY(Strcmp(buffer,EA_CHAR16(" 3")) == 0);
  1352. precision = 3;
  1353. Sprintf(buffer, EA_CHAR16("%04.*o"), precision, 33);
  1354. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 041")) == 0);
  1355. precision = 7;
  1356. Sprintf(buffer, EA_CHAR16("%09.*u"), precision, 33);
  1357. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 0000033")) == 0);
  1358. precision = 3;
  1359. Sprintf(buffer, EA_CHAR16("%04.*x"), precision, 33);
  1360. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 021")) == 0);
  1361. precision = 3;
  1362. Sprintf(buffer, EA_CHAR16("%04.*X"), precision, 33);
  1363. EATEST_VERIFY(Strcmp(buffer, EA_CHAR16(" 021")) == 0);
  1364. }
  1365. {
  1366. static const int kSourceSize = 1024 * 5;
  1367. static const int kOutputSize = kSourceSize + 100;
  1368. char8_t value[kSourceSize];
  1369. char16_t destination[kOutputSize];
  1370. char16_t comparison[kOutputSize];
  1371. for(int i = 0; i < kSourceSize - 1; ++i)
  1372. {
  1373. value[i] = '0' + (i % 10);
  1374. comparison[i] = '0' + (i % 10);
  1375. }
  1376. value[kSourceSize - 1] = 0;
  1377. comparison[kSourceSize - 1] = 0;
  1378. EA::StdC::Snprintf(destination, kOutputSize, EA_CHAR16("%I8s"), value);
  1379. EATEST_VERIFY(Strcmp(destination, comparison) == 0);
  1380. EA::StdC::Snprintf(destination, kOutputSize, EA_CHAR16("%.10I8s"), value);
  1381. EATEST_VERIFY(Strcmp(destination, EA_CHAR16("0123456789")) == 0);
  1382. }
  1383. return nErrorCount;
  1384. }
  1385. static int TestSprintf32(int unused = 0, ...)
  1386. {
  1387. using namespace EA::StdC;
  1388. int nErrorCount(0);
  1389. // int Snprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  1390. {
  1391. char32_t sn18[32];
  1392. Snprintf(sn18, EAArrayCount(sn18), EA_CHAR32("%5s%-4d%03i"), EA_WCHAR("abc"), -12, 3);
  1393. EATEST_VERIFY(!Strcmp(EA_CHAR32(" abc-12 003"), sn18));
  1394. Snprintf(sn18, EAArrayCount(sn18), EA_CHAR32("%.2f"), 3.1415);
  1395. EATEST_VERIFY(!Strcmp(EA_CHAR32("3.14"), sn18));
  1396. }
  1397. // int Vsnprintf(char_t* pDestination, size_t n, const char_t* pFormat, ...);
  1398. {
  1399. char32_t sn18[32];
  1400. TestCRTVsnprintf(sn18, EAArrayCount(sn18), EA_CHAR32("%5s%-5d%04i"), EA_WCHAR("abc"), -12, 3);
  1401. EATEST_VERIFY(!Strcmp(EA_CHAR32(" abc-12 0003"), sn18));
  1402. TestCRTVsnprintf(sn18, EAArrayCount(sn18), EA_CHAR32("%.2f"), 3.1415);
  1403. EATEST_VERIFY(!Strcmp(EA_CHAR32("3.14"), sn18));
  1404. }
  1405. #if EASTDC_VSNPRINTF8_ENABLED
  1406. {
  1407. char32_t sn18[32];
  1408. TestCRTVsnprintf32(sn18, EAArrayCount(sn18), EA_CHAR32("%5s%-5d%04i"), EA_WCHAR("abc"), -12, 3);
  1409. EATEST_VERIFY(!Strcmp(EA_CHAR32(" abc-12 0003"), sn18));
  1410. TestCRTVsnprintf32(sn18, EAArrayCount(sn18), EA_CHAR32("%.2f"), 3.1415);
  1411. EATEST_VERIFY(!Strcmp(EA_CHAR32("3.14"), sn18));
  1412. }
  1413. #endif
  1414. // int Vscprintf(const char_t* pFormat, va_list arguments);
  1415. {
  1416. va_list arguments;
  1417. va_start(arguments, unused);
  1418. int result = Vscprintf(EA_CHAR32("abc"), arguments);
  1419. EATEST_VERIFY(result == 3);
  1420. va_end(arguments);
  1421. }
  1422. // template <typename String>
  1423. // int StringVcprintf(String& s, const char8_t* EA_RESTRICT pFormat, va_list arguments)
  1424. {
  1425. va_list arguments;
  1426. va_start(arguments, unused);
  1427. eastl::string32 s32;
  1428. int result = StringVcprintf(s32, EA_CHAR32("hello"), arguments);
  1429. EATEST_VERIFY((result == 5) && (s32 == EA_CHAR32("hello")));
  1430. va_end(arguments);
  1431. }
  1432. // template <typename String>
  1433. // int StringPrintf(String& s, const typename String::value_type* EA_RESTRICT pFormat, ...)
  1434. {
  1435. eastl::string32 s32;
  1436. int result = StringPrintf(s32, EA_CHAR32("%s"), EA_WCHAR("hello"));
  1437. EATEST_VERIFY((result == 5) && (s32 == EA_CHAR32("hello")));
  1438. }
  1439. {
  1440. char32_t buffer[32];
  1441. const int kHexValue = 0x12;
  1442. Sprintf(buffer, EA_CHAR32("%.4x"), kHexValue);
  1443. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1444. Sprintf(buffer, EA_CHAR32("%04x"), kHexValue);
  1445. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1446. Sprintf(buffer, EA_CHAR32("%4.4x"), kHexValue);
  1447. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1448. Sprintf(buffer, EA_CHAR32("%04.4x"), kHexValue);
  1449. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1450. Sprintf(buffer, EA_CHAR32("%4.3x"), kHexValue);
  1451. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 012")) == 0);
  1452. Sprintf(buffer, EA_CHAR32("%04.3x"), kHexValue);
  1453. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 012")) == 0);
  1454. Sprintf(buffer, EA_CHAR32("%.*x"), 4, kHexValue);
  1455. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1456. Sprintf(buffer, EA_CHAR32("%0*x"), 4, kHexValue);
  1457. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1458. Sprintf(buffer, EA_CHAR32("%*.*x"), 4, 4, kHexValue);
  1459. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1460. Sprintf(buffer, EA_CHAR32("%0*.*x"), 4, 4, kHexValue);
  1461. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0012")) == 0);
  1462. }
  1463. {
  1464. char32_t buffer[96];
  1465. Sprintf(buffer, EA_CHAR32("decimal negative: \"%d\"\n"), -2345);
  1466. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("decimal negative: \"-2345\"\n")) == 0);
  1467. Sprintf(buffer, EA_CHAR32("octal negative: \"%o\"\n"), -2345);
  1468. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1469. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("octal negative: \"37777773327\"\n")) == 0);
  1470. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1471. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("octal negative: \"1777777777777777773327\"\n")) == 0);
  1472. Sprintf(buffer, EA_CHAR32("hex negative: \"%x\"\n"), -2345);
  1473. if(sizeof(int) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1474. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("hex negative: \"fffff6d7\"\n")) == 0);
  1475. else if(sizeof(int) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1476. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("hex negative: \"fffffffffffff6d7\"\n")) == 0);
  1477. Sprintf(buffer, EA_CHAR32("long decimal number: \"%ld\"\n"), -123456L);
  1478. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("long decimal number: \"-123456\"\n")) == 0);
  1479. Sprintf(buffer, EA_CHAR32("long octal negative: \"%lo\"\n"), -2345L);
  1480. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1481. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("long octal negative: \"37777773327\"\n")) == 0);
  1482. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1483. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("long octal negative: \"1777777777777777773327\"\n")) == 0);
  1484. Sprintf(buffer, EA_CHAR32("long unsigned decimal number: \"%lu\"\n"), -123456L);
  1485. if(sizeof(long) == (4 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1486. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("long unsigned decimal number: \"4294843840\"\n")) == 0);
  1487. else if(sizeof(long) == (8 + (__FILE__[0] / 100000))) // Trickery here to avoid compiler warnings.
  1488. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("long unsigned decimal number: \"18446744073709428160\"\n")) == 0);
  1489. Sprintf(buffer, EA_CHAR32("zero-padded LDN: \"%010ld\"\n"), -123456L);
  1490. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("zero-padded LDN: \"-000123456\"\n")) == 0);
  1491. Sprintf(buffer, EA_CHAR32("left-adjusted ZLDN: \"%-010ld\"\n"), -123456L);
  1492. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("left-adjusted ZLDN: \"-123456 \"\n")) == 0);
  1493. Sprintf(buffer, EA_CHAR32("space-padded LDN: \"%10ld\"\n"), -123456L);
  1494. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("space-padded LDN: \" -123456\"\n")) == 0);
  1495. Sprintf(buffer, EA_CHAR32("left-adjusted SLDN: \"%-10ld\"\n"), -123456L);
  1496. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("left-adjusted SLDN: \"-123456 \"\n")) == 0);
  1497. }
  1498. {
  1499. char32_t buffer[1024];
  1500. wchar_t str1[64]; Strlcpy(str1, EA_WCHAR("abc de"), EAArrayCount(str1)); // Can't do str1[64] = EA_CHAR32("abc de") because some compilers don't support 32 bit string literals.
  1501. wchar_t str2[64]; Strlcpy(str2, EA_WCHAR("abd def ghi jkl mno pqr stu vwz yz."), EAArrayCount(str2));
  1502. // The C99 standard specifies that leading zeros only put zeroes in front of numerical types. Spaces for others.
  1503. Sprintf(buffer, EA_CHAR32("zero-padded string: \"%010s\"\n"), str1);
  1504. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("zero-padded string: \" abc de\"\n")) == 0); // VC++ fails this, as it puts zeroes in front.
  1505. Sprintf(buffer, EA_CHAR32("left-adjusted Z string: \"%-010s\"\n"), str1);
  1506. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("left-adjusted Z string: \"abc de \"\n")) == 0);
  1507. Sprintf(buffer, EA_CHAR32("space-padded string: \"%10s\"\n"), str1);
  1508. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("space-padded string: \" abc de\"\n")) == 0);
  1509. Sprintf(buffer, EA_CHAR32("left-adjusted S string: \"%-10s\"\n"), str1);
  1510. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("left-adjusted S string: \"abc de \"\n")) == 0);
  1511. Sprintf(buffer, EA_CHAR32("limited string: \"%.22s\"\n"), str2);
  1512. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("limited string: \"abd def ghi jkl mno pq\"\n")) == 0);
  1513. Sprintf(buffer, EA_CHAR32("null string: \"%s\"\n"), (wchar_t*)NULL);
  1514. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("null string: \"(null)\"\n")) == 0);
  1515. Sprintf(buffer, EA_CHAR32("%10s\n"), (wchar_t*)NULL);
  1516. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" (null)\n")) == 0);
  1517. Sprintf(buffer, EA_CHAR32("%-10s\n"), (wchar_t*)NULL);
  1518. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("(null) \n")) == 0);
  1519. Sprintf(buffer, EA_CHAR32("%*s%*s%*s"), -1, EA_WCHAR("one"), -20, EA_WCHAR("two"), -30, EA_WCHAR("three"));
  1520. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("onetwo three ")) == 0);
  1521. int i;
  1522. memset(buffer, '_', sizeof(buffer));
  1523. Sprintf(buffer, EA_CHAR32("x%1000ls"), EA_WCHAR(" "));
  1524. EATEST_VERIFY(buffer[0] == 'x');
  1525. for(i = 0; i < 1000; i++)
  1526. {
  1527. if(buffer[1 + i] != ' ')
  1528. break;
  1529. }
  1530. if(i != 1000)
  1531. EATEST_VERIFY(i == 1000);
  1532. else
  1533. EATEST_VERIFY(buffer[1 + 1000] == 0);
  1534. }
  1535. { // String tests
  1536. // We accept %hc, %c, %lc, %I8c, %I16c, %I32c (regular, regular, wide, char8_t, char16_t, char32_t)
  1537. // We accept %hC, %C, %lC, %I8C, %I16C, %I32C (regular, wide, wide, char8_t, char16_t, char32_t)
  1538. // We accept %hs, %s, %ls, %I8s, %I16s, %I32s (regular, regular, wide, char8_t, char16_t, char32_t)
  1539. // We accept %hS, %S, %lS, %I8s, %I16s, %I32s (regular, wide, wide, char8_t, char16_t, char32_t)
  1540. char32_t buffer[32];
  1541. char8_t dStr8[2] = { 'd', 0 };
  1542. char16_t eStr16[2] = { 'e', 0 };
  1543. char32_t fStr32[2] = { 'f', 0 };
  1544. #if EASPRINTF_MS_STYLE_S_FORMAT // Microsoft style means that the meanings of S and s are reversed for non-char8_t Sprintf.
  1545. Sprintf(buffer, EA_CHAR32("%hc %c %lc %I8c %I16c %I32c"), 'a', EA_WCHAR('b'), EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1546. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1547. Sprintf(buffer, EA_CHAR32("%hC %C %lC %I8C %I16C %I32C"), 'a', 'b', EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1548. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1549. Sprintf(buffer, EA_CHAR32("%hs %s %ls %I8s %I16s %I32s"), "a", EA_WCHAR("b"), EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1550. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1551. Sprintf(buffer, EA_CHAR32("%hS %S %lS %I8S %I16S %I32S"), "a", "b", EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1552. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1553. #else
  1554. Sprintf(buffer, EA_CHAR32("%hc %c %lc %I8c %I16c %I32c"), 'a', 'b', EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1555. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1556. Sprintf(buffer, EA_CHAR32("%hC %C %lC %I8C %I16C %I32C"), 'a', EA_WCHAR('b'), EA_WCHAR('c'), (char8_t)'d', (char16_t)'e', (char32_t)'f');
  1557. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f)") == 0);
  1558. Sprintf(buffer, EA_CHAR32("%hs %s %ls %I8s %I16s %I32s"), "a", "b", EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1559. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1560. Sprintf(buffer, EA_CHAR32("%hS %S %lS %I8S %I16S %I32S"), "a", EA_WCHAR("b"), EA_WCHAR("c"), dStr8, eStr16, fStr32);
  1561. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("a b c d e f")) == 0);
  1562. #endif
  1563. }
  1564. {
  1565. char32_t buffer[384];
  1566. int i;
  1567. Sprintf(buffer, EA_CHAR32("e-style >= 1: \"%e\"\n"), 12.34);
  1568. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("e-style >= 1: \"1.234000e+01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1569. Sprintf(buffer, EA_CHAR32("e-style >= .1: \"%e\"\n"), 0.1234);
  1570. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("e-style >= .1: \"1.234000e-01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1571. Sprintf(buffer, EA_CHAR32("e-style < .1: \"%e\"\n"), 0.001234);
  1572. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("e-style < .1: \"1.234000e-03\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1573. Sprintf(buffer, EA_CHAR32("e-style big: \"%.60e\"\n"), 1e20);
  1574. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("e-style big: \"1.000000000000000000000000000000000000000000000000000000000000e+20\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1575. Sprintf(buffer, EA_CHAR32("e-style == .1: \"%e\"\n"), 0.1);
  1576. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("e-style == .1: \"1.000000e-01\"\n")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1577. Sprintf(buffer, EA_CHAR32("f-style >= 1: \"%f\"\n"), 12.34);
  1578. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("f-style >= 1: \"12.340000\"\n")) == 0);
  1579. Sprintf(buffer, EA_CHAR32("f-style >= .1: \"%f\"\n"), 0.1234);
  1580. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("f-style >= .1: \"0.123400\"\n")) == 0);
  1581. Sprintf(buffer, EA_CHAR32("f-style < .1: \"%f\"\n"), 0.001234);
  1582. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("f-style < .1: \"0.001234\"\n")) == 0);
  1583. Sprintf(buffer, EA_CHAR32("g-style >= 1: \"%g\"\n"), 12.34);
  1584. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("g-style >= 1: \"12.34\"\n")) == 0);
  1585. Sprintf(buffer, EA_CHAR32("g-style >= .1: \"%g\"\n"), 0.1234);
  1586. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("g-style >= .1: \"0.1234\"\n")) == 0);
  1587. Sprintf(buffer, EA_CHAR32("g-style < .1: \"%g\"\n"), 0.001234);
  1588. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("g-style < .1: \"0.001234\"\n")) == 0);
  1589. Sprintf(buffer, EA_CHAR32("g-style big: \"%.60g\"\n"), 1e20);
  1590. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("g-style big: \"100000000000000000000\"\n")) == 0);
  1591. //Sprintf(buffer, EA_CHAR32("%#.4g\n"), 0.0); // The C99 committee has decided in a defect analysis that this is how it should work.
  1592. //EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0\n")) == 0);
  1593. Sprintf(buffer, EA_CHAR32(" %6.5f\n"), .099999999860301614);
  1594. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 0.10000\n")) == 0);
  1595. Sprintf(buffer, EA_CHAR32(" %6.5f\n"), .1);
  1596. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 0.10000\n")) == 0);
  1597. Sprintf(buffer, EA_CHAR32("x%5.4fx\n"), .5);
  1598. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("x0.5000x\n")) == 0);
  1599. Sprintf(buffer, EA_CHAR32("%#03x\n"), 1);
  1600. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("0x1\n")) == 0);
  1601. memset(buffer, '_', sizeof(buffer));
  1602. Sprintf(buffer, EA_CHAR32("%.300f"), 1.0);
  1603. EATEST_VERIFY((buffer[0] == '1') && (buffer[1] == '.'));
  1604. for(i = 0; i < 300; i++)
  1605. {
  1606. if(buffer[2 + i] != '0')
  1607. break;
  1608. }
  1609. if(i != 300)
  1610. EATEST_VERIFY(i == 300);
  1611. else
  1612. EATEST_VERIFY(buffer[2 + 300] == 0);
  1613. double d = static_cast<double>(FLT_MIN); // We are intentionally using FLT_MIN and not DBL_MIN.
  1614. d /= 2.0;
  1615. Sprintf(buffer, EA_CHAR32("%.17e"), d); // It should be something like 5.87747175411143___e-39 where count and values of the _ digits vary by hardware.
  1616. buffer[16] = buffer[17] = buffer[18] = '_'; // Replace the uncertain digits with '_' characters, as they are system-dependent.
  1617. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("5.87747175411143___e-39")) == 0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1618. Sprintf(buffer, EA_CHAR32("%15.5e\n"), 4.9406564584124654e-307);
  1619. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 4.94066e-307\n")) == 0);
  1620. }
  1621. {
  1622. char32_t buffer[96];
  1623. const char32_t* pExpected;
  1624. // VC++ sprintf would fail these tests, as the Standard says to print no more
  1625. // than 2 unless necessary, yet VC++ sprintf prints 3 digits exponents.
  1626. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 0.0, 0.0, 0.0);
  1627. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("| 0.0000| 0.0000e+00| 0|")) == 0);
  1628. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 1.0, 1.0, 1.0);
  1629. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("| 1.0000| 1.0000e+00| 1|")) == 0);
  1630. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), -1.0, -1.0, -1.0);
  1631. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("| -1.0000| -1.0000e+00| -1|")) == 0);
  1632. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 100.0, 100.0, 100.0);
  1633. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("| 100.0000| 1.0000e+02| 100|")) == 0);
  1634. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 1000.0, 1000.0, 1000.0);
  1635. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("| 1000.0000| 1.0000e+03| 1000|")) == 0);
  1636. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 10000.0, 10000.0, 10000.0);
  1637. EATEST_VERIFY(Strcmp(buffer,EA_CHAR32("| 10000.0000| 1.0000e+04| 1e+04|")) == 0);
  1638. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 12346.0, 12346.0, 12346.0);
  1639. pExpected = EA_CHAR32("| 12346.0000| 1.2346e+04| 1.235e+04|");
  1640. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1641. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 100000.0, 100000.0, 100000.0);
  1642. pExpected = EA_CHAR32("| 100000.0000| 1.0000e+05| 1e+05|");
  1643. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1644. Sprintf(buffer, EA_CHAR32("|%12.4f|%12.4e|%12.4g|"), 123467.0, 123467.0, 123467.0);
  1645. pExpected = EA_CHAR32("| 123467.0000| 1.2347e+05| 1.235e+05|");
  1646. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1647. }
  1648. {
  1649. char32_t buffer[96];
  1650. // Verify that snprintf follows the C99 convention of returning the number of characters
  1651. // required. This is as opposed to the non-standard way that some libraries just return
  1652. // -1 if the buffer isn't big enough.
  1653. const int kBuf1Capacity = 20;
  1654. wchar_t buf1[kBuf1Capacity];
  1655. int n1 = Snprintf(buf1, kBuf1Capacity, EA_WCHAR("%30I32s"), EA_CHAR32("foo"));
  1656. Sprintf(buffer, EA_CHAR32("snprintf(\"%%30s\", \"foo\") == %d, \"%.*s\"\n"), n1, kBuf1Capacity, buf1);
  1657. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("snprintf(\"%30s\", \"foo\") == 30, \" \"\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1658. const int kBuf2Capacity = 512;
  1659. char32_t buf2[kBuf2Capacity];
  1660. int n2 = Snprintf(buf2, kBuf2Capacity, EA_CHAR32("%.1000u"), 10);
  1661. Sprintf(buffer, EA_CHAR32("snprintf(\"%%.1000u\", 10) == %d\n"), n2);
  1662. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("snprintf(\"%.1000u\", 10) == 1000\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1663. const int kBuf3Capacity = 512;
  1664. char32_t buf3[kBuf3Capacity];
  1665. char32_t* pString = new char32_t[100000];
  1666. memset(pString, '_', 100000 * sizeof(char32_t));
  1667. pString[100000 - 1] = 0;
  1668. int n3 = Snprintf(buf3, kBuf2Capacity, EA_CHAR32("%I32s"), pString);
  1669. Sprintf(buffer, EA_CHAR32("snprintf(\"%%s\", pString) == %d\n"), n3);
  1670. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("snprintf(\"%s\", pString) == 99999\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1671. delete[] pString;
  1672. int n4 = Snprintf(NULL, 0, EA_CHAR32("%I32s"), EA_CHAR32("abc"));
  1673. Sprintf(buffer, EA_CHAR32("snprintf(NULL, \"abc\") == %d\n"), n4);
  1674. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("snprintf(NULL, \"abc\") == 3\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1675. int n5 = Snprintf(NULL, 100, EA_CHAR32("%I32s"), EA_CHAR32("abc"));
  1676. Sprintf(buffer, EA_CHAR32("snprintf(NULL, \"abc\") == %d\n"), n5);
  1677. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("snprintf(NULL, \"abc\") == 3\n")) == 0); // VC++ fails this, as it's version of snprintf doesn't use C99 standard snprintf return value conventions.
  1678. }
  1679. {
  1680. char32_t buffer[16][64];
  1681. int n = 0, i, j, k, m;
  1682. for(i = 0; i < 2; i++)
  1683. {
  1684. for(j = 0; j < 2; j++)
  1685. {
  1686. for(k = 0; k < 2; k++)
  1687. {
  1688. for(m = 0; m < 2; m++)
  1689. {
  1690. wchar_t prefix[7];
  1691. char32_t format[96];
  1692. Strcpy(prefix, EA_WCHAR("%"));
  1693. if(i == 0)
  1694. Strcat(prefix, EA_WCHAR("-"));
  1695. if(j == 0)
  1696. Strcat(prefix, EA_WCHAR("+"));
  1697. if(k == 0)
  1698. Strcat(prefix, EA_WCHAR("#"));
  1699. if(m == 0)
  1700. Strcat(prefix, EA_WCHAR("0"));
  1701. #define DEC -123
  1702. #define INT 255
  1703. #define UNS (~0)
  1704. Sprintf(format, EA_CHAR32("%%5s |%s6d |%s6o |%s6x |%s6X |%s6u |"), prefix, prefix, prefix, prefix, prefix);
  1705. Sprintf(buffer[n], format, prefix, DEC, INT, INT, INT, UNS);
  1706. n++;
  1707. }
  1708. }
  1709. }
  1710. }
  1711. EATEST_VERIFY(Strcmp(buffer[ 0], EA_CHAR32("%-+#0 |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1712. EATEST_VERIFY(Strcmp(buffer[ 1], EA_CHAR32(" %-+# |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1713. EATEST_VERIFY(Strcmp(buffer[ 2], EA_CHAR32(" %-+0 |-123 |377 |ff |FF |4294967295 |")) == 0);
  1714. EATEST_VERIFY(Strcmp(buffer[ 3], EA_CHAR32(" %-+ |-123 |377 |ff |FF |4294967295 |")) == 0);
  1715. EATEST_VERIFY(Strcmp(buffer[ 4], EA_CHAR32(" %-#0 |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1716. EATEST_VERIFY(Strcmp(buffer[ 5], EA_CHAR32(" %-# |-123 |0377 |0xff |0XFF |4294967295 |")) == 0);
  1717. EATEST_VERIFY(Strcmp(buffer[ 6], EA_CHAR32(" %-0 |-123 |377 |ff |FF |4294967295 |")) == 0);
  1718. EATEST_VERIFY(Strcmp(buffer[ 7], EA_CHAR32(" %- |-123 |377 |ff |FF |4294967295 |")) == 0);
  1719. EATEST_VERIFY(Strcmp(buffer[ 8], EA_CHAR32(" %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |")) == 0);
  1720. EATEST_VERIFY(Strcmp(buffer[ 9], EA_CHAR32(" %+# | -123 | 0377 | 0xff | 0XFF |4294967295 |")) == 0);
  1721. EATEST_VERIFY(Strcmp(buffer[10], EA_CHAR32(" %+0 |-00123 |000377 |0000ff |0000FF |4294967295 |")) == 0);
  1722. EATEST_VERIFY(Strcmp(buffer[11], EA_CHAR32(" %+ | -123 | 377 | ff | FF |4294967295 |")) == 0);
  1723. EATEST_VERIFY(Strcmp(buffer[12], EA_CHAR32(" %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |")) == 0);
  1724. EATEST_VERIFY(Strcmp(buffer[13], EA_CHAR32(" %# | -123 | 0377 | 0xff | 0XFF |4294967295 |")) == 0);
  1725. EATEST_VERIFY(Strcmp(buffer[14], EA_CHAR32(" %0 |-00123 |000377 |0000ff |0000FF |4294967295 |")) == 0);
  1726. EATEST_VERIFY(Strcmp(buffer[15], EA_CHAR32(" % | -123 | 377 | ff | FF |4294967295 |")) == 0);
  1727. }
  1728. {
  1729. char32_t buffer[256];
  1730. const char32_t* pExpected;
  1731. Sprintf(buffer, EA_CHAR32("%e"), 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1732. pExpected = EA_CHAR32("1.234568e+06");
  1733. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1734. Sprintf(buffer, EA_CHAR32("%f"), 1234567.8);
  1735. pExpected = EA_CHAR32("1234567.800000");
  1736. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1737. Sprintf(buffer, EA_CHAR32("%g"), 1234567.8); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1738. pExpected = EA_CHAR32("1.23457e+06");
  1739. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1740. Sprintf(buffer, EA_CHAR32("%g"), 123.456);
  1741. pExpected = EA_CHAR32("123.456");
  1742. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1743. Sprintf(buffer, EA_CHAR32("%g"), 1000000.0); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1744. pExpected = EA_CHAR32("1e+06");
  1745. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1746. Sprintf(buffer, EA_CHAR32("%g"), 10.0);
  1747. pExpected = EA_CHAR32("10");
  1748. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1749. Sprintf(buffer, EA_CHAR32("%g"), 0.02);
  1750. pExpected = EA_CHAR32("0.02");
  1751. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1752. }
  1753. { // Test the ' extension, which cases numbers to be printed with a thousands separator.
  1754. char32_t buffer[64];
  1755. const char32_t* pExpected;
  1756. Sprintf(buffer, EA_CHAR32("%'u"), 123456789);
  1757. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("123,456,789")) == 0);
  1758. Sprintf(buffer, EA_CHAR32("%'d"), -123456789);
  1759. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("-123,456,789")) == 0);
  1760. Sprintf(buffer, EA_CHAR32("%'I8u"), 123);
  1761. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("123")) == 0);
  1762. Sprintf(buffer, EA_CHAR32("%'I16u"), 12345);
  1763. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("12,345")) == 0);
  1764. Sprintf(buffer, EA_CHAR32("%'I16d"), -12345);
  1765. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("-12,345")) == 0);
  1766. Sprintf(buffer, EA_CHAR32("%'I32u"), 12345678);
  1767. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("12,345,678")) == 0);
  1768. Sprintf(buffer, EA_CHAR32("%'I32d"), -12345678);
  1769. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("-12,345,678")) == 0);
  1770. Sprintf(buffer, EA_CHAR32("%20I32d"), -12345678);
  1771. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" -12345678")) == 0);
  1772. Sprintf(buffer, EA_CHAR32("%'20I32d"), -12345678); // Verify that the , chars count towards the field width.
  1773. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" -12,345,678")) == 0);
  1774. Sprintf(buffer, EA_CHAR32("%'I32x"), 0x12345678); // ' has no effect on hex formatting.
  1775. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("12345678")) == 0);
  1776. Sprintf(buffer, EA_CHAR32("%'I64u"), UINT64_C(1234999995678));
  1777. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("1,234,999,995,678")) == 0);
  1778. Sprintf(buffer, EA_CHAR32("%'I64d"), INT64_C(-1234599999678));
  1779. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("-1,234,599,999,678")) == 0);
  1780. Sprintf(buffer, EA_CHAR32("%'I64x"), UINT64_C(0x1234567812345678)); // ' has no effect on hex formatting.
  1781. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("1234567812345678")) == 0);
  1782. Sprintf(buffer, EA_CHAR32("%'f"), 123456.234);
  1783. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("123,456.234000")) == 0);
  1784. Sprintf(buffer, EA_CHAR32("%'e"), 1234567.8); // ' has no effect on %e formatting.
  1785. pExpected = EA_CHAR32("1.234568e+06");
  1786. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1787. Sprintf(buffer, EA_CHAR32("%'g"), 1234.54); // In some cases %g acts like %f.
  1788. pExpected = EA_CHAR32("1,234.54");
  1789. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1790. Sprintf(buffer, EA_CHAR32("%'g"), 1234567.8); // In some cases %g acts like %f.
  1791. pExpected = EA_CHAR32("1.23457e+06");
  1792. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1793. }
  1794. {
  1795. char32_t buffer[256];
  1796. Sprintf(buffer, EA_CHAR32("%hhu"), UCHAR_MAX + 2);
  1797. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("1")) == 0); // VC++ fails this, as it doesn't implement the C99 standard %hh modifier.
  1798. Sprintf(buffer, EA_CHAR32("%hu"), USHRT_MAX + 2);
  1799. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("1")) == 0);
  1800. }
  1801. {
  1802. char32_t buffer[128];
  1803. const char32_t* pExpected;
  1804. Sprintf(buffer, EA_CHAR32("%5.s"), EA_WCHAR("xyz"));
  1805. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" ")) == 0);
  1806. Sprintf(buffer, EA_CHAR32("%5.f"), 33.3);
  1807. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 33")) == 0);
  1808. Sprintf(buffer, EA_CHAR32("%8.e"), 33.3e7); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1809. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 3e+08")) == 0);
  1810. Sprintf(buffer, EA_CHAR32("%8.E"), 33.3e7); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1811. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 3E+08")) == 0);
  1812. Sprintf(buffer, EA_CHAR32("%.g"), 33.3); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1813. pExpected = EA_CHAR32("3e+01");
  1814. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1815. Sprintf(buffer, EA_CHAR32("%.G"), 33.3); // VC++ sprintf would fail this, as it uses 3 exponent digits, but the Standard says to print no more than 2 unless necessary.
  1816. pExpected = EA_CHAR32("3E+01");
  1817. EATEST_VERIFY_F(Strcmp(buffer, pExpected) == 0, "\n Expected: %I32s\n Actual: %I32s", pExpected, buffer);
  1818. }
  1819. {
  1820. char32_t buffer[128];
  1821. int precision;
  1822. precision = 0;
  1823. Sprintf(buffer, EA_CHAR32("%.*g"), precision, 3.3);
  1824. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("3")) == 0);
  1825. precision = 0;
  1826. Sprintf(buffer, EA_CHAR32("%.*G"), precision, 3.3);
  1827. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32("3")) == 0);
  1828. precision = 0;
  1829. Sprintf(buffer, EA_CHAR32("%7.*G"), precision, 3.33);
  1830. EATEST_VERIFY(Strcmp(buffer,EA_CHAR32(" 3")) == 0);
  1831. precision = 3;
  1832. Sprintf(buffer, EA_CHAR32("%04.*o"), precision, 33);
  1833. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 041")) == 0);
  1834. precision = 7;
  1835. Sprintf(buffer, EA_CHAR32("%09.*u"), precision, 33);
  1836. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 0000033")) == 0);
  1837. precision = 3;
  1838. Sprintf(buffer, EA_CHAR32("%04.*x"), precision, 33);
  1839. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 021")) == 0);
  1840. precision = 3;
  1841. Sprintf(buffer, EA_CHAR32("%04.*X"), precision, 33);
  1842. EATEST_VERIFY(Strcmp(buffer, EA_CHAR32(" 021")) == 0);
  1843. }
  1844. {
  1845. static const int kSourceSize = 1024 * 5;
  1846. static const int kOutputSize = kSourceSize + 100;
  1847. char8_t value[kSourceSize];
  1848. char32_t destination[kOutputSize];
  1849. char32_t comparison[kOutputSize];
  1850. for(int i = 0; i < kSourceSize - 1; ++i)
  1851. {
  1852. value[i] = '0' + (i % 10);
  1853. comparison[i] = '0' + (i % 10);
  1854. }
  1855. value[kSourceSize - 1] = 0;
  1856. comparison[kSourceSize - 1] = 0;
  1857. EA::StdC::Snprintf(destination, kOutputSize, EA_CHAR32("%I8s"), value);
  1858. EATEST_VERIFY(Strcmp(destination, comparison) == 0);
  1859. EA::StdC::Snprintf(destination, kOutputSize, EA_CHAR32("%.10I8s"), value);
  1860. EATEST_VERIFY(Strcmp(destination, EA_CHAR32("0123456789")) == 0);
  1861. }
  1862. return nErrorCount;
  1863. }
  1864. static int TestDrintf8()
  1865. {
  1866. using namespace EA::StdC;
  1867. int nErrorCount = 0;
  1868. {
  1869. int result;
  1870. Dprintf("Begin Dprintf (debug output printf) testing...\n");
  1871. // EASTDC_API int Vdprintf(const char8_t* EA_RESTRICT pFormat, va_list arguments);
  1872. // EASTDC_API int Dprintf(const char8_t* EA_RESTRICT pFormat, ...);
  1873. eastl::string8 sBuffer;
  1874. for(eastl_size_t i = 0; i < 1024; i++) // This size should be > than the size of the buffer(s) used in PlatformLogWriter8, though those buffer sizes aren't publicly exposed.
  1875. sBuffer.push_back('a' + (char8_t)(i % 26));
  1876. EA::UnitTest::Rand rand((uint32_t)EA::StdC::GetTime());
  1877. for(eastl_size_t i = 0; i < 1024; i += rand.RandRange(1, 100))
  1878. {
  1879. char formatBuffer[32]; // Something like "%.52s"
  1880. Sprintf(formatBuffer, "%%.%ds\n", i); // Use \n because some debug output systems might otherwise get overwhelmed.
  1881. result = Dprintf(formatBuffer, sBuffer.c_str());
  1882. EATEST_VERIFY(result > 0);
  1883. }
  1884. #if EASTDC_PRINTF_DEBUG_ENABLED
  1885. // EASTDC_API int Fprintf(FILE* EA_RESTRICT pFile, const char8_t* EA_RESTRICT pFormat, ...);
  1886. // EASTDC_API int Printf(const char8_t* EA_RESTRICT pFormat, ...);
  1887. // EASTDC_API int Vfprintf(FILE* EA_RESTRICT pFile, const char8_t* EA_RESTRICT pFormat, va_list arguments);
  1888. // EASTDC_API int Vprintf(const char8_t* EA_RESTRICT pFormat, va_list arguments);
  1889. result = Printf("%s", "Printf test (EASTDC_PRINTF_DEBUG_ENABLED).\n");
  1890. EATEST_VERIFY(result > 0);
  1891. result = Fprintf(stdout, "%s", "Printf test (EASTDC_PRINTF_DEBUG_ENABLED).\n");
  1892. EATEST_VERIFY(result > 0);
  1893. #endif
  1894. Dprintf("End Dprintf (debug output printf) testing.\n");
  1895. }
  1896. return nErrorCount;
  1897. }
  1898. static int TestOsprintf8()
  1899. {
  1900. using namespace EA::StdC;
  1901. int nErrorCount = 0;
  1902. {
  1903. char8_t buffer[32];
  1904. int result;
  1905. memset(buffer, 0, sizeof(buffer));
  1906. result = OSprintf(buffer, "%0:d", (int)0);
  1907. EATEST_VERIFY((result == 1) && Strcmp(buffer, "0") == 0);
  1908. memset(buffer, 0, sizeof(buffer));
  1909. result = OSprintf(buffer, "%2:1.0f %3:d %1:c", (char)'3', (float)1.f, (int)2);
  1910. EATEST_VERIFY((result == 5) && Strcmp(buffer, "1 2 3") == 0);
  1911. // Test 0-based ordering
  1912. memset(buffer, 0, sizeof(buffer));
  1913. result = OSprintf(buffer, "%1:1.0f %2:d %0:c", (char)'3', (float)1.f, (int)2);
  1914. EATEST_VERIFY((result == 5) && Strcmp(buffer, "1 2 3") == 0);
  1915. // Test format limit (currently 21 spans)
  1916. memset(buffer, 0, sizeof(buffer));
  1917. result = OSprintf(buffer, " %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d ", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  1918. EATEST_VERIFY((result == 28) && Strcmp(buffer, " 0 1 2 3 4 5 6 7 8 9 " ) == 0);
  1919. // Test format overflow
  1920. // Tests below are disabled by default because they trigger runtime asserts which break auto-testing.
  1921. // They can be enabled by running these tests in interactive mode, in which case you'll have to manually
  1922. // dismiss assertion failures for these.
  1923. if(EA::UnitTest::GetInteractive())
  1924. {
  1925. memset(buffer, 0, sizeof(buffer));
  1926. result = OSprintf(buffer, " %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d %9:d ", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9);
  1927. EATEST_VERIFY(result == -1);
  1928. memset(buffer, 0, sizeof(buffer));
  1929. result = OSprintf(buffer, "%00000000000000000000:f", 0.f);
  1930. EATEST_VERIFY(result == -1);
  1931. memset(buffer, 0, sizeof(buffer));
  1932. result = OSprintf(buffer, "%0:000000000000000000f", 0.f);
  1933. EATEST_VERIFY(result == -1);
  1934. memset(buffer, 0, sizeof(buffer));
  1935. result = OSprintf(buffer, "%0:.000000000000000000f", 0.f);
  1936. EATEST_VERIFY(result == -1);
  1937. memset(buffer, 0, sizeof(buffer));
  1938. result = OSprintf(buffer, "%000000000000000000:000000000000000000.000000000000000000f", 0.f);
  1939. EATEST_VERIFY(result == -1);
  1940. }
  1941. // Test OVsnprintf capacity limits
  1942. memset(buffer, 0, sizeof(buffer));
  1943. result = OSnprintf(buffer, 0, "%2:1.0f %3:d %1:c", (char)'3', (float)1.f, (int)2);
  1944. EATEST_VERIFY((result == 5) && (buffer[0] == 0));
  1945. }
  1946. return nErrorCount;
  1947. }
  1948. static int TestOsprintf16()
  1949. {
  1950. using namespace EA::StdC;
  1951. int nErrorCount = 0;
  1952. {
  1953. char16_t buffer[128];
  1954. int result;
  1955. memset(buffer, 0, sizeof(buffer));
  1956. result = OSprintf(buffer, EA_CHAR16("%0:d"), (int)0);
  1957. EATEST_VERIFY((result == 1) && Strcmp(buffer, EA_CHAR16("0")) == 0);
  1958. memset(buffer, 0, sizeof(buffer));
  1959. result = OSprintf(buffer, EA_CHAR16("%2:1.0f %3:d %1:c"), (char)'3', (float)1.f, (int)2);
  1960. EATEST_VERIFY((result == 5) && Strcmp(buffer, EA_CHAR16("1 2 3")) == 0);
  1961. // Test 0-based ordering
  1962. memset(buffer, 0, sizeof(buffer));
  1963. result = OSprintf(buffer, EA_CHAR16("%1:1.0f %2:d %0:c"), (char)'3', (float)1.f, (int)2);
  1964. EATEST_VERIFY((result == 5) && Strcmp(buffer, EA_CHAR16("1 2 3")) == 0);
  1965. // Test format limit (currently 21 spans)
  1966. memset(buffer, 0, sizeof(buffer));
  1967. result = OSprintf(buffer, EA_CHAR16(" %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d "), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  1968. EATEST_VERIFY((result == 28) && Strcmp(buffer, EA_CHAR16(" 0 1 2 3 4 5 6 7 8 9 ")) == 0);
  1969. // Test format overflow
  1970. // Tests below are disabled by default because they trigger runtime asserts which break auto-testing.
  1971. // They can be enabled by running these tests in interactive mode, in which case you'll have to manually
  1972. // dismiss assertion failures for these.
  1973. if(EA::UnitTest::GetInteractive())
  1974. {
  1975. memset(buffer, 0, sizeof(buffer));
  1976. result = OSprintf(buffer, EA_CHAR16(" %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d %9:d "), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9);
  1977. EATEST_VERIFY(result == -1);
  1978. memset(buffer, 0, sizeof(buffer));
  1979. result = OSprintf(buffer, EA_CHAR16("%00000000000000000000:f"), 0.f);
  1980. EATEST_VERIFY(result == -1);
  1981. memset(buffer, 0, sizeof(buffer));
  1982. result = OSprintf(buffer, EA_CHAR16("%0:000000000000000000f"), 0.f);
  1983. EATEST_VERIFY(result == -1);
  1984. memset(buffer, 0, sizeof(buffer));
  1985. result = OSprintf(buffer, EA_CHAR16("%0:.000000000000000000f"), 0.f);
  1986. EATEST_VERIFY(result == -1);
  1987. memset(buffer, 0, sizeof(buffer));
  1988. result = OSprintf(buffer, EA_CHAR16("%000000000000000000:000000000000000000.000000000000000000f"), 0.f);
  1989. EATEST_VERIFY(result == -1);
  1990. }
  1991. // Test OVsnprintf capacity limits
  1992. memset(buffer, 0, sizeof(buffer));
  1993. result = OSnprintf(buffer, 0, EA_CHAR16("%2:1.0f %3:d %1:c"), (char)'3', (float)1.f, (int)2);
  1994. EATEST_VERIFY((result == 5) && (buffer[0] == 0));
  1995. }
  1996. return nErrorCount;
  1997. }
  1998. static int TestOsprintf32()
  1999. {
  2000. using namespace EA::StdC;
  2001. int nErrorCount = 0;
  2002. {
  2003. char32_t buffer[128];
  2004. int result;
  2005. memset(buffer, 0, sizeof(buffer));
  2006. result = OSprintf(buffer, EA_CHAR32("%0:d"), (int)0);
  2007. EATEST_VERIFY((result == 1) && Strcmp(buffer, EA_CHAR32("0")) == 0);
  2008. memset(buffer, 0, sizeof(buffer));
  2009. result = OSprintf(buffer, EA_CHAR32("%2:1.0f %3:d %1:c"), (char)'3', (float)1.f, (int)2);
  2010. EATEST_VERIFY((result == 5) && Strcmp(buffer, EA_CHAR32("1 2 3")) == 0);
  2011. // Test 0-based ordering
  2012. memset(buffer, 0, sizeof(buffer));
  2013. result = OSprintf(buffer, EA_CHAR32("%1:1.0f %2:d %0:c"), (char)'3', (float)1.f, (int)2);
  2014. EATEST_VERIFY((result == 5) && Strcmp(buffer, EA_CHAR32("1 2 3")) == 0);
  2015. // Test format limit (currently 21 spans)
  2016. memset(buffer, 0, sizeof(buffer));
  2017. result = OSprintf(buffer, EA_CHAR32(" %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d "), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
  2018. EATEST_VERIFY((result == 28) && Strcmp(buffer, EA_CHAR32(" 0 1 2 3 4 5 6 7 8 9 ")) == 0);
  2019. // Test format overflow
  2020. // Tests below are disabled by default because they trigger runtime asserts which break auto-testing.
  2021. // They can be enabled by running these tests in interactive mode, in which case you'll have to manually
  2022. // dismiss assertion failures for these.
  2023. if(EA::UnitTest::GetInteractive())
  2024. {
  2025. memset(buffer, 0, sizeof(buffer));
  2026. result = OSprintf(buffer, EA_CHAR32(" %0:d %1:d %2:d %3:d %4:d %5:d %6:d %7:d %8:d %9:d %9:d "), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9);
  2027. EATEST_VERIFY(result == -1);
  2028. memset(buffer, 0, sizeof(buffer));
  2029. result = OSprintf(buffer, EA_CHAR32("%00000000000000000000:f"), 0.f);
  2030. EATEST_VERIFY(result == -1);
  2031. memset(buffer, 0, sizeof(buffer));
  2032. result = OSprintf(buffer, EA_CHAR32("%0:000000000000000000f"), 0.f);
  2033. EATEST_VERIFY(result == -1);
  2034. memset(buffer, 0, sizeof(buffer));
  2035. result = OSprintf(buffer, EA_CHAR32("%0:.000000000000000000f"), 0.f);
  2036. EATEST_VERIFY(result == -1);
  2037. memset(buffer, 0, sizeof(buffer));
  2038. result = OSprintf(buffer, EA_CHAR32("%000000000000000000:000000000000000000.000000000000000000f"), 0.f);
  2039. EATEST_VERIFY(result == -1);
  2040. }
  2041. // Test OVsnprintf capacity limits
  2042. memset(buffer, 0, sizeof(buffer));
  2043. result = OSnprintf(buffer, 0, EA_CHAR32("%2:1.0f %3:d %1:c"), (char)'3', (float)1.f, (int)2);
  2044. EATEST_VERIFY((result == 5) && (buffer[0] == 0));
  2045. }
  2046. return nErrorCount;
  2047. }
  2048. ///////////////////////////////////////////////////////////////////////////////
  2049. // TestDeprecated
  2050. ///////////////////////////////////////////////////////////////////////////////
  2051. static int StringWriterOld8(const char8_t* EA_RESTRICT pData, size_t nCount, void* EA_RESTRICT pContext8)
  2052. {
  2053. eastl::string8* pString8 = static_cast<eastl::string8*>(pContext8);
  2054. pString8->append(pData, (eastl_size_t)nCount);
  2055. return (int)nCount;
  2056. }
  2057. static int StringWriterOld16(const char16_t* EA_RESTRICT pData, size_t nCount, void* EA_RESTRICT pContext16)
  2058. {
  2059. eastl::string16* pString16 = static_cast<eastl::string16*>(pContext16);
  2060. pString16->append(pData, (eastl_size_t)nCount);
  2061. return (int)nCount;
  2062. }
  2063. static int TestDeprecated()
  2064. {
  2065. using namespace EA::StdC;
  2066. int nErrorCount = 0;
  2067. {
  2068. eastl::string8 s8;
  2069. eastl::string16 s16;
  2070. int result;
  2071. result = Cprintf(StringWriterOld8, &s8, "Hello world");
  2072. EATEST_VERIFY(result == (int)Strlen("Hello world"));
  2073. EATEST_VERIFY(s8 == "Hello world");
  2074. result = Cprintf(StringWriterOld16, &s16, EA_CHAR16("Hello world"));
  2075. EATEST_VERIFY(result == (int)Strlen(EA_CHAR16("Hello world")));
  2076. EATEST_VERIFY(s16 == EA_CHAR16("Hello world"));
  2077. }
  2078. return nErrorCount;
  2079. }
  2080. ///////////////////////////////////////////////////////////////////////////////
  2081. // TestSprintf
  2082. ///////////////////////////////////////////////////////////////////////////////
  2083. int TestSprintf()
  2084. {
  2085. int nErrorCount(0);
  2086. EA::UnitTest::Report("TestSprintf\n");
  2087. // Regular sprintf
  2088. nErrorCount += TestSprintf8();
  2089. nErrorCount += TestSprintf16();
  2090. nErrorCount += TestSprintf32();
  2091. // Dprintf
  2092. nErrorCount += TestDrintf8();
  2093. // Ordered sprintf
  2094. nErrorCount += TestOsprintf8();
  2095. nErrorCount += TestOsprintf16();
  2096. nErrorCount += TestOsprintf32();
  2097. // Test deprecated functionality
  2098. nErrorCount += TestDeprecated();
  2099. return nErrorCount;
  2100. }