String.cpp 126 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "UserTypes.h"
  9. #include <AzCore/std/string/string.h>
  10. #include <AzCore/std/string/conversions.h>
  11. #include <AzCore/std/string/tokenize.h>
  12. #include <AzCore/std/string/alphanum.h>
  13. #include <AzCore/std/sort.h>
  14. #include <AzCore/std/allocator_stateless.h>
  15. #include <AzCore/std/containers/map.h>
  16. #include <AzCore/std/containers/set.h>
  17. #include <AzCore/std/containers/array.h>
  18. #include <AzCore/std/containers/span.h>
  19. #include <AzCore/std/ranges/join_view.h>
  20. #include <AzCore/std/ranges/transform_view.h>
  21. #include <AzCore/std/string/regex.h>
  22. #include <AzCore/std/string/wildcard.h>
  23. #include <AzCore/std/string/fixed_string.h>
  24. #include <AzCore/std/typetraits/is_convertible.h>
  25. // we need this for AZ_TEST_FLOAT compare
  26. #include <cinttypes>
  27. #include <string>
  28. #include <string_view>
  29. // Because of the SSO (small string optimization) we always shoule have capacity != 0 and data != 0
  30. #define AZ_TEST_VALIDATE_EMPTY_STRING(_String) \
  31. EXPECT_TRUE(_String.validate()); \
  32. EXPECT_EQ(0, _String.size()); \
  33. EXPECT_TRUE(_String.empty()); \
  34. EXPECT_TRUE(_String.begin() == _String.end()); \
  35. EXPECT_NE(0, _String.capacity()); \
  36. EXPECT_NE(nullptr, _String.data()); \
  37. EXPECT_EQ(0, strlen(_String.c_str())); \
  38. EXPECT_TRUE(_String.data() == _String.c_str())
  39. #define AZ_TEST_VALIDATE_STRING(_String, _NumElements) \
  40. EXPECT_TRUE(_String.validate()); \
  41. EXPECT_EQ(_NumElements, _String.size()); \
  42. EXPECT_TRUE((_String.size() > 0) ? !_String.empty() : _String.empty()); \
  43. EXPECT_TRUE((_NumElements > 0) ? _String.capacity() >= _NumElements : true); \
  44. EXPECT_TRUE((_NumElements > 0) ? _String.begin() != _String.end() : _String.begin() == _String.end()); \
  45. EXPECT_FALSE(_String.empty()); \
  46. EXPECT_NE(nullptr, _String.data()); \
  47. EXPECT_EQ(_NumElements, strlen(_String.c_str()));
  48. #define AZ_TEST_VALIDATE_WSTRING(_String, _NumElements) \
  49. EXPECT_TRUE(_String.validate()); \
  50. EXPECT_EQ(_NumElements, _String.size()); \
  51. EXPECT_TRUE((_String.size() > 0) ? !_String.empty() : _String.empty()); \
  52. EXPECT_TRUE((_NumElements > 0) ? _String.capacity() >= _NumElements : true); \
  53. EXPECT_TRUE((_NumElements > 0) ? _String.begin() != _String.end() : _String.begin() == _String.end()); \
  54. EXPECT_FALSE(_String.empty()); \
  55. EXPECT_NE(nullptr, _String.data()); \
  56. EXPECT_EQ(_NumElements, wcslen(_String.c_str()));
  57. #if defined(AZ_COMPILER_MSVC) // just for a test purpose (we actully leak the memory)
  58. # define strdup _strdup
  59. #endif
  60. namespace UnitTest
  61. {
  62. void TestVSNPrintf(char* buffer, size_t bufferSize, const char* format, ...)
  63. {
  64. va_list mark;
  65. va_start(mark, format);
  66. azvsnprintf(buffer, bufferSize, format, mark);
  67. va_end(mark);
  68. }
  69. void TestVSWNPrintf(wchar_t* buffer, size_t bufferSize, const wchar_t* format, ...)
  70. {
  71. va_list mark;
  72. va_start(mark, format);
  73. azvsnwprintf(buffer, bufferSize, format, mark);
  74. va_end(mark);
  75. }
  76. TEST(StringC, VSNPrintf)
  77. {
  78. char buffer32[32];
  79. TestVSNPrintf(buffer32, AZ_ARRAY_SIZE(buffer32), "This is a buffer test %s", "Bla2");
  80. EXPECT_EQ(0, strcmp(buffer32, "This is a buffer test Bla2"));
  81. }
  82. TEST(StringC, VSWNPrintf)
  83. {
  84. wchar_t wbuffer32[32];
  85. TestVSWNPrintf(wbuffer32, AZ_ARRAY_SIZE(wbuffer32), L"This is a buffer test %ls", L"Bla3");
  86. AZ_TEST_ASSERT(wcscmp(wbuffer32, L"This is a buffer test Bla3") == 0);
  87. }
  88. TEST(StringC, AZSNPrintf)
  89. {
  90. char buffer32[32];
  91. azsnprintf(buffer32, AZ_ARRAY_SIZE(buffer32), "This is a buffer test %s", "Bla");
  92. EXPECT_EQ(0, strcmp(buffer32, "This is a buffer test Bla"));
  93. }
  94. TEST(StringC, AZSWNPrintf)
  95. {
  96. wchar_t wbuffer32[32];
  97. azsnwprintf(wbuffer32, AZ_ARRAY_SIZE(wbuffer32), L"This is a buffer test %ls", L"Bla1");
  98. EXPECT_EQ(0, wcscmp(wbuffer32, L"This is a buffer test Bla1"));
  99. }
  100. TEST(StringC, AZStrcat)
  101. {
  102. char buffer32[32];
  103. azsnprintf(buffer32, AZ_ARRAY_SIZE(buffer32), "This is a buffer test %s", "Bla2");
  104. azstrcat(buffer32, AZ_ARRAY_SIZE(buffer32), "_1");
  105. EXPECT_EQ(0, strcmp(buffer32, "This is a buffer test Bla2_1"));
  106. }
  107. TEST(StringC, AZStrncat)
  108. {
  109. char buffer32[32];
  110. azsnprintf(buffer32, AZ_ARRAY_SIZE(buffer32), "This is a buffer test %s", "Bla2");
  111. azstrncat(buffer32, AZ_ARRAY_SIZE(buffer32), "_23", 2);
  112. EXPECT_EQ(0, strcmp(buffer32, "This is a buffer test Bla2_2"));
  113. }
  114. TEST(StringC, AZStrcpy)
  115. {
  116. char buffer32[32];
  117. azstrcpy(buffer32, AZ_ARRAY_SIZE(buffer32), "Bla Bla 1");
  118. EXPECT_EQ(0, strcmp(buffer32, "Bla Bla 1"));
  119. }
  120. TEST(StringC, AZStrncpy)
  121. {
  122. char buffer32[32];
  123. azstrncpy(buffer32, AZ_ARRAY_SIZE(buffer32), "Gla Gla 1", 7);
  124. // azstrncpy note: if count is reached before the entire array src was copied, the resulting character array is not null-terminated.
  125. buffer32[7] = '\0';
  126. EXPECT_EQ(0, strcmp(buffer32, "Gla Gla"));
  127. }
  128. TEST(StringC, AZStricmp)
  129. {
  130. char buffer32[32];
  131. azstrncpy(buffer32, AZ_ARRAY_SIZE(buffer32), "Gla Gla 1", 7);
  132. // azstrncpy note: if count is reached before the entire array src was copied, the resulting character array is not null-terminated.
  133. buffer32[7] = '\0';
  134. EXPECT_EQ(0, azstricmp(buffer32, "gla gla"));
  135. }
  136. TEST(StringC, AZStrnicmp)
  137. {
  138. char buffer32[32];
  139. azstrncpy(buffer32, AZ_ARRAY_SIZE(buffer32), "Gla Gla 1", 7);
  140. EXPECT_EQ(0, azstrnicmp(buffer32, "gla", 3));
  141. }
  142. class String
  143. : public LeakDetectionFixture
  144. {
  145. };
  146. TEST_F(String, Basic)
  147. {
  148. const char* sChar = "SSO string"; // 10 characters
  149. const char* sCharLong = "This is a long string test that will allocate"; // 45 characters
  150. AZStd::array<char, 6> aChar = {
  151. { 'a', 'b', 'c', 'd', 'e', 'f' }
  152. }; // short string (should use SSO)
  153. AZStd::string str1;
  154. AZ_TEST_VALIDATE_EMPTY_STRING(str1);
  155. // short char*
  156. AZStd::string str2(sChar);
  157. AZ_TEST_VALIDATE_STRING(str2, 10);
  158. AZStd::string str2_1("");
  159. AZ_TEST_VALIDATE_EMPTY_STRING(str2_1);
  160. AZStd::string str3(sChar, 5);
  161. AZ_TEST_VALIDATE_STRING(str3, 5);
  162. // long char*
  163. AZStd::string str4(sCharLong);
  164. AZ_TEST_VALIDATE_STRING(str4, 45);
  165. AZStd::string str5(sCharLong, 35);
  166. AZ_TEST_VALIDATE_STRING(str5, 35);
  167. // element
  168. AZStd::string str6(13, 'a');
  169. AZ_TEST_VALIDATE_STRING(str6, 13);
  170. AZStd::string str6_1(0, 'a');
  171. AZ_TEST_VALIDATE_EMPTY_STRING(str6_1);
  172. AZStd::string str7(aChar.begin(), aChar.end());
  173. AZ_TEST_VALIDATE_STRING(str7, 6);
  174. AZStd::string str7_1(aChar.begin(), aChar.begin());
  175. AZ_TEST_VALIDATE_EMPTY_STRING(str7_1);
  176. AZStd::string str8(sChar, sChar + 3);
  177. AZ_TEST_VALIDATE_STRING(str8, 3);
  178. AZStd::string str8_1(sChar, sChar);
  179. AZ_TEST_VALIDATE_EMPTY_STRING(str8_1);
  180. //
  181. AZStd::string str9(str2);
  182. AZ_TEST_VALIDATE_STRING(str9, 10);
  183. AZStd::string str9_1(str1);
  184. AZ_TEST_VALIDATE_EMPTY_STRING(str9_1);
  185. AZStd::string str10(str2, 4);
  186. AZ_TEST_VALIDATE_STRING(str10, 6);
  187. AZStd::string str11(str2, 4, 3);
  188. AZ_TEST_VALIDATE_STRING(str11, 3);
  189. AZStd::string str12(sChar);
  190. AZStd::string large = sCharLong;
  191. // move ctor
  192. AZStd::string strSm = AZStd::move(str12);
  193. AZ_TEST_VALIDATE_STRING(strSm, 10);
  194. AZ_TEST_VALIDATE_EMPTY_STRING(str12);
  195. AZStd::string strLg(AZStd::move(large));
  196. AZ_TEST_VALIDATE_STRING(strLg, 45);
  197. AZ_TEST_VALIDATE_EMPTY_STRING(large);
  198. AZStd::string strEmpty(AZStd::move(str1));
  199. AZ_TEST_VALIDATE_EMPTY_STRING(strEmpty);
  200. AZ_TEST_VALIDATE_EMPTY_STRING(str1);
  201. // move assign
  202. str12 = sChar; // reset
  203. large = sCharLong;
  204. // move small string into small string
  205. strSm = AZStd::move(str12);
  206. AZ_TEST_VALIDATE_STRING(strSm, 10);
  207. AZ_TEST_VALIDATE_EMPTY_STRING(str12);
  208. // move large string into large string
  209. strLg = AZStd::move(large);
  210. AZ_TEST_VALIDATE_STRING(strLg, 45);
  211. AZ_TEST_VALIDATE_EMPTY_STRING(large);
  212. str12 = sChar; // reset
  213. large = sCharLong;
  214. // move large string into small string
  215. strSm = AZStd::move(large);
  216. AZ_TEST_VALIDATE_STRING(strSm, 45);
  217. AZ_TEST_VALIDATE_EMPTY_STRING(large);
  218. // move small string into large string
  219. strLg = AZStd::move(str12);
  220. AZ_TEST_VALIDATE_STRING(strLg, 10);
  221. AZ_TEST_VALIDATE_EMPTY_STRING(str12);
  222. // clear small and large, validate empty
  223. strSm.clear();
  224. AZ_TEST_VALIDATE_EMPTY_STRING(strSm);
  225. strLg.clear();
  226. AZ_TEST_VALIDATE_EMPTY_STRING(strLg);
  227. str2.append(str3);
  228. AZ_TEST_VALIDATE_STRING(str2, 15);
  229. AZ_TEST_ASSERT(str2[10] == 'S');
  230. str3.append(str4, 10, 4);
  231. AZ_TEST_VALIDATE_STRING(str3, 9);
  232. AZ_TEST_ASSERT(str3[5] == 'l');
  233. str4.append(sChar);
  234. AZ_TEST_VALIDATE_STRING(str4, 55);
  235. AZ_TEST_ASSERT(str4[45] == 'S');
  236. str5.append(10, 'b');
  237. AZ_TEST_VALIDATE_STRING(str5, 45);
  238. AZ_TEST_ASSERT(str5[35] == 'b');
  239. str6.append(aChar.begin(), aChar.end());
  240. AZ_TEST_VALIDATE_STRING(str6, 19);
  241. AZ_TEST_ASSERT(str6[14] == 'b');
  242. str7.append(sCharLong + 10, sCharLong + 14);
  243. AZ_TEST_VALIDATE_STRING(str7, 10);
  244. AZ_TEST_ASSERT(str7[6] == 'l');
  245. str2.assign(str9);
  246. AZ_TEST_VALIDATE_STRING(str2, 10);
  247. AZ_TEST_ASSERT(str2[0] == 'S');
  248. str3.assign(str9, 5, 5);
  249. AZ_TEST_VALIDATE_STRING(str3, 5);
  250. AZ_TEST_ASSERT(str3[0] == 't');
  251. str2.assign(sCharLong, 25);
  252. AZ_TEST_VALIDATE_STRING(str2, 25);
  253. AZ_TEST_ASSERT(str2[10] == 'l');
  254. str2.assign(sChar);
  255. AZ_TEST_VALIDATE_STRING(str2, 10);
  256. AZ_TEST_ASSERT(str2[0] == 'S');
  257. str2.assign(5, 'a');
  258. AZ_TEST_VALIDATE_STRING(str2, 5);
  259. AZ_TEST_ASSERT(str2[4] == 'a');
  260. str2.assign(aChar.begin(), aChar.end());
  261. AZ_TEST_VALIDATE_STRING(str2, 6);
  262. AZ_TEST_ASSERT(str2[1] == 'b');
  263. str2.assign(sChar, sChar + 5);
  264. AZ_TEST_VALIDATE_STRING(str2, 5);
  265. AZ_TEST_ASSERT(str2[0] == 'S');
  266. str1.clear();
  267. AZ_TEST_VALIDATE_EMPTY_STRING(str1);
  268. str1.assign(sCharLong);
  269. AZ_TEST_VALIDATE_STRING(str1, 45);
  270. AZ_TEST_ASSERT(str1[10] == 'l');
  271. str1.insert(10, str9, 4, 6);
  272. AZ_TEST_VALIDATE_STRING(str1, 51);
  273. AZ_TEST_ASSERT(str1[10] == 's');
  274. str2.insert(3, sChar, 5);
  275. AZ_TEST_VALIDATE_STRING(str2, 10);
  276. AZ_TEST_ASSERT(str2[0] == 'S');
  277. AZ_TEST_ASSERT(str2[3] == 'S');
  278. str2.insert(5, sChar);
  279. AZ_TEST_VALIDATE_STRING(str2, 20);
  280. AZ_TEST_ASSERT(str2[4] == 'S');
  281. str2.insert(10, 5, 'g');
  282. AZ_TEST_VALIDATE_STRING(str2, 25);
  283. AZ_TEST_ASSERT(str2[10] == 'g');
  284. AZ_TEST_ASSERT(str2[14] == 'g');
  285. str2.insert(str2.end(), 'b');
  286. AZ_TEST_VALIDATE_STRING(str2, 26);
  287. AZ_TEST_ASSERT(str2[25] == 'b');
  288. str2.insert(str2.end(), 2, 'c');
  289. AZ_TEST_VALIDATE_STRING(str2, 28);
  290. AZ_TEST_ASSERT(str2[26] == 'c');
  291. AZ_TEST_ASSERT(str2[27] == 'c');
  292. str2.insert(str2.begin(), aChar.begin(), aChar.end());
  293. AZ_TEST_VALIDATE_STRING(str2, 34);
  294. AZ_TEST_ASSERT(str2[0] == 'a');
  295. AZ_TEST_ASSERT(str2[1] == 'b');
  296. str2.erase(16, 5);
  297. AZ_TEST_VALIDATE_STRING(str2, 29);
  298. AZ_TEST_ASSERT(str2[10] != 'g');
  299. AZ_TEST_ASSERT(str2[14] != 'g');
  300. str2.erase(str2.begin());
  301. AZ_TEST_VALIDATE_STRING(str2, 28);
  302. AZ_TEST_ASSERT(str2[0] == 'b');
  303. str2.erase(str2.begin(), AZStd::next(str2.begin(), 4));
  304. AZ_TEST_VALIDATE_STRING(str2, 24);
  305. AZ_TEST_ASSERT(str2[0] == 'f');
  306. str1.assign(aChar.begin(), aChar.end());
  307. str2.replace(1, 6, str1);
  308. AZ_TEST_VALIDATE_STRING(str2, 24);
  309. AZ_TEST_ASSERT(str2[0] == 'f');
  310. AZ_TEST_ASSERT(str2[1] == 'a');
  311. AZ_TEST_ASSERT(str2[5] == 'e');
  312. str2.replace(6, 1, str1, 5, 1);
  313. AZ_TEST_VALIDATE_STRING(str2, 24);
  314. AZ_TEST_ASSERT(str2[6] == 'f');
  315. str2.replace(3, 2, sCharLong, 2);
  316. AZ_TEST_VALIDATE_STRING(str2, 24);
  317. AZ_TEST_ASSERT(str2[3] == 'T');
  318. AZ_TEST_ASSERT(str2[4] == 'h');
  319. str2.replace(3, 10, sChar);
  320. AZ_TEST_VALIDATE_STRING(str2, 24);
  321. AZ_TEST_ASSERT(str2[3] == 'S');
  322. AZ_TEST_ASSERT(str2[4] == 'S');
  323. str2.replace(3, 2, 2, 'g');
  324. AZ_TEST_VALIDATE_STRING(str2, 24);
  325. AZ_TEST_ASSERT(str2[3] == 'g');
  326. AZ_TEST_ASSERT(str2[4] == 'g');
  327. str2.replace(str2.begin(), AZStd::next(str2.begin(), str1.length()), str1);
  328. AZ_TEST_VALIDATE_STRING(str2, 24);
  329. AZ_TEST_ASSERT(str2[0] == 'a');
  330. AZ_TEST_ASSERT(str2[1] == 'b');
  331. str2.replace(str2.begin(), AZStd::next(str2.begin(), 10), sChar);
  332. AZ_TEST_VALIDATE_STRING(str2, 24);
  333. AZ_TEST_ASSERT(str2[0] == 'S');
  334. AZ_TEST_ASSERT(str2[1] == 'S');
  335. str2.replace(str2.begin(), AZStd::next(str2.begin(), 3), sChar, 3);
  336. AZ_TEST_VALIDATE_STRING(str2, 24);
  337. AZ_TEST_ASSERT(str2[0] == 'S');
  338. AZ_TEST_ASSERT(str2[1] == 'S');
  339. AZ_TEST_ASSERT(str2[2] == 'O');
  340. str2.replace(str2.begin(), AZStd::next(str2.begin(), 2), 2, 'h');
  341. AZ_TEST_VALIDATE_STRING(str2, 24);
  342. AZ_TEST_ASSERT(str2[0] == 'h');
  343. AZ_TEST_ASSERT(str2[1] == 'h');
  344. str2.replace(str2.begin(), AZStd::next(str2.begin(), 2), aChar.begin(), AZStd::next(aChar.begin(), 2));
  345. AZ_TEST_VALIDATE_STRING(str2, 24);
  346. AZ_TEST_ASSERT(str2[0] == 'a');
  347. AZ_TEST_ASSERT(str2[1] == 'b');
  348. str2.replace(str2.begin(), AZStd::next(str2.begin(), 2), sChar, sChar + 5);
  349. AZ_TEST_VALIDATE_STRING(str2, 27);
  350. AZ_TEST_ASSERT(str2[0] == 'S');
  351. AZ_TEST_ASSERT(str2[1] == 'S');
  352. AZ_TEST_ASSERT(str2.at(0) == 'S');
  353. str2.at(0) = 'E';
  354. AZ_TEST_ASSERT(str2.at(0) == 'E');
  355. str2[0] = 'G';
  356. AZ_TEST_ASSERT(str2.at(0) == 'G');
  357. AZ_TEST_ASSERT(str2.front() == 'G');
  358. str2.front() = 'X';
  359. AZ_TEST_ASSERT(str2.front() == 'X');
  360. AZ_TEST_ASSERT(str2.back() == 'c'); // From the insert of 2 'c's at the end() further up.
  361. str2.back() = 'p';
  362. AZ_TEST_ASSERT(str2.back() == 'p');
  363. AZ_TEST_ASSERT(str2.c_str() != nullptr);
  364. AZ_TEST_ASSERT(::strlen(str2.c_str()) == str2.length());
  365. str2.resize(30, 'm');
  366. AZ_TEST_VALIDATE_STRING(str2, 30);
  367. AZ_TEST_ASSERT(str2[29] == 'm');
  368. str2.reserve(100);
  369. AZ_TEST_VALIDATE_STRING(str2, 30);
  370. AZ_TEST_ASSERT(str2.capacity() >= 100);
  371. char myCharArray[128]; // make sure it's big enough or use make the copy safe
  372. AZ_TEST_ASSERT(str2.copy(myCharArray, AZ_ARRAY_SIZE(myCharArray), 1) == str2.length() - 1);
  373. str1.clear();
  374. str2.swap(str1);
  375. AZ_TEST_VALIDATE_STRING(str1, 30);
  376. AZ_TEST_VALIDATE_EMPTY_STRING(str2);
  377. str1.assign(sChar);
  378. str2.assign(sChar + 2, sChar + 5);
  379. str1.append(sChar);
  380. AZStd::size_t pos;
  381. pos = str1.find(str2);
  382. AZ_TEST_ASSERT(pos == 2);
  383. pos = str1.find(str2, 1);
  384. AZ_TEST_ASSERT(pos == 2);
  385. pos = str1.find(str2, 3); // skip the first
  386. AZ_TEST_ASSERT(pos == 12);
  387. pos = str1.find(sChar, 1, 10);
  388. AZ_TEST_ASSERT(pos == 10);
  389. const char sStr[] = "string";
  390. pos = str1.find(sStr);
  391. AZ_TEST_ASSERT(pos == 4);
  392. pos = str1.find('O');
  393. AZ_TEST_ASSERT(pos == 2);
  394. pos = str1.find('Z');
  395. AZ_TEST_ASSERT(pos == AZStd::string::npos);
  396. pos = str1.rfind(str2);
  397. AZ_TEST_ASSERT(pos == 12);
  398. pos = str1.rfind(str2);
  399. AZ_TEST_ASSERT(pos == 12);
  400. pos = str1.rfind(sChar, 0, 10);
  401. AZ_TEST_ASSERT(pos == 0);
  402. pos = str1.rfind(sChar);
  403. AZ_TEST_ASSERT(pos == 10);
  404. pos = str1.rfind(sChar, 11);
  405. AZ_TEST_ASSERT(pos == 10);
  406. pos = str1.rfind('O');
  407. AZ_TEST_ASSERT(pos == 12);
  408. pos = str1.rfind('Z');
  409. AZ_TEST_ASSERT(pos == AZStd::string::npos);
  410. pos = str1.find_first_of(str2);
  411. AZ_TEST_ASSERT(pos == 2);
  412. pos = str1.find_first_of(str2, 10);
  413. AZ_TEST_ASSERT(pos == 12);
  414. pos = str1.find_first_of(sChar, 0, 15);
  415. AZ_TEST_ASSERT(pos == 0);
  416. pos = str1.find_first_of(sChar, 3, 10);
  417. AZ_TEST_ASSERT(pos == 3);
  418. pos = str1.find_first_of(sChar, 7);
  419. AZ_TEST_ASSERT(pos == 7);
  420. pos = str1.find_first_of(sChar);
  421. AZ_TEST_ASSERT(pos == 0);
  422. pos = str1.find_first_of('O');
  423. AZ_TEST_ASSERT(pos == 2);
  424. pos = str1.find_first_of('O', 10);
  425. AZ_TEST_ASSERT(pos == 12);
  426. pos = str1.find_first_of('Z');
  427. AZ_TEST_ASSERT(pos == AZStd::string::npos);
  428. pos = str1.find_last_of(str2);
  429. AZ_TEST_ASSERT(pos == 14);
  430. pos = str1.find_last_of(str2, 3);
  431. AZ_TEST_ASSERT(pos == 3);
  432. pos = str1.find_last_of(sChar, 4);
  433. AZ_TEST_ASSERT(pos == 4);
  434. pos = str1.find_last_of('O');
  435. AZ_TEST_ASSERT(pos == 12);
  436. pos = str1.find_last_of('Z');
  437. AZ_TEST_ASSERT(pos == AZStd::string::npos);
  438. pos = str1.find_first_not_of(str2, 3);
  439. AZ_TEST_ASSERT(pos == 5);
  440. pos = str1.find_first_not_of('Z');
  441. AZ_TEST_ASSERT(pos == 0);
  442. pos = str1.find_last_not_of(sChar);
  443. AZ_TEST_ASSERT(pos == AZStd::string::npos);
  444. pos = str1.find_last_not_of('Z');
  445. AZ_TEST_ASSERT(pos == 19);
  446. AZStd::string sub = str1.substr(0, 10);
  447. AZ_TEST_VALIDATE_STRING(sub, 10);
  448. AZ_TEST_ASSERT(sub[0] == 'S');
  449. AZ_TEST_ASSERT(sub[9] == 'g');
  450. int cmpRes;
  451. cmpRes = str1.compare(str1);
  452. AZ_TEST_ASSERT(cmpRes == 0);
  453. cmpRes = str1.compare(str2);
  454. AZ_TEST_ASSERT(cmpRes > 0);
  455. cmpRes = str1.compare(2, 3, str2);
  456. AZ_TEST_ASSERT(cmpRes == 0);
  457. cmpRes = str1.compare(12, 2, str2, 0, 2);
  458. AZ_TEST_ASSERT(cmpRes == 0);
  459. cmpRes = str1.compare(3, 1, str2, 0, 1);
  460. AZ_TEST_ASSERT(cmpRes < 0);
  461. cmpRes = str1.compare(sChar);
  462. AZ_TEST_ASSERT(cmpRes > 0);
  463. cmpRes = str1.compare(10, 10, sChar);
  464. AZ_TEST_ASSERT(cmpRes == 0);
  465. cmpRes = str1.compare(11, 3, sChar, 3);
  466. AZ_TEST_ASSERT(cmpRes < 0);
  467. using iteratorType = char;
  468. auto testValue = str4;
  469. AZStd::reverse_iterator<iteratorType*> rend = testValue.rend();
  470. AZStd::reverse_iterator<const iteratorType*> crend1 = testValue.rend();
  471. AZStd::reverse_iterator<const iteratorType*> crend2 = testValue.crend();
  472. AZStd::reverse_iterator<iteratorType*> rbegin = testValue.rbegin();
  473. AZStd::reverse_iterator<const iteratorType*> crbegin1 = testValue.rbegin();
  474. AZStd::reverse_iterator<const iteratorType*> crbegin2 = testValue.crbegin();
  475. AZ_TEST_ASSERT(rend == crend1);
  476. AZ_TEST_ASSERT(crend1 == crend2);
  477. AZ_TEST_ASSERT(rbegin == crbegin1);
  478. AZ_TEST_ASSERT(crbegin1 == crbegin2);
  479. AZ_TEST_ASSERT(rbegin != rend);
  480. str1.set_capacity(3);
  481. AZ_TEST_VALIDATE_STRING(str1, 3);
  482. AZ_TEST_ASSERT(str1[0] == 'S');
  483. AZ_TEST_ASSERT(str1[1] == 'S');
  484. AZ_TEST_ASSERT(str1[2] == 'O');
  485. str1.clear();
  486. for (int i = 0; i < 10000; ++i)
  487. {
  488. str1 += 'i';
  489. }
  490. AZ_TEST_ASSERT(str1.size() == 10000);
  491. for (int i = 0; i < 10000; ++i)
  492. {
  493. AZ_TEST_ASSERT(str1[i] == 'i');
  494. }
  495. }
  496. TEST_F(String, Algorithms)
  497. {
  498. AZStd::string str = AZStd::string::format("%s %d", "BlaBla", 5);
  499. AZ_TEST_VALIDATE_STRING(str, 8);
  500. AZStd::wstring wstr = AZStd::wstring::format(L"%ls %d", L"BlaBla", 5);
  501. AZ_TEST_VALIDATE_WSTRING(wstr, 8);
  502. AZStd::to_lower(str.begin(), str.end());
  503. AZ_TEST_ASSERT(str[0] == 'b');
  504. AZ_TEST_ASSERT(str[3] == 'b');
  505. AZStd::to_upper(str.begin(), str.end());
  506. AZ_TEST_ASSERT(str[1] == 'L');
  507. AZ_TEST_ASSERT(str[2] == 'A');
  508. AZStd::string intStr("10");
  509. int ival = AZStd::stoi(intStr);
  510. AZ_TEST_ASSERT(ival == 10);
  511. AZStd::wstring wintStr(L"10");
  512. ival = AZStd::stoi(wintStr);
  513. AZ_TEST_ASSERT(ival == 10);
  514. AZStd::string floatStr("2.32");
  515. float fval = AZStd::stof(floatStr);
  516. AZ_TEST_ASSERT_FLOAT_CLOSE(fval, 2.32f);
  517. AZStd::wstring wfloatStr(L"2.32");
  518. fval = AZStd::stof(wfloatStr);
  519. AZ_TEST_ASSERT_FLOAT_CLOSE(fval, 2.32f);
  520. // wstring to string
  521. AZStd::string str1;
  522. AZStd::to_string(str1, wstr);
  523. AZ_TEST_ASSERT(str1 == "BlaBla 5");
  524. EXPECT_EQ(8, to_string_length(wstr));
  525. str1 = AZStd::string::format("%ls", wstr.c_str());
  526. AZ_TEST_ASSERT(str1 == "BlaBla 5");
  527. // string to wstring
  528. AZStd::wstring wstr1;
  529. AZStd::to_wstring(wstr1, str);
  530. AZ_TEST_ASSERT(wstr1 == L"BLABLA 5");
  531. wstr1 = AZStd::wstring::format(L"%hs", str.c_str());
  532. AZ_TEST_ASSERT(wstr1 == L"BLABLA 5");
  533. // wstring to char buffer
  534. char strBuffer[9];
  535. AZStd::to_string(strBuffer, 9, wstr1.c_str());
  536. AZ_TEST_ASSERT(0 == azstricmp(strBuffer, "BLABLA 5"));
  537. EXPECT_EQ(8, to_string_length(wstr1));
  538. // wstring to char with unicode
  539. AZStd::wstring ws1InfinityEscaped = L"Infinity: \u221E"; // escaped
  540. EXPECT_EQ(13, to_string_length(ws1InfinityEscaped));
  541. // wchar_t buffer to char buffer
  542. wchar_t wstrBuffer[9] = L"BLABLA 5";
  543. memset(strBuffer, 0, AZ_ARRAY_SIZE(strBuffer));
  544. AZStd::to_string(strBuffer, 9, wstrBuffer);
  545. AZ_TEST_ASSERT(0 == azstricmp(strBuffer, "BLABLA 5"));
  546. // string to wchar_t buffer
  547. memset(wstrBuffer, 0, AZ_ARRAY_SIZE(wstrBuffer));
  548. AZStd::to_wstring(wstrBuffer, 9, str1.c_str());
  549. AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BlaBla 5"));
  550. // char buffer to wchar_t buffer
  551. memset(wstrBuffer, L' ', AZ_ARRAY_SIZE(wstrBuffer)); // to check that the null terminator is properly placed
  552. AZStd::to_wstring(wstrBuffer, 9, strBuffer);
  553. AZ_TEST_ASSERT(0 == azwcsicmp(wstrBuffer, L"BLABLA 5"));
  554. // wchar UTF16/UTF32 to/from Utf8
  555. wstr1 = L"this is a \u20AC \u00A3 test"; // that's a euro and a pound sterling
  556. AZStd::to_string(str, wstr1);
  557. AZStd::wstring wstr2;
  558. AZStd::to_wstring(wstr2, str);
  559. AZ_TEST_ASSERT(wstr1 == wstr2);
  560. // tokenize
  561. AZStd::vector<AZStd::string> tokens;
  562. AZStd::tokenize(AZStd::string("one, two, three"), AZStd::string(", "), tokens);
  563. AZ_TEST_ASSERT(tokens.size() == 3);
  564. AZ_TEST_ASSERT(tokens[0] == "one");
  565. AZ_TEST_ASSERT(tokens[1] == "two");
  566. AZ_TEST_ASSERT(tokens[2] == "three");
  567. AZStd::tokenize(AZStd::string("one, ,, two, ,, three"), AZStd::string(", "), tokens);
  568. AZ_TEST_ASSERT(tokens.size() == 3);
  569. AZ_TEST_ASSERT(tokens[0] == "one");
  570. AZ_TEST_ASSERT(tokens[1] == "two");
  571. AZ_TEST_ASSERT(tokens[2] == "three");
  572. AZStd::tokenize(AZStd::string("thequickbrownfox"), AZStd::string("ABC"), tokens);
  573. AZ_TEST_ASSERT(tokens.size() == 1);
  574. AZ_TEST_ASSERT(tokens[0] == "thequickbrownfox");
  575. AZStd::tokenize(AZStd::string{}, AZStd::string{}, tokens);
  576. AZ_TEST_ASSERT(tokens.empty());
  577. AZStd::tokenize(AZStd::string("ABC"), AZStd::string("ABC"), tokens);
  578. AZ_TEST_ASSERT(tokens.empty());
  579. AZStd::tokenize(AZStd::string(" foo bar "), AZStd::string(" "), tokens);
  580. AZ_TEST_ASSERT(tokens.size() == 2);
  581. AZ_TEST_ASSERT(tokens[0] == "foo");
  582. AZ_TEST_ASSERT(tokens[1] == "bar");
  583. AZStd::tokenize_keep_empty(AZStd::string(" foo , bar "), AZStd::string(","), tokens);
  584. AZ_TEST_ASSERT(tokens.size() == 2);
  585. AZ_TEST_ASSERT(tokens[0] == " foo ");
  586. AZ_TEST_ASSERT(tokens[1] == " bar ");
  587. // Sort
  588. AZStd::vector<AZStd::string> toSort;
  589. toSort.push_back("z2");
  590. toSort.push_back("z100");
  591. toSort.push_back("z1");
  592. AZStd::sort(toSort.begin(), toSort.end());
  593. AZ_TEST_ASSERT(toSort[0] == "z1");
  594. AZ_TEST_ASSERT(toSort[1] == "z100");
  595. AZ_TEST_ASSERT(toSort[2] == "z2");
  596. // Natural sort
  597. AZ_TEST_ASSERT(AZStd::alphanum_comp("", "") == 0);
  598. AZ_TEST_ASSERT(AZStd::alphanum_comp("", "a") < 0);
  599. AZ_TEST_ASSERT(AZStd::alphanum_comp("a", "") > 0);
  600. AZ_TEST_ASSERT(AZStd::alphanum_comp("a", "a") == 0);
  601. AZ_TEST_ASSERT(AZStd::alphanum_comp("", "9") < 0);
  602. AZ_TEST_ASSERT(AZStd::alphanum_comp("9", "") > 0);
  603. AZ_TEST_ASSERT(AZStd::alphanum_comp("1", "1") == 0);
  604. AZ_TEST_ASSERT(AZStd::alphanum_comp("1", "2") < 0);
  605. AZ_TEST_ASSERT(AZStd::alphanum_comp("3", "2") > 0);
  606. AZ_TEST_ASSERT(AZStd::alphanum_comp("a1", "a1") == 0);
  607. AZ_TEST_ASSERT(AZStd::alphanum_comp("a1", "a2") < 0);
  608. AZ_TEST_ASSERT(AZStd::alphanum_comp("a2", "a1") > 0);
  609. AZ_TEST_ASSERT(AZStd::alphanum_comp("a1a2", "a1a3") < 0);
  610. AZ_TEST_ASSERT(AZStd::alphanum_comp("a1a2", "a1a0") > 0);
  611. AZ_TEST_ASSERT(AZStd::alphanum_comp("134", "122") > 0);
  612. AZ_TEST_ASSERT(AZStd::alphanum_comp("12a3", "12a3") == 0);
  613. AZ_TEST_ASSERT(AZStd::alphanum_comp("12a1", "12a0") > 0);
  614. AZ_TEST_ASSERT(AZStd::alphanum_comp("12a1", "12a2") < 0);
  615. AZ_TEST_ASSERT(AZStd::alphanum_comp("a", "aa") < 0);
  616. AZ_TEST_ASSERT(AZStd::alphanum_comp("aaa", "aa") > 0);
  617. AZ_TEST_ASSERT(AZStd::alphanum_comp("Alpha 2", "Alpha 2") == 0);
  618. AZ_TEST_ASSERT(AZStd::alphanum_comp("Alpha 2", "Alpha 2A") < 0);
  619. AZ_TEST_ASSERT(AZStd::alphanum_comp("Alpha 2 B", "Alpha 2") > 0);
  620. AZStd::string strA("Alpha 2");
  621. AZ_TEST_ASSERT(AZStd::alphanum_comp(strA, "Alpha 2") == 0);
  622. AZ_TEST_ASSERT(AZStd::alphanum_comp(strA, "Alpha 2A") < 0);
  623. AZ_TEST_ASSERT(AZStd::alphanum_comp("Alpha 2 B", strA) > 0);
  624. // show usage of the comparison functor with a set
  625. using StringSetType = AZStd::set<AZStd::string, AZStd::alphanum_less<AZStd::string>>;
  626. StringSetType s;
  627. s.insert("Xiph Xlater 58");
  628. s.insert("Xiph Xlater 5000");
  629. s.insert("Xiph Xlater 500");
  630. s.insert("Xiph Xlater 50");
  631. s.insert("Xiph Xlater 5");
  632. s.insert("Xiph Xlater 40");
  633. s.insert("Xiph Xlater 300");
  634. s.insert("Xiph Xlater 2000");
  635. s.insert("Xiph Xlater 10000");
  636. s.insert("QRS-62F Intrinsia Machine");
  637. s.insert("QRS-62 Intrinsia Machine");
  638. s.insert("QRS-60F Intrinsia Machine");
  639. s.insert("QRS-60 Intrinsia Machine");
  640. s.insert("Callisto Morphamax 7000 SE2");
  641. s.insert("Callisto Morphamax 7000 SE");
  642. s.insert("Callisto Morphamax 7000");
  643. s.insert("Callisto Morphamax 700");
  644. s.insert("Callisto Morphamax 600");
  645. s.insert("Callisto Morphamax 5000");
  646. s.insert("Callisto Morphamax 500");
  647. s.insert("Callisto Morphamax");
  648. s.insert("Alpha 2A-900");
  649. s.insert("Alpha 2A-8000");
  650. s.insert("Alpha 2A");
  651. s.insert("Alpha 200");
  652. s.insert("Alpha 2");
  653. s.insert("Alpha 100");
  654. s.insert("Allegia 60 Clasteron");
  655. s.insert("Allegia 52 Clasteron");
  656. s.insert("Allegia 51B Clasteron");
  657. s.insert("Allegia 51 Clasteron");
  658. s.insert("Allegia 500 Clasteron");
  659. s.insert("Allegia 50 Clasteron");
  660. s.insert("40X Radonius");
  661. s.insert("30X Radonius");
  662. s.insert("20X Radonius Prime");
  663. s.insert("20X Radonius");
  664. s.insert("200X Radonius");
  665. s.insert("10X Radonius");
  666. s.insert("1000X Radonius Maximus");
  667. // check sorting
  668. StringSetType::const_iterator setIt = s.begin();
  669. AZ_TEST_ASSERT(*setIt++ == "10X Radonius");
  670. AZ_TEST_ASSERT(*setIt++ == "20X Radonius");
  671. AZ_TEST_ASSERT(*setIt++ == "20X Radonius Prime");
  672. AZ_TEST_ASSERT(*setIt++ == "30X Radonius");
  673. AZ_TEST_ASSERT(*setIt++ == "40X Radonius");
  674. AZ_TEST_ASSERT(*setIt++ == "200X Radonius");
  675. AZ_TEST_ASSERT(*setIt++ == "1000X Radonius Maximus");
  676. AZ_TEST_ASSERT(*setIt++ == "Allegia 50 Clasteron");
  677. AZ_TEST_ASSERT(*setIt++ == "Allegia 51 Clasteron");
  678. AZ_TEST_ASSERT(*setIt++ == "Allegia 51B Clasteron");
  679. AZ_TEST_ASSERT(*setIt++ == "Allegia 52 Clasteron");
  680. AZ_TEST_ASSERT(*setIt++ == "Allegia 60 Clasteron");
  681. AZ_TEST_ASSERT(*setIt++ == "Allegia 500 Clasteron");
  682. AZ_TEST_ASSERT(*setIt++ == "Alpha 2");
  683. AZ_TEST_ASSERT(*setIt++ == "Alpha 2A");
  684. AZ_TEST_ASSERT(*setIt++ == "Alpha 2A-900");
  685. AZ_TEST_ASSERT(*setIt++ == "Alpha 2A-8000");
  686. AZ_TEST_ASSERT(*setIt++ == "Alpha 100");
  687. AZ_TEST_ASSERT(*setIt++ == "Alpha 200");
  688. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax");
  689. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 500");
  690. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 600");
  691. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 700");
  692. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 5000");
  693. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 7000");
  694. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 7000 SE");
  695. AZ_TEST_ASSERT(*setIt++ == "Callisto Morphamax 7000 SE2");
  696. AZ_TEST_ASSERT(*setIt++ == "QRS-60 Intrinsia Machine");
  697. AZ_TEST_ASSERT(*setIt++ == "QRS-60F Intrinsia Machine");
  698. AZ_TEST_ASSERT(*setIt++ == "QRS-62 Intrinsia Machine");
  699. AZ_TEST_ASSERT(*setIt++ == "QRS-62F Intrinsia Machine");
  700. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 5");
  701. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 40");
  702. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 50");
  703. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 58");
  704. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 300");
  705. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 500");
  706. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 2000");
  707. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 5000");
  708. AZ_TEST_ASSERT(*setIt++ == "Xiph Xlater 10000");
  709. // show usage of comparison functor with a map
  710. using StringIntMapType = AZStd::map<AZStd::string, int, AZStd::alphanum_less<AZStd::string>>;
  711. StringIntMapType m;
  712. m["z1.doc"] = 1;
  713. m["z10.doc"] = 2;
  714. m["z100.doc"] = 3;
  715. m["z101.doc"] = 4;
  716. m["z102.doc"] = 5;
  717. m["z11.doc"] = 6;
  718. m["z12.doc"] = 7;
  719. m["z13.doc"] = 8;
  720. m["z14.doc"] = 9;
  721. m["z15.doc"] = 10;
  722. m["z16.doc"] = 11;
  723. m["z17.doc"] = 12;
  724. m["z18.doc"] = 13;
  725. m["z19.doc"] = 14;
  726. m["z2.doc"] = 15;
  727. m["z20.doc"] = 16;
  728. m["z3.doc"] = 17;
  729. m["z4.doc"] = 18;
  730. m["z5.doc"] = 19;
  731. m["z6.doc"] = 20;
  732. m["z7.doc"] = 21;
  733. m["z8.doc"] = 22;
  734. m["z9.doc"] = 23;
  735. // check sorting
  736. StringIntMapType::const_iterator mapIt = m.begin();
  737. AZ_TEST_ASSERT((mapIt++)->second == 1);
  738. AZ_TEST_ASSERT((mapIt++)->second == 15);
  739. AZ_TEST_ASSERT((mapIt++)->second == 17);
  740. AZ_TEST_ASSERT((mapIt++)->second == 18);
  741. AZ_TEST_ASSERT((mapIt++)->second == 19);
  742. AZ_TEST_ASSERT((mapIt++)->second == 20);
  743. AZ_TEST_ASSERT((mapIt++)->second == 21);
  744. AZ_TEST_ASSERT((mapIt++)->second == 22);
  745. AZ_TEST_ASSERT((mapIt++)->second == 23);
  746. AZ_TEST_ASSERT((mapIt++)->second == 2);
  747. AZ_TEST_ASSERT((mapIt++)->second == 6);
  748. AZ_TEST_ASSERT((mapIt++)->second == 7);
  749. AZ_TEST_ASSERT((mapIt++)->second == 8);
  750. AZ_TEST_ASSERT((mapIt++)->second == 9);
  751. AZ_TEST_ASSERT((mapIt++)->second == 10);
  752. AZ_TEST_ASSERT((mapIt++)->second == 11);
  753. AZ_TEST_ASSERT((mapIt++)->second == 12);
  754. AZ_TEST_ASSERT((mapIt++)->second == 13);
  755. AZ_TEST_ASSERT((mapIt++)->second == 14);
  756. AZ_TEST_ASSERT((mapIt++)->second == 16);
  757. AZ_TEST_ASSERT((mapIt++)->second == 3);
  758. AZ_TEST_ASSERT((mapIt++)->second == 4);
  759. AZ_TEST_ASSERT((mapIt++)->second == 5);
  760. // show usage of comparison functor with an STL algorithm on a vector
  761. AZStd::vector<AZStd::string> v;
  762. // vector contents are reversed sorted contents of the old set
  763. AZStd::copy(s.rbegin(), s.rend(), AZStd::back_inserter(v));
  764. // now sort the vector with the algorithm
  765. AZStd::sort(v.begin(), v.end(), AZStd::alphanum_less<AZStd::string>());
  766. // check values
  767. AZStd::vector<AZStd::string>::const_iterator vecIt = v.begin();
  768. AZ_TEST_ASSERT(*vecIt++ == "10X Radonius");
  769. AZ_TEST_ASSERT(*vecIt++ == "20X Radonius");
  770. AZ_TEST_ASSERT(*vecIt++ == "20X Radonius Prime");
  771. AZ_TEST_ASSERT(*vecIt++ == "30X Radonius");
  772. AZ_TEST_ASSERT(*vecIt++ == "40X Radonius");
  773. AZ_TEST_ASSERT(*vecIt++ == "200X Radonius");
  774. AZ_TEST_ASSERT(*vecIt++ == "1000X Radonius Maximus");
  775. AZ_TEST_ASSERT(*vecIt++ == "Allegia 50 Clasteron");
  776. AZ_TEST_ASSERT(*vecIt++ == "Allegia 51 Clasteron");
  777. AZ_TEST_ASSERT(*vecIt++ == "Allegia 51B Clasteron");
  778. AZ_TEST_ASSERT(*vecIt++ == "Allegia 52 Clasteron");
  779. AZ_TEST_ASSERT(*vecIt++ == "Allegia 60 Clasteron");
  780. AZ_TEST_ASSERT(*vecIt++ == "Allegia 500 Clasteron");
  781. AZ_TEST_ASSERT(*vecIt++ == "Alpha 2");
  782. AZ_TEST_ASSERT(*vecIt++ == "Alpha 2A");
  783. AZ_TEST_ASSERT(*vecIt++ == "Alpha 2A-900");
  784. AZ_TEST_ASSERT(*vecIt++ == "Alpha 2A-8000");
  785. AZ_TEST_ASSERT(*vecIt++ == "Alpha 100");
  786. AZ_TEST_ASSERT(*vecIt++ == "Alpha 200");
  787. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax");
  788. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 500");
  789. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 600");
  790. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 700");
  791. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 5000");
  792. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 7000");
  793. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 7000 SE");
  794. AZ_TEST_ASSERT(*vecIt++ == "Callisto Morphamax 7000 SE2");
  795. AZ_TEST_ASSERT(*vecIt++ == "QRS-60 Intrinsia Machine");
  796. AZ_TEST_ASSERT(*vecIt++ == "QRS-60F Intrinsia Machine");
  797. AZ_TEST_ASSERT(*vecIt++ == "QRS-62 Intrinsia Machine");
  798. AZ_TEST_ASSERT(*vecIt++ == "QRS-62F Intrinsia Machine");
  799. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 5");
  800. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 40");
  801. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 50");
  802. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 58");
  803. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 300");
  804. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 500");
  805. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 2000");
  806. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 5000");
  807. AZ_TEST_ASSERT(*vecIt++ == "Xiph Xlater 10000");
  808. }
  809. // Concept to model if AZStd::to_string(<type>) is a valid expression
  810. template<class T, class = void>
  811. constexpr bool IsToStringInvocable = false;
  812. template<class T>
  813. constexpr bool IsToStringInvocable<T, AZStd::void_t<decltype(AZStd::to_string(AZStd::declval<T>()))>> = true;
  814. TEST_F(String, String_to_stringOverload_DoesNotImplicitlyConvertToBool)
  815. {
  816. AZStd::string intStr;
  817. AZStd::to_string(intStr, 20);
  818. EXPECT_EQ("20", intStr);
  819. EXPECT_EQ("20", AZStd::to_string(static_cast<int16_t>(20)));
  820. EXPECT_EQ("20", AZStd::to_string(static_cast<uint16_t>(20)));
  821. EXPECT_EQ("20", AZStd::to_string(static_cast<int32_t>(20)));
  822. EXPECT_EQ("20", AZStd::to_string(static_cast<uint32_t>(20)));
  823. EXPECT_EQ("20", AZStd::to_string(static_cast<int64_t>(20)));
  824. EXPECT_EQ("20", AZStd::to_string(static_cast<uint64_t>(20)));
  825. EXPECT_EQ("false", AZStd::to_string(false));
  826. EXPECT_EQ("true", AZStd::to_string(true));
  827. // AZStd::to_string should not be invocable with a char or wchar_t literal
  828. static_assert(!IsToStringInvocable<decltype("NarrowStrLiteral")>);
  829. static_assert(!IsToStringInvocable<decltype(L"WideStrLiteral")>);
  830. // AZStd::to_string should be invocable with the following types
  831. static_assert(IsToStringInvocable<bool>);
  832. static_assert(IsToStringInvocable<AZ::s8>);
  833. static_assert(IsToStringInvocable<AZ::u8>);
  834. static_assert(IsToStringInvocable<AZ::s16>);
  835. static_assert(IsToStringInvocable<AZ::u16>);
  836. static_assert(IsToStringInvocable<AZ::s32>);
  837. static_assert(IsToStringInvocable<AZ::u32>);
  838. static_assert(IsToStringInvocable<AZ::s64>);
  839. static_assert(IsToStringInvocable<AZ::u64>);
  840. static_assert(IsToStringInvocable<float>);
  841. static_assert(IsToStringInvocable<double>);
  842. static_assert(IsToStringInvocable<long double>);
  843. }
  844. class Regex
  845. : public LeakDetectionFixture
  846. {
  847. };
  848. TEST_F(Regex, Regex_IPAddressSubnetPattern_Success)
  849. {
  850. // Error case for LY-43888
  851. AZStd::regex txt_regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))?$");
  852. AZStd::string sample_input("10.85.22.92/24");
  853. bool match = AZStd::regex_match(sample_input, txt_regex);
  854. AZ_TEST_ASSERT(match);
  855. }
  856. TEST_F(Regex, MatchConstChar)
  857. {
  858. //regex
  859. AZ_TEST_ASSERT(AZStd::regex_match("subject", AZStd::regex("(sub)(.*)")));
  860. }
  861. TEST_F(Regex, MatchString)
  862. {
  863. AZStd::string reStr("subject");
  864. AZStd::regex re("(sub)(.*)");
  865. AZ_TEST_ASSERT(AZStd::regex_match(reStr, re));
  866. AZ_TEST_ASSERT(AZStd::regex_match(reStr.begin(), reStr.end(), re))
  867. }
  868. TEST_F(Regex, CMatch)
  869. {
  870. AZStd::regex re("(sub)(.*)");
  871. AZStd::cmatch cm; // same as match_results<const char*> cm;
  872. AZStd::regex_match("subject", cm, re);
  873. AZ_TEST_ASSERT(cm.size() == 3);
  874. }
  875. TEST_F(Regex, SMatch)
  876. {
  877. AZStd::string reStr("subject");
  878. AZStd::regex re("(sub)(.*)");
  879. AZStd::smatch sm; // same as std::match_results<string::const_iterator> sm;
  880. AZStd::regex_match(reStr, sm, re);
  881. AZ_TEST_ASSERT(sm.size() == 3);
  882. AZStd::regex_match(reStr.cbegin(), reStr.cend(), sm, re);
  883. AZ_TEST_ASSERT(sm.size() == 3);
  884. }
  885. TEST_F(Regex, CMatchWithFlags)
  886. {
  887. AZStd::regex re("(sub)(.*)");
  888. AZStd::cmatch cm; // same as match_results<const char*> cm;
  889. // using explicit flags:
  890. AZStd::regex_match("subject", cm, re, AZStd::regex_constants::match_default);
  891. AZ_TEST_ASSERT(cm[0] == "subject");
  892. AZ_TEST_ASSERT(cm[1] == "sub");
  893. AZ_TEST_ASSERT(cm[2] == "ject");
  894. }
  895. TEST_F(Regex, PatternMatchFiles)
  896. {
  897. // Simple regular expression matching
  898. AZStd::string fnames[] = { "foo.txt", "bar.txt", "baz.dat", "zoidberg" };
  899. AZStd::regex txt_regex("[a-z]+\\.txt");
  900. for (size_t i = 0; i < AZ_ARRAY_SIZE(fnames); ++i)
  901. {
  902. if (i < 2)
  903. {
  904. AZ_TEST_ASSERT(AZStd::regex_match(fnames[i], txt_regex) == true);
  905. }
  906. else
  907. {
  908. AZ_TEST_ASSERT(AZStd::regex_match(fnames[i], txt_regex) == false);
  909. }
  910. }
  911. }
  912. TEST_F(Regex, PatternWithSingleCaptureGroup)
  913. {
  914. // Extraction of a sub-match
  915. AZStd::string fnames[] = { "foo.txt", "bar.txt", "baz.dat", "zoidberg" };
  916. AZStd::regex base_regex("([a-z]+)\\.txt");
  917. AZStd::smatch base_match;
  918. for (size_t i = 0; i < AZ_ARRAY_SIZE(fnames); ++i)
  919. {
  920. if (AZStd::regex_match(fnames[i], base_match, base_regex))
  921. {
  922. AZ_TEST_ASSERT(base_match.size() == 2);
  923. AZ_TEST_ASSERT(base_match[1] == "foo" || base_match[1] == "bar")
  924. }
  925. }
  926. }
  927. TEST_F(Regex, PatternWithMultipleCaptureGroups)
  928. {
  929. // Extraction of several sub-matches
  930. AZStd::string fnames[] = { "foo.txt", "bar.txt", "baz.dat", "zoidberg" };
  931. AZStd::regex pieces_regex("([a-z]+)\\.([a-z]+)");
  932. AZStd::smatch pieces_match;
  933. for (size_t i = 0; i < AZ_ARRAY_SIZE(fnames); ++i)
  934. {
  935. if (AZStd::regex_match(fnames[i], pieces_match, pieces_regex))
  936. {
  937. AZ_TEST_ASSERT(pieces_match.size() == 3);
  938. AZ_TEST_ASSERT(pieces_match[0] == "foo.txt" || pieces_match[0] == "bar.txt" || pieces_match[0] == "baz.dat");
  939. AZ_TEST_ASSERT(pieces_match[1] == "foo" || pieces_match[1] == "bar" || pieces_match[1] == "baz");
  940. AZ_TEST_ASSERT(pieces_match[2] == "txt" || pieces_match[2] == "dat");
  941. }
  942. }
  943. }
  944. TEST_F(Regex, WideCharTests)
  945. {
  946. //wchar_t
  947. AZ_TEST_ASSERT(AZStd::regex_match(L"subject", AZStd::wregex(L"(sub)(.*)")));
  948. AZStd::wstring reWStr(L"subject");
  949. AZStd::wregex reW(L"(sub)(.*)");
  950. AZ_TEST_ASSERT(AZStd::regex_match(reWStr, reW));
  951. AZ_TEST_ASSERT(AZStd::regex_match(reWStr.begin(), reWStr.end(), reW))
  952. }
  953. TEST_F(Regex, LongPatterns)
  954. {
  955. // test construction and destruction of a regex with a pattern long enough to require reallocation of buffers
  956. AZStd::regex longerThan16(".*\\/Presets\\/GeomCache\\/.*", AZStd::regex::flag_type::icase | AZStd::regex::flag_type::ECMAScript);
  957. AZStd::regex longerThan32(".*\\/Presets\\/GeomCache\\/Whatever\\/Much\\/Test\\/Very\\/Memory\\/.*", AZStd::regex::flag_type::icase);
  958. }
  959. TEST_F(Regex, SmileyFaceParseRegression)
  960. {
  961. AZStd::regex smiley(":)");
  962. EXPECT_TRUE(smiley.Empty());
  963. EXPECT_TRUE(smiley.GetError() != nullptr);
  964. EXPECT_FALSE(AZStd::regex_match("wut", smiley));
  965. EXPECT_FALSE(AZStd::regex_match(":)", smiley));
  966. }
  967. TEST_F(Regex, ParseFailure)
  968. {
  969. AZStd::regex failed(")))/?!\\$");
  970. EXPECT_FALSE(failed.Valid());
  971. AZStd::regex other = AZStd::move(failed);
  972. EXPECT_FALSE(other.Valid());
  973. AZStd::regex other2;
  974. other2.swap(other);
  975. EXPECT_TRUE(other.Empty());
  976. EXPECT_TRUE(other.GetError() == nullptr);
  977. EXPECT_FALSE(other.Valid());
  978. EXPECT_FALSE(other2.Valid());
  979. }
  980. TEST_F(String, ConstString)
  981. {
  982. AZStd::string_view cstr1;
  983. EXPECT_EQ(nullptr, cstr1.data());
  984. EXPECT_EQ(0, cstr1.size());
  985. EXPECT_EQ(0, cstr1.length());
  986. EXPECT_EQ(cstr1.begin(), cstr1.end());
  987. EXPECT_EQ(cstr1, AZStd::string_view());
  988. EXPECT_TRUE(cstr1.empty());
  989. AZStd::string_view cstr2("Test");
  990. EXPECT_NE(nullptr, cstr2.data());
  991. EXPECT_EQ(4, cstr2.size());
  992. EXPECT_EQ(4, cstr2.length());
  993. EXPECT_NE(cstr2.begin(), cstr2.end());
  994. EXPECT_NE(cstr2, cstr1);
  995. EXPECT_EQ(cstr2, AZStd::string_view("Test"));
  996. EXPECT_EQ(cstr2, "Test");
  997. EXPECT_NE(cstr2, "test");
  998. EXPECT_EQ(cstr2[2], 's');
  999. EXPECT_EQ(cstr2.at(2), 's');
  1000. AZ_TEST_START_TRACE_SUPPRESSION;
  1001. EXPECT_EQ(0, cstr2.at(7));
  1002. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  1003. EXPECT_FALSE(cstr2.empty());
  1004. EXPECT_EQ(cstr2.data(), AZStd::string("Test"));
  1005. EXPECT_EQ(cstr2, AZStd::string("Test"));
  1006. AZStd::string_view cstr3 = cstr2;
  1007. EXPECT_EQ(cstr3, cstr2);
  1008. cstr3.swap(cstr1);
  1009. EXPECT_EQ(cstr3, AZStd::string_view());
  1010. EXPECT_EQ(cstr1, cstr2);
  1011. cstr1 = {};
  1012. EXPECT_EQ(cstr1, AZStd::string_view());
  1013. EXPECT_EQ(0, cstr1.size());
  1014. EXPECT_EQ(0, cstr1.length());
  1015. AZStd::string str1("Test");
  1016. EXPECT_EQ(cstr2, str1);
  1017. cstr1 = str1;
  1018. EXPECT_EQ(cstr1, cstr2);
  1019. // check hashing
  1020. AZStd::hash<AZStd::string_view> h;
  1021. AZStd::size_t value = h(cstr1);
  1022. EXPECT_NE(0, value);
  1023. // testing empty string
  1024. AZStd::string emptyString;
  1025. AZStd::string_view cstr4;
  1026. cstr4 = emptyString;
  1027. EXPECT_NE(nullptr, cstr4.data());
  1028. EXPECT_EQ(0, cstr4.size());
  1029. EXPECT_EQ(0, cstr4.length());
  1030. EXPECT_EQ(cstr4.begin(), cstr4.end());
  1031. EXPECT_TRUE(cstr4.empty());
  1032. }
  1033. TEST_F(String, StringViewModifierTest)
  1034. {
  1035. AZStd::string_view emptyView1;
  1036. AZStd::string_view view2("Needle in Haystack");
  1037. // front
  1038. EXPECT_EQ('N', view2.front());
  1039. // back
  1040. EXPECT_EQ('k', view2.back());
  1041. AZStd::string findStr("Hay");
  1042. AZStd::string_view view3(findStr);
  1043. // copy
  1044. const size_t destBufferSize = 32;
  1045. char dest[destBufferSize] = { 0 };
  1046. AZStd::size_t copyResult = view2.copy(dest, destBufferSize, 1);
  1047. EXPECT_EQ(view2.size() - 1, copyResult);
  1048. char assertDest[destBufferSize] = { 0 };
  1049. AZ_TEST_START_TRACE_SUPPRESSION;
  1050. view2.copy(assertDest, destBufferSize, view2.size() + 1);
  1051. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  1052. // substr
  1053. AZStd::string_view subView2 = view2.substr(10);
  1054. EXPECT_EQ("Haystack", subView2);
  1055. AZ_TEST_START_TRACE_SUPPRESSION;
  1056. [[maybe_unused]] AZStd::string_view assertSubView = view2.substr(view2.size() + 1);
  1057. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  1058. // compare
  1059. AZStd::size_t compareResult = view2.compare(1, view2.size() - 1, dest, copyResult);
  1060. EXPECT_EQ(0, compareResult);
  1061. AZStd::string_view compareView = "Stackhay in Needle";
  1062. compareResult = compareView.compare(view2);
  1063. EXPECT_NE(0, compareResult);
  1064. compareResult = compareView.compare(12, 6, view2, 0, 6);
  1065. EXPECT_EQ(0, compareResult);
  1066. compareResult = compareView.compare(9, 2, view2, 7, 2);
  1067. EXPECT_EQ(0, compareResult);
  1068. compareResult = compareView.compare("Stackhay in Needle");
  1069. EXPECT_EQ(0, compareResult);
  1070. // find
  1071. AZStd::size_t findResult = view2.find(view3, 0);
  1072. EXPECT_NE(0, findResult);
  1073. EXPECT_EQ(10, findResult);
  1074. findResult = compareView.find("Random String");
  1075. EXPECT_EQ(AZStd::string_view::npos, findResult);
  1076. findResult = view3.find('y', 2);
  1077. EXPECT_EQ(2, findResult);
  1078. // rfind
  1079. AZStd::size_t rfindResult = view3.rfind('a', 2);
  1080. EXPECT_EQ(1, rfindResult);
  1081. rfindResult = emptyView1.rfind("");
  1082. EXPECT_EQ(AZStd::string_view::npos, rfindResult);
  1083. rfindResult = view2.rfind("z");
  1084. EXPECT_EQ(AZStd::string_view::npos, rfindResult);
  1085. // find_first_of
  1086. AZStd::string_view repeatString = "abcdefabcfedghiabcdef";
  1087. AZStd::size_t findFirstOfResult = repeatString.find_first_of('f');
  1088. EXPECT_EQ(5, findFirstOfResult);
  1089. findFirstOfResult = repeatString.find_first_of("def");
  1090. EXPECT_EQ(3, findFirstOfResult);
  1091. findFirstOfResult = repeatString.find_first_of("def", 6);
  1092. EXPECT_EQ(9, findFirstOfResult);
  1093. AZStd::string notFoundStr = "zzz";
  1094. AZStd::string foundStr = "ghi";
  1095. findFirstOfResult = repeatString.find_first_of(notFoundStr);
  1096. EXPECT_EQ(AZStd::string_view::npos, findFirstOfResult);
  1097. findFirstOfResult = repeatString.find_first_of(foundStr);
  1098. EXPECT_EQ(12, findFirstOfResult);
  1099. // find_last_of
  1100. AZStd::size_t findLastOfResult = repeatString.find_last_of('f');
  1101. EXPECT_EQ(20, findLastOfResult);
  1102. findLastOfResult = repeatString.find_last_of("bcd");
  1103. EXPECT_EQ(18, findLastOfResult);
  1104. findLastOfResult = repeatString.find_last_of("bcd", 3);
  1105. EXPECT_EQ(3, findLastOfResult);
  1106. findLastOfResult = repeatString.find_last_of(notFoundStr);
  1107. EXPECT_EQ(AZStd::string_view::npos, findLastOfResult);
  1108. findLastOfResult = repeatString.find_last_of(foundStr);
  1109. EXPECT_EQ(14, findLastOfResult);
  1110. // find_first_not_of
  1111. AZStd::size_t findFirstNotOfResult = repeatString.find_first_not_of('a');
  1112. EXPECT_EQ(1, findFirstNotOfResult);
  1113. findFirstNotOfResult = repeatString.find_first_not_of("abcdef");
  1114. EXPECT_EQ(12, findFirstNotOfResult);
  1115. findFirstNotOfResult = repeatString.find_first_not_of("abc", 6);
  1116. EXPECT_EQ(9, findFirstNotOfResult);
  1117. findFirstNotOfResult = repeatString.find_first_not_of(notFoundStr);
  1118. EXPECT_EQ(0, findFirstNotOfResult);
  1119. findFirstNotOfResult = repeatString.find_first_not_of(foundStr, 12);
  1120. EXPECT_EQ(15, findFirstNotOfResult);
  1121. // find_last_not_of
  1122. AZStd::size_t findLastNotOfResult = repeatString.find_last_not_of('a');
  1123. EXPECT_EQ(20, findLastNotOfResult);
  1124. findLastNotOfResult = repeatString.find_last_not_of("abcdef");
  1125. EXPECT_EQ(14, findLastNotOfResult);
  1126. findLastNotOfResult = repeatString.find_last_not_of("abcf", 9);
  1127. EXPECT_EQ(4, findLastNotOfResult);
  1128. findLastNotOfResult = repeatString.find_last_not_of(notFoundStr);
  1129. EXPECT_EQ(20, findLastNotOfResult);
  1130. findLastNotOfResult = repeatString.find_last_not_of(foundStr, 14);
  1131. EXPECT_EQ(11, findLastNotOfResult);
  1132. // remove_prefix
  1133. AZStd::string_view prefixRemovalView = view2;
  1134. prefixRemovalView.remove_prefix(6);
  1135. EXPECT_EQ(" in Haystack", prefixRemovalView);
  1136. // remove_suffix
  1137. AZStd::string_view suffixRemovalView = view2;
  1138. suffixRemovalView.remove_suffix(8);
  1139. EXPECT_EQ("Needle in ", suffixRemovalView);
  1140. // starts_with
  1141. EXPECT_TRUE(view2.starts_with("Needle"));
  1142. EXPECT_TRUE(view2.starts_with('N'));
  1143. EXPECT_TRUE(view2.starts_with(AZStd::string_view("Needle")));
  1144. EXPECT_FALSE(view2.starts_with("Needle not"));
  1145. EXPECT_FALSE(view2.starts_with('n'));
  1146. EXPECT_FALSE(view2.starts_with(AZStd::string_view("Needle not")));
  1147. // ends_with
  1148. EXPECT_TRUE(view2.ends_with("Haystack"));
  1149. EXPECT_TRUE(view2.ends_with('k'));
  1150. EXPECT_TRUE(view2.ends_with(AZStd::string_view("Haystack")));
  1151. EXPECT_FALSE(view2.ends_with("Hayqueue"));
  1152. EXPECT_FALSE(view2.ends_with('e'));
  1153. EXPECT_FALSE(view2.ends_with(AZStd::string_view("Hayqueue")));
  1154. }
  1155. TEST_F(String, StringViewCmpOperatorTest)
  1156. {
  1157. AZStd::string_view view1("The quick brown fox jumped over the lazy dog");
  1158. AZStd::string_view view2("Needle in Haystack");
  1159. AZStd::string_view emptyBeaverView;
  1160. AZStd::string_view superEmptyBeaverView("");
  1161. EXPECT_EQ("", emptyBeaverView);
  1162. EXPECT_EQ("", superEmptyBeaverView);
  1163. EXPECT_EQ("The quick brown fox jumped over the lazy dog", view1);
  1164. EXPECT_NE("The slow brown fox jumped over the lazy dog", view1);
  1165. EXPECT_EQ(view2, "Needle in Haystack");
  1166. EXPECT_NE(view2, "Needle in Hayqueue");
  1167. AZStd::string_view compareView(view2);
  1168. EXPECT_EQ(view2, compareView);
  1169. EXPECT_NE(view2, view1);
  1170. AZStd::string compareStr("Busy Beaver");
  1171. AZStd::string_view notBeaverView("Lumber Beaver");
  1172. AZStd::string_view beaverView("Busy Beaver");
  1173. EXPECT_EQ(compareStr, beaverView);
  1174. EXPECT_NE(compareStr, notBeaverView);
  1175. AZStd::string microBeaverStr("Micro Beaver");
  1176. EXPECT_LT(view2, view1);
  1177. EXPECT_LT(notBeaverView, "Super Lumber Beaver");
  1178. EXPECT_LT("Disgruntled Beaver", notBeaverView);
  1179. EXPECT_LT(notBeaverView, microBeaverStr);
  1180. EXPECT_LT(compareStr, notBeaverView);
  1181. EXPECT_GT(view1, view2);
  1182. EXPECT_GT(notBeaverView, "Disgruntled Beaver");
  1183. EXPECT_GT("Super Lumber Beaver", notBeaverView);
  1184. EXPECT_GT(microBeaverStr, notBeaverView);
  1185. EXPECT_GT(notBeaverView, compareStr);
  1186. AZStd::string lowerBeaverStr("busy Beaver");
  1187. EXPECT_LE(view2, view1);
  1188. EXPECT_LE(compareView, compareView);
  1189. EXPECT_LE(beaverView, "Rocket Beaver");
  1190. EXPECT_LE(beaverView, "Busy Beaver");
  1191. EXPECT_LE("Likable Beaver", notBeaverView);
  1192. EXPECT_LE("Busy Beaver", beaverView);
  1193. EXPECT_LE(microBeaverStr, view1);
  1194. EXPECT_LE(compareStr, beaverView);
  1195. AZStd::string bigBeaver("Big Beaver");
  1196. EXPECT_GE(view1, view2);
  1197. EXPECT_GE(view1, view1);
  1198. EXPECT_GE(beaverView, "Busy Beave");
  1199. EXPECT_GE(beaverView, "Busy Beaver");
  1200. EXPECT_GE("Busy Beaver", beaverView);
  1201. EXPECT_GE("Busy Beaver1", beaverView);
  1202. EXPECT_GE(beaverView, compareStr);
  1203. EXPECT_GE(beaverView, bigBeaver);
  1204. EXPECT_GE(compareStr, beaverView);
  1205. EXPECT_GE(microBeaverStr, beaverView);
  1206. }
  1207. TEST_F(String, String_FormatOnlyAllowsValidArgs)
  1208. {
  1209. constexpr bool v1 = false;
  1210. constexpr char v2 = 0;
  1211. constexpr unsigned char v3 = 0;
  1212. constexpr signed char v4 = 0;
  1213. constexpr wchar_t v5 = 0;
  1214. constexpr unsigned short v6 = 0;
  1215. constexpr short v7 = 0;
  1216. constexpr unsigned int v8 = 0;
  1217. constexpr int v9 = 0;
  1218. constexpr unsigned long v10 = 0;
  1219. constexpr long v11 = 0;
  1220. constexpr unsigned long long v12 = 0;
  1221. constexpr long long v13 = 0;
  1222. constexpr float v14 = 0;
  1223. constexpr double v15 = 0;
  1224. constexpr const char* v16 = "Hello";
  1225. constexpr const wchar_t* v17 = L"Hello";
  1226. constexpr void* v18 = nullptr;
  1227. // This shouldn't give a compile error
  1228. AZStd::string::format(
  1229. "%i %c %uc " AZ_TRAIT_FORMAT_STRING_PRINTF_CHAR AZ_TRAIT_FORMAT_STRING_PRINTF_WCHAR " %i %i %u %i %lu %li %llu %lli %f %f " AZ_TRAIT_FORMAT_STRING_PRINTF_STRING AZ_TRAIT_FORMAT_STRING_PRINTF_WSTRING " %p",
  1230. v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18);
  1231. // This shouldn't give a compile error
  1232. AZStd::wstring::format(
  1233. L"%i %c %uc " AZ_TRAIT_FORMAT_STRING_WPRINTF_CHAR AZ_TRAIT_FORMAT_STRING_WPRINTF_WCHAR " %i %i %u %i %lu %li %llu %lli %f %f " AZ_TRAIT_FORMAT_STRING_WPRINTF_STRING AZ_TRAIT_FORMAT_STRING_WPRINTF_WSTRING " %p",
  1234. v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18);
  1235. class WrappedInt
  1236. {
  1237. [[maybe_unused]] int val;
  1238. };
  1239. using ValidFormatArg = AZStd::string::_Format_Internal::ValidFormatArg;
  1240. static_assert(AZStd::is_convertible_v<decltype(v1), ValidFormatArg>, "Should be valid format argument");
  1241. static_assert(AZStd::is_convertible_v<decltype(v2), ValidFormatArg>, "Should be valid format argument");
  1242. static_assert(AZStd::is_convertible_v<decltype(v3), ValidFormatArg>, "Should be valid format argument");
  1243. static_assert(AZStd::is_convertible_v<decltype(v4), ValidFormatArg>, "Should be valid format argument");
  1244. static_assert(AZStd::is_convertible_v<decltype(v5), ValidFormatArg>, "Should be valid format argument");
  1245. static_assert(AZStd::is_convertible_v<decltype(v7), ValidFormatArg>, "Should be valid format argument");
  1246. static_assert(AZStd::is_convertible_v<decltype(v8), ValidFormatArg>, "Should be valid format argument");
  1247. static_assert(AZStd::is_convertible_v<decltype(v9), ValidFormatArg>, "Should be valid format argument");
  1248. static_assert(AZStd::is_convertible_v<decltype(v10), ValidFormatArg>, "Should be valid format argument");
  1249. static_assert(AZStd::is_convertible_v<decltype(v11), ValidFormatArg>, "Should be valid format argument");
  1250. static_assert(AZStd::is_convertible_v<decltype(v12), ValidFormatArg>, "Should be valid format argument");
  1251. static_assert(AZStd::is_convertible_v<decltype(v13), ValidFormatArg>, "Should be valid format argument");
  1252. static_assert(AZStd::is_convertible_v<decltype(v14), ValidFormatArg>, "Should be valid format argument");
  1253. static_assert(AZStd::is_convertible_v<decltype(v15), ValidFormatArg>, "Should be valid format argument");
  1254. static_assert(AZStd::is_convertible_v<decltype(v16), ValidFormatArg>, "Should be valid format argument");
  1255. static_assert(AZStd::is_convertible_v<decltype(v17), ValidFormatArg>, "Should be valid format argument");
  1256. static_assert(AZStd::is_convertible_v<decltype(v18), ValidFormatArg>, "Should be valid format argument");
  1257. static_assert(!AZStd::is_convertible_v<AZStd::string, ValidFormatArg>, "AZStd::string shouldn't be a valid format argument");
  1258. static_assert(!AZStd::is_convertible_v<std::string, ValidFormatArg>, "std::string shouldn't be a valid format argument");
  1259. static_assert(!AZStd::is_convertible_v<AZStd::wstring, ValidFormatArg>, "AZStd::wstring shouldn't be a valid format argument");
  1260. static_assert(!AZStd::is_convertible_v<std::wstring, ValidFormatArg>, "std::wstring shouldn't be a valid format argument");
  1261. static_assert(!AZStd::is_convertible_v<WrappedInt, ValidFormatArg>, "WrappedInt shouldn't be a valid format argument");
  1262. static_assert(!AZStd::is_convertible_v<AZStd::string_view, ValidFormatArg>, "AZStd::string_view shouldn't be a valid format argument");
  1263. static_assert(!AZStd::is_convertible_v<AZStd::wstring_view, ValidFormatArg>, "AZStd::wstring_view shouldn't be a valid format argument");
  1264. static_assert(!AZStd::is_convertible_v<std::string_view, ValidFormatArg>, "string_view shouldn't be a valid format argument");
  1265. static_assert(!AZStd::is_convertible_v<std::wstring_view, ValidFormatArg>, "wstring_view shouldn't be a valid format argument");
  1266. }
  1267. TEST_F(String, StringViewPrintf)
  1268. {
  1269. AZStd::string s = "This is a long string";
  1270. AZStd::string_view view0 = "";
  1271. AZStd::string_view view1 = s;
  1272. AZStd::string_view view2{&s[10], 4};
  1273. AZStd::string result;
  1274. result = AZStd::string::format("%s %.*s %s", "[", AZ_STRING_ARG(view0), "]");
  1275. EXPECT_EQ(AZStd::string{"[ ]"}, result);
  1276. result = AZStd::string::format("%s %.*s %s", "[", AZ_STRING_ARG(view1), "]");
  1277. EXPECT_EQ(AZStd::string{"[ This is a long string ]"}, result);
  1278. result = AZStd::string::format("%s %.*s %s", "[", AZ_STRING_ARG(view2), "]");
  1279. EXPECT_EQ(AZStd::string{"[ long ]"}, result);
  1280. result = AZStd::string::format("%s %.*s %s", "[", AZ_STRING_ARG(s), "]");
  1281. EXPECT_EQ(AZStd::string{"[ This is a long string ]"}, result);
  1282. // Testing AZ_STRING_FORMATTER too
  1283. result = AZStd::string::format("%s" AZ_STRING_FORMAT "%s", "[", AZ_STRING_ARG(view2), "]");
  1284. EXPECT_EQ(AZStd::string{"[long]"}, result);
  1285. // Test the AZ_TRAIT_FORMAT_STRING_WPRINTF_* variants for wstrings
  1286. constexpr AZStd::wstring_view wideView = L"This is a long string";
  1287. AZStd::wstring wideResult = AZStd::wstring::format(AZ_TRAIT_FORMAT_STRING_WPRINTF_STRING_WITH_SIZE, AZ_STRING_ARG(view1));
  1288. EXPECT_EQ(wideView, wideResult);
  1289. wideResult = AZStd::wstring::format(AZ_TRAIT_FORMAT_STRING_WPRINTF_WSTRING_WITH_SIZE, AZ_STRING_ARG(wideView));
  1290. EXPECT_EQ(wideView, wideResult);
  1291. }
  1292. template<typename T>
  1293. class BasicStringViewConstexprFixture
  1294. : public LeakDetectionFixture
  1295. {};
  1296. using StringViewElementTypes = ::testing::Types<char, wchar_t>;
  1297. TYPED_TEST_CASE(BasicStringViewConstexprFixture, StringViewElementTypes);
  1298. TYPED_TEST(BasicStringViewConstexprFixture, StringView_DefaultConstructorsIsConstexpr)
  1299. {
  1300. constexpr AZStd::basic_string_view<TypeParam> defaultView1;
  1301. constexpr AZStd::basic_string_view<TypeParam> defaultView2;
  1302. static_assert(defaultView1 == defaultView2, "string_view constructor should be constexpr");
  1303. }
  1304. TYPED_TEST(BasicStringViewConstexprFixture, StringView_CharTConstructorsAreConstexpr)
  1305. {
  1306. // null terminated compile time string
  1307. constexpr const TypeParam* compileTimeString = []() constexpr -> const TypeParam*
  1308. {
  1309. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1310. {
  1311. return "HelloWorld\0";
  1312. }
  1313. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1314. {
  1315. return L"HelloWorld\0";
  1316. }
  1317. return {};
  1318. }();
  1319. constexpr AZStd::basic_string_view<TypeParam> charTView1(compileTimeString);
  1320. static_assert(charTView1.size() == 10, "string_view constructor should be constexpr");
  1321. // non-null terminated compile time string
  1322. constexpr const TypeParam* compileTimeString2 = []() constexpr -> const TypeParam*
  1323. {
  1324. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1325. {
  1326. return "GoodbyeWorld";
  1327. }
  1328. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1329. {
  1330. return L"GoodbyeWorld";
  1331. }
  1332. return {};
  1333. }();
  1334. constexpr AZStd::basic_string_view<TypeParam> charTViewWithLength(compileTimeString2, 7);
  1335. static_assert(charTViewWithLength.size() == 7, "string_view constructor should be constexpr");
  1336. }
  1337. TYPED_TEST(BasicStringViewConstexprFixture, StringView_CopyConstructorsIsConstexpr)
  1338. {
  1339. // null terminated compile time string
  1340. constexpr const TypeParam* compileTimeString = []() constexpr-> const TypeParam*
  1341. {
  1342. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1343. {
  1344. return "HelloWorld\0";
  1345. }
  1346. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1347. {
  1348. return L"HelloWorld\0";
  1349. }
  1350. return {};
  1351. }();
  1352. constexpr AZStd::basic_string_view<TypeParam> copyView1(compileTimeString);
  1353. constexpr AZStd::basic_string_view<TypeParam> copyView2(copyView1);
  1354. static_assert(copyView1 == copyView2, "string_view constructor should be constexpr");
  1355. }
  1356. TYPED_TEST(BasicStringViewConstexprFixture, StringView_AssignmentOperatorIsConstexpr)
  1357. {
  1358. // null terminated compile time string
  1359. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1360. {
  1361. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1362. {
  1363. return "HelloWorld\0";
  1364. }
  1365. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1366. {
  1367. return L"HelloWorld\0";
  1368. }
  1369. return {};
  1370. }();
  1371. constexpr AZStd::basic_string_view<TypeParam> assignView1(compileTimeString1);
  1372. auto assignment_test_func = [](AZStd::basic_string_view<TypeParam> sourceView) constexpr -> AZStd::basic_string_view<TypeParam>
  1373. {
  1374. constexpr const TypeParam* const compileTimeString2 = []() constexpr-> const TypeParam*
  1375. {
  1376. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1377. {
  1378. return "GoodbyeWorld\0";
  1379. }
  1380. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1381. {
  1382. return L"GoodbyeWorld\0";
  1383. }
  1384. return {};
  1385. }();
  1386. AZStd::basic_string_view<TypeParam> assignView2(compileTimeString2);
  1387. assignView2 = sourceView;
  1388. return assignView2;
  1389. };
  1390. static_assert(assignment_test_func(assignView1) == assignView1, "The assigned string_view should compare equal to the original");
  1391. }
  1392. TYPED_TEST(BasicStringViewConstexprFixture, StringView_IteratorsAreConstexpr)
  1393. {
  1394. // null terminated compile time string
  1395. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1396. {
  1397. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1398. {
  1399. return "HelloWorld\0";
  1400. }
  1401. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1402. {
  1403. return L"HelloWorld\0";
  1404. }
  1405. return {};
  1406. }();
  1407. constexpr AZStd::basic_string_view<TypeParam> iteratorView(compileTimeString1);
  1408. constexpr typename AZStd::basic_string_view<TypeParam>::iterator beginIt = iteratorView.begin();
  1409. constexpr typename AZStd::basic_string_view<TypeParam>::const_iterator cbeginIt = iteratorView.cbegin();
  1410. constexpr typename AZStd::basic_string_view<TypeParam>::iterator endIt = iteratorView.end();
  1411. constexpr typename AZStd::basic_string_view<TypeParam>::const_iterator cendIt = iteratorView.cend();
  1412. constexpr typename AZStd::basic_string_view<TypeParam>::reverse_iterator rbeginIt = iteratorView.rbegin();
  1413. constexpr typename AZStd::basic_string_view<TypeParam>::const_reverse_iterator crbeginIt = iteratorView.crbegin();
  1414. constexpr typename AZStd::basic_string_view<TypeParam>::reverse_iterator rendIt = iteratorView.rend();
  1415. constexpr typename AZStd::basic_string_view<TypeParam>::const_reverse_iterator crendIt = iteratorView.crend();
  1416. static_assert(beginIt != endIt, "begin and iterators should be different");
  1417. static_assert(cbeginIt != cendIt, "begin and iterators should be different");
  1418. static_assert(rbeginIt != rendIt, "begin and iterators should be different");
  1419. static_assert(crbeginIt != crendIt, "begin and iterators should be different");
  1420. static_assert(AZStd::begin(iteratorView) != AZStd::end(iteratorView), "non-member begin and end functions should return different iterators");
  1421. }
  1422. TYPED_TEST(BasicStringViewConstexprFixture, StringView_AccessOperatorsAreConstexpr)
  1423. {
  1424. // null terminated compile time string
  1425. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1426. {
  1427. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1428. {
  1429. return "HelloWorld\0";
  1430. }
  1431. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1432. {
  1433. return L"HelloWorld\0";
  1434. }
  1435. return {};
  1436. }();
  1437. constexpr AZStd::basic_string_view<TypeParam> elementView1(compileTimeString1);
  1438. static_assert(elementView1[4] == 'o', "character at index 4 in string_view should be 'o'");
  1439. static_assert(elementView1.at(5) == 'W', "character at index 5 in string_view should be 'W'");
  1440. }
  1441. TYPED_TEST(BasicStringViewConstexprFixture, StringView_FrontAndBackAreConstexpr)
  1442. {
  1443. // null terminated compile time string
  1444. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1445. {
  1446. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1447. {
  1448. return "HelloWorld\0";
  1449. }
  1450. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1451. {
  1452. return L"HelloWorld\0";
  1453. }
  1454. return {};
  1455. }();
  1456. constexpr AZStd::basic_string_view<TypeParam> elementView1(compileTimeString1);
  1457. static_assert(elementView1.front() == 'H', "Fourth character in string_view should be 'H'");
  1458. static_assert(elementView1.back() == 'd', "Fifth character in string_view should be 'd'");
  1459. }
  1460. TYPED_TEST(BasicStringViewConstexprFixture, StringView_DataIsConstexpr)
  1461. {
  1462. // null terminated compile time string
  1463. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1464. {
  1465. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1466. {
  1467. return "HelloWorld\0";
  1468. }
  1469. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1470. {
  1471. return L"HelloWorld\0";
  1472. }
  1473. return {};
  1474. }();
  1475. constexpr const TypeParam* compileTimeString2 = []() constexpr-> const TypeParam*
  1476. {
  1477. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1478. {
  1479. return "OthelloWorld\0";
  1480. }
  1481. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1482. {
  1483. return L"OthelloWorld\0";
  1484. }
  1485. return {};
  1486. }();
  1487. static constexpr AZStd::basic_string_view<TypeParam> elementView1(compileTimeString1);
  1488. static constexpr AZStd::basic_string_view<TypeParam> elementView2(compileTimeString2);
  1489. static_assert(elementView1.data(), "string_view.data() should be non-nullptr");
  1490. static_assert(elementView2.data(), "string_view.data() should be non-nullptr");
  1491. }
  1492. TYPED_TEST(BasicStringViewConstexprFixture, StringView_SizeOperatorsConstexpr)
  1493. {
  1494. // null terminated compile time string
  1495. constexpr const TypeParam* compileTimeString1 = []() constexpr-> const TypeParam*
  1496. {
  1497. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1498. {
  1499. return "HelloWorld\0";
  1500. }
  1501. else if constexpr (AZStd::is_same_v<TypeParam, wchar_t>)
  1502. {
  1503. return L"HelloWorld\0";
  1504. }
  1505. return {};
  1506. }();
  1507. constexpr AZStd::basic_string_view<TypeParam> sizeView1(compileTimeString1);
  1508. static_assert(sizeView1.size() == sizeView1.length(), "string_views size and length function should return the same value");
  1509. static_assert(!sizeView1.empty(), "string_views should not be empty");
  1510. static_assert(sizeView1.max_size() != 0, "string_views max_size should be greater than 0");
  1511. }
  1512. TEST_F(String, StringView_ModifiersAreConstexpr)
  1513. {
  1514. using TypeParam = char;
  1515. // null terminated compile time string
  1516. [[maybe_unused]] auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1517. {
  1518. return "HelloWorld";
  1519. };
  1520. constexpr AZStd::basic_string_view<TypeParam> modifierView("HelloWorld");
  1521. // A constexpr lambda is used to evaluate non constexpr string_view instances' member functions which
  1522. // have been marked as constexpr at compile time
  1523. // The google test function being run is not a constexpr function and therefore will evaulate
  1524. // non-constexpr string_view variables at runtime. This would cause static_assert to state
  1525. // that the expression is evaluated at runtime
  1526. auto remove_prefix_test_func = [](AZStd::basic_string_view<TypeParam> sourceView) constexpr -> AZStd::basic_string_view<TypeParam>
  1527. {
  1528. AZStd::basic_string_view<TypeParam> lstripView(sourceView);
  1529. lstripView.remove_prefix(5);
  1530. return lstripView;
  1531. };
  1532. auto remove_suffix_test_func = [](AZStd::basic_string_view<TypeParam> sourceView) constexpr -> AZStd::basic_string_view<TypeParam>
  1533. {
  1534. AZStd::basic_string_view<TypeParam> rstripView(sourceView);
  1535. rstripView.remove_suffix(5);
  1536. return rstripView;
  1537. };
  1538. static_assert(remove_prefix_test_func(modifierView) == "World", "string_view should compare equal to World");
  1539. static_assert(remove_suffix_test_func(modifierView) == "Hello", "string_view should compare equal to Hello");
  1540. }
  1541. TEST_F(String, StringView_SubstrIsConstexpr)
  1542. {
  1543. using TypeParam = char;
  1544. auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1545. {
  1546. return "HelloWorld";
  1547. };
  1548. constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();;
  1549. constexpr AZStd::basic_string_view<TypeParam> fullView(compileTimeString1);
  1550. auto substr_test_func = [](AZStd::basic_string_view<TypeParam> sourceView) constexpr -> AZStd::basic_string_view<TypeParam>
  1551. {
  1552. return sourceView.substr(3, 5);
  1553. };
  1554. static_assert(substr_test_func(fullView) == "loWor", "string_view substring should result in string \"lloWo\"");
  1555. }
  1556. TEST_F(String, StringView_StartsAndEndsWithAreConstexpr)
  1557. {
  1558. using TypeParam = char;
  1559. auto MakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1560. {
  1561. return "elloGovernor";
  1562. };
  1563. constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1();
  1564. constexpr AZStd::basic_string_view<TypeParam> withView(compileTimeString1);
  1565. static_assert(withView.starts_with("ello"), "string_view should start with \"ello\"");
  1566. // Regression in VS2017 15.8 and 15.9 where __builtin_memcmp fails in valid checks
  1567. #if AZ_COMPILER_MSVC < 1915 && AZ_COMPILER_MSVC > 1916
  1568. static_assert(withView.ends_with("Governor"), "string_view should end with \"Governor\"");
  1569. #endif
  1570. }
  1571. template<typename> constexpr const char* MakeCompileTimeString1 ="the quick brown fox jumped over the lazy dog";
  1572. template<> constexpr const wchar_t* MakeCompileTimeString1<wchar_t> = L"the quick brown fox jumped over the lazy dog";
  1573. template<typename> constexpr const char* MakeSearchString = "o";
  1574. template<> constexpr const wchar_t* MakeSearchString<wchar_t> = L"o";
  1575. template<typename> constexpr const char* MakeTestString1 = "fox";
  1576. template<> constexpr const wchar_t* MakeTestString1<wchar_t> = L"fox";
  1577. template<typename> constexpr const char* MakeTestString2 = "the";
  1578. template<> constexpr const wchar_t* MakeTestString2<wchar_t> = L"the";
  1579. template<typename> constexpr const char* MakeTestString3 = "browning";
  1580. template<> constexpr const wchar_t* MakeTestString3<wchar_t> = L"browning";
  1581. template<typename> constexpr const char* MakeTestString4 = "e";
  1582. template<> constexpr const wchar_t* MakeTestString4<wchar_t> = L"e";
  1583. template<typename> constexpr const char* MakeTestString5 = "dino";
  1584. template<> constexpr const wchar_t* MakeTestString5<wchar_t> = L"dino";
  1585. template<typename> constexpr const char* MakeTestString6 = "eh ";
  1586. template<> constexpr const wchar_t* MakeTestString6<wchar_t> = L"eh ";
  1587. template<typename> constexpr const char* MakeTestString7 = "eh";
  1588. template<> constexpr const wchar_t* MakeTestString7<wchar_t> = L"eh";
  1589. template<typename> constexpr const char* MakeTestString8 = "cat";
  1590. template<> constexpr const wchar_t* MakeTestString8<wchar_t> = L"cat";
  1591. template<typename> constexpr const char* MakeTestString9 = "the ";
  1592. template<> constexpr const wchar_t* MakeTestString9<wchar_t> = L"the ";
  1593. template<typename> constexpr const char* MakeTestString10 = "dog ";
  1594. template<> constexpr const wchar_t* MakeTestString10<wchar_t> = L"dog ";
  1595. TYPED_TEST(BasicStringViewConstexprFixture, StringView_FindOperationsAreConstexpr)
  1596. {
  1597. constexpr const TypeParam* compileTimeString1 = MakeCompileTimeString1<TypeParam>;
  1598. constexpr AZStd::basic_string_view<TypeParam> quickFoxView(compileTimeString1);
  1599. constexpr const TypeParam* searchString = MakeSearchString<TypeParam>;
  1600. constexpr AZStd::basic_string_view<TypeParam> searchView(searchString);
  1601. constexpr const TypeParam* testString1 = MakeTestString1<TypeParam>;
  1602. constexpr const TypeParam* testString2 = MakeTestString2<TypeParam>;
  1603. constexpr const TypeParam* testString3 = MakeTestString3<TypeParam>;
  1604. constexpr const TypeParam* testString4 = MakeTestString4<TypeParam>;
  1605. constexpr const TypeParam* testString5 = MakeTestString5<TypeParam>;
  1606. constexpr const TypeParam* testString6 = MakeTestString6<TypeParam>;
  1607. constexpr const TypeParam* testString7 = MakeTestString7<TypeParam>;
  1608. constexpr const TypeParam* testString8 = MakeTestString8<TypeParam>;
  1609. constexpr const TypeParam* testString9 = MakeTestString9<TypeParam>;
  1610. constexpr const TypeParam* testString10 = MakeTestString10<TypeParam>;
  1611. // find test
  1612. static_assert(quickFoxView.find(searchView) == 12, "string_view find should result in index 12");
  1613. static_assert(quickFoxView.find('q') == 4, "string_view find should result in index 4");
  1614. static_assert(quickFoxView.find(testString1) == 16, "string_view find should result in index 16");
  1615. static_assert(quickFoxView.find(testString2, 3) == 32, "string_view find should result in index 32");
  1616. static_assert(quickFoxView.find(testString3, 0, 5) == 10, "string_view find should result in index 10");
  1617. // rfind test
  1618. static_assert(quickFoxView.rfind(searchView) == 42, "string_view rfind should result in index 42");
  1619. static_assert(quickFoxView.rfind('o') == 42, "string_view rfind should result in index 42");
  1620. static_assert(quickFoxView.rfind(testString2) == 32, "string_view rfind should result in index 32");
  1621. static_assert(quickFoxView.rfind(testString4, 32) == 29, "string_view rfind should result in index 29");
  1622. static_assert(quickFoxView.rfind(testString5, 40, 1) == 25, "string_view rfind should result in index 25");
  1623. // find_first_of test
  1624. static_assert(quickFoxView.find_first_of(searchView) == 12, "string_view find_first_of_test should result in index 12");
  1625. static_assert(quickFoxView.find_first_of('o') == 12, "string_view find_first_of should result in index 12");
  1626. static_assert(quickFoxView.find_first_of(testString6) == 1, "string_view find_first_of should result in index 1");
  1627. static_assert(quickFoxView.find_first_of(testString7, 6) == 24, "string_view find_first_of should result in index 24");
  1628. static_assert(quickFoxView.find_first_of(testString8, 0, 1) == 7, "string_view find_first_of should result in index 7");
  1629. // find_last_of test
  1630. static_assert(quickFoxView.find_last_of(searchView) == 42, "string_view find_last_of_test should result in index 42");
  1631. static_assert(quickFoxView.find_last_of('o') == 42, "string_view find_last_of should result in index 42");
  1632. static_assert(quickFoxView.find_last_of(testString6) == 40, "string_view find_last_of should result in index 40");
  1633. static_assert(quickFoxView.find_last_of(testString7, 31) == 29, "string_view find_last_of should result in index 29");
  1634. static_assert(quickFoxView.find_last_of(testString8, AZStd::basic_string_view<TypeParam>::npos, 1) == 7, "string_view find_last_of should result in index 7");
  1635. // find_first_not_of test
  1636. constexpr AZStd::basic_string_view<TypeParam> firstNotOfView(testString9);
  1637. static_assert(quickFoxView.find_first_not_of(firstNotOfView) == 4, "string_view find_first_not_of should result in index 0");
  1638. static_assert(quickFoxView.find_first_not_of('t') == 1, "string_view find_first_not_of should result in index 1");
  1639. static_assert(quickFoxView.find_first_not_of(testString9) == 4, "string_view find_first_not_of should result in index 4");
  1640. static_assert(quickFoxView.find_first_not_of(testString9, 31) == 36, "string_view find_first_not_of should result in index 36");
  1641. static_assert(quickFoxView.find_first_not_of(testString9, 0, 1) == 1, "string_view find_first_not_of should result in index 1");
  1642. // find_last_not_of test
  1643. constexpr AZStd::basic_string_view<TypeParam> lastNotOfView(testString10);
  1644. static_assert(quickFoxView.find_last_not_of(lastNotOfView) == 39, "string_view find_last_not_of should result in index 39");
  1645. static_assert(quickFoxView.find_last_not_of('g') == 42, "string_view find_last_not_of should result in index 42");
  1646. static_assert(quickFoxView.find_last_not_of(testString10) == 39, "string_view find_last_not_of should result in index 39");
  1647. static_assert(quickFoxView.find_last_not_of(testString10, 27) == 24, "string_view find_last_not_of should result in index 24");
  1648. static_assert(quickFoxView.find_last_not_of(testString10, AZStd::basic_string_view<TypeParam>::npos, 1) == 43, "string_view find_last_not_of should result in index 43");
  1649. }
  1650. TEST_F(String, StringView_CompareIsConstexpr)
  1651. {
  1652. using TypeParam = char;
  1653. auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1654. {
  1655. return "HelloWorld";
  1656. };
  1657. auto MakeCompileTimeString2 = []() constexpr -> const TypeParam*
  1658. {
  1659. return "HelloPearl";
  1660. };
  1661. constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
  1662. constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
  1663. constexpr AZStd::basic_string_view<TypeParam> lhsView(compileTimeString1);
  1664. constexpr AZStd::basic_string_view<TypeParam> rhsView(compileTimeString2);
  1665. static_assert(lhsView.compare(rhsView) > 0, R"("HelloWorld" > "HelloPearl")");
  1666. static_assert(lhsView.compare(0, 5, rhsView) < 0, R"("Hello" < HelloPearl")");
  1667. static_assert(lhsView.compare(2, 3, rhsView, 2, 3) == 0, R"("llo" == llo")");
  1668. static_assert(lhsView.compare("Hello") > 0, R"("HelloWorld" > Hello")");
  1669. static_assert(lhsView.compare(0, 5, "Hello") == 0, R"("Hello" == Hello")");
  1670. static_assert(lhsView.compare(0, 5, "HelloTheorello", 5) == 0, R"("Hello" == Hello")");
  1671. }
  1672. TEST_F(String, StringView_CompareOperatorsAreConstexpr)
  1673. {
  1674. using TypeParam = char;
  1675. auto TestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1676. {
  1677. return "HelloWorld";
  1678. };
  1679. constexpr const TypeParam* compileTimeString1 = TestMakeCompileTimeString1();
  1680. constexpr AZStd::basic_string_view<TypeParam> compareView(compileTimeString1);
  1681. static_assert(compareView == "HelloWorld", "string_view operator== comparison has failed");
  1682. static_assert(compareView != "MadWorld", "string_view operator!= comparison has failed");
  1683. static_assert(compareView < "JelloWorld", "string_view operator< comparison has failed");
  1684. static_assert("MelloWorld" > compareView, "string_view operator> comparison has failed");
  1685. static_assert(compareView <= "HelloWorld", "string_view operator== comparison has failed");
  1686. static_assert(compareView >= "HelloWorld", "string_view operator== comparison has failed");
  1687. }
  1688. TYPED_TEST(BasicStringViewConstexprFixture, StringView_SwapIsConstexpr)
  1689. {
  1690. auto swap_test_func = []() constexpr -> AZStd::basic_string_view<TypeParam>
  1691. {
  1692. constexpr auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1693. {
  1694. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1695. {
  1696. return "NekuWorld";
  1697. }
  1698. else
  1699. {
  1700. return L"NekuWorld";
  1701. }
  1702. };
  1703. constexpr auto MakeCompileTimeString2 = []() constexpr -> const TypeParam*
  1704. {
  1705. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1706. {
  1707. return "InuWorld";
  1708. }
  1709. else
  1710. {
  1711. return L"InuWorld";
  1712. }
  1713. };
  1714. constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
  1715. constexpr const TypeParam* compileTimeString2 = MakeCompileTimeString2();
  1716. AZStd::basic_string_view<TypeParam> lhsView(compileTimeString1);
  1717. AZStd::basic_string_view<TypeParam> rhsView(compileTimeString2);
  1718. lhsView.swap(rhsView);
  1719. return lhsView;
  1720. };
  1721. constexpr auto MakeCompileTimeString3 = []() constexpr -> const TypeParam*
  1722. {
  1723. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1724. {
  1725. return "InuWorld";
  1726. }
  1727. else
  1728. {
  1729. return L"InuWorld";
  1730. }
  1731. };
  1732. static_assert(swap_test_func() == MakeCompileTimeString3(), R"(string_view swap should have swapped around "NekuWorld" and "InuWorld")");
  1733. }
  1734. TYPED_TEST(BasicStringViewConstexprFixture, HashString_FunctionIsConstexpr)
  1735. {
  1736. auto ThisTestMakeCompileTimeString1 = []() constexpr -> const TypeParam*
  1737. {
  1738. if constexpr (AZStd::is_same_v<TypeParam, char>)
  1739. {
  1740. return "HelloWorld";
  1741. }
  1742. else
  1743. {
  1744. return L"HelloWorld";
  1745. }
  1746. };
  1747. constexpr const TypeParam* compileTimeString1 = ThisTestMakeCompileTimeString1();
  1748. constexpr AZStd::basic_string_view<TypeParam> hashView(compileTimeString1);
  1749. constexpr size_t compileHash = AZStd::hash<AZStd::basic_string_view<TypeParam>>{}(hashView);
  1750. static_assert(compileHash != 0, "Hash of \"HelloWorld\" should not be 0");
  1751. }
  1752. TEST_F(String, StringView_UserLiteralsSucceed)
  1753. {
  1754. using namespace AZStd::string_view_literals;
  1755. constexpr auto charView{ "Test"_sv };
  1756. constexpr auto wcharView{ L"Super Test"_sv };
  1757. static_assert(charView == "Test", "char string literal should be \"Test\"");
  1758. static_assert(wcharView == L"Super Test", "char string literal should be \"Super Test\"");
  1759. }
  1760. TEST_F(String, FixedString_ConstructorsAreConstexpr_Succeeds)
  1761. {
  1762. constexpr AZStd::fixed_string<128> test1;
  1763. constexpr AZStd::fixed_string<128> test2(static_cast<size_t>(5), 'm');
  1764. constexpr AZStd::fixed_string<128> test3{ test2, 2, 2 };
  1765. constexpr AZStd::fixed_string<128> test4{ "World", 3 };
  1766. constexpr AZStd::fixed_string<128> test5{ "World" };
  1767. constexpr AZStd::array<int, 5> testView{ 'H', 'e', 'l', 'l', 'o' };
  1768. constexpr AZStd::fixed_string<128> test6{ testView.begin(), testView.end() };
  1769. constexpr AZStd::fixed_string<128> test7{ test4 };
  1770. constexpr AZStd::fixed_string<128> test8{ AZStd::fixed_string<128>{ "MoveTheWorld"} };
  1771. constexpr AZStd::fixed_string<128> test9{ {'O', 'r', 'a', 'n', 'g', 'e'} };
  1772. constexpr AZStd::fixed_string<128> test10{ AZStd::string_view{"BozBox" } };
  1773. constexpr AZStd::fixed_string<128> test11{ AZStd::string_view{"BozBox"}, 2, 3 };
  1774. static_assert(test1.empty());
  1775. static_assert(test2 == "mmmmm");
  1776. static_assert(test3 == "mm");
  1777. static_assert(test4 == "Wor");
  1778. static_assert(test5 == "World");
  1779. static_assert(test6 == "Hello");
  1780. static_assert(test7 == "Wor");
  1781. static_assert(test8 == "MoveTheWorld");
  1782. static_assert(test9 == "Orange");
  1783. static_assert(test10 == "BozBox");
  1784. static_assert(test11 == "zBo");
  1785. }
  1786. TEST_F(String, FixedString_OperatorPlusIsConstexpr_Succeeds)
  1787. {
  1788. constexpr AZStd::fixed_string<128> test1{ "Hello" };
  1789. constexpr AZStd::fixed_string<128> test2{ "World" };
  1790. static_assert((test1 + test2) == "HelloWorld");
  1791. static_assert(("Mello" + test2) == "MelloWorld");
  1792. static_assert((test1 + "Curl") == "HelloCurl");
  1793. static_assert(('F' + test2) == "FWorld");
  1794. static_assert((test1 + 'Z') == "HelloZ");
  1795. static_assert((AZStd::fixed_string<128>{"Chello"} + AZStd::fixed_string<128>{"Play"}) == "ChelloPlay");
  1796. static_assert((AZStd::fixed_string<128>{"Chello"} + test2) == "ChelloWorld");
  1797. static_assert((AZStd::fixed_string<128>{"Chello"} + "Play") == "ChelloPlay");
  1798. static_assert((AZStd::fixed_string<128>{"Chello"} + 'P') == "ChelloP");
  1799. static_assert((test1 + AZStd::fixed_string<128>{"Chello"}) == "HelloChello");
  1800. static_assert(("Mellow" + AZStd::fixed_string<128>{"Chello"}) == "MellowChello");
  1801. static_assert(('M' + AZStd::fixed_string<128>{"Chello"}) == "MChello");
  1802. }
  1803. TEST_F(String, FixedString_AppendIsConstexpr_Succeeds)
  1804. {
  1805. constexpr AZStd::fixed_string<128> test1{ "Hello" };
  1806. constexpr AZStd::fixed_string<128> test2{ AZStd::fixed_string<128>{}.append(test1) };
  1807. constexpr AZStd::fixed_string<128> test3{ AZStd::fixed_string<128>{}.append("Brown") };
  1808. constexpr AZStd::fixed_string<128> test4{ AZStd::fixed_string<128>{ "App" }.append(AZStd::string_view("Blue")) };
  1809. constexpr AZStd::string_view redView("Red");
  1810. constexpr AZStd::fixed_string<128> test5{ AZStd::fixed_string<128>{ "App" }.append(redView.begin(), redView.end()) };
  1811. constexpr AZStd::fixed_string<128> test6{ AZStd::fixed_string<128>{ "App" }.append(5, 'X') };
  1812. constexpr AZStd::fixed_string<128> test7{ AZStd::fixed_string<128>{ "App" }.append("Green", 2) };
  1813. static_assert(test2 == "Hello");
  1814. static_assert(test3 == "Brown");
  1815. static_assert(test4 == "AppBlue");
  1816. static_assert(test5 == "AppRed");
  1817. static_assert(test6 == "AppXXXXX");
  1818. static_assert(test7 == "AppGr");
  1819. }
  1820. TEST_F(String, FixedString_AssignIsConstexpr_Succeeds)
  1821. {
  1822. constexpr AZStd::fixed_string<128> test1{ "Hello" };
  1823. constexpr AZStd::fixed_string<128> test2{ AZStd::fixed_string<128>{}.assign(test1) };
  1824. constexpr AZStd::fixed_string<128> test3{ AZStd::fixed_string<128>{}.assign("Brown") };
  1825. constexpr AZStd::fixed_string<128> test4{ AZStd::fixed_string<128>{ "App" }.assign(AZStd::string_view("Blue")) };
  1826. constexpr AZStd::string_view redView("Red");
  1827. constexpr AZStd::fixed_string<128> test5{ AZStd::fixed_string<128>{ "App" }.assign(redView.begin(), redView.end()) };
  1828. constexpr AZStd::fixed_string<128> test6{ AZStd::fixed_string<128>{ "App" }.assign(5, 'X') };
  1829. constexpr AZStd::fixed_string<128> test7{ AZStd::fixed_string<128>{ "App" }.assign("GreenMile", 5) };
  1830. constexpr AZStd::fixed_string<128> testAssignFromEmptyStringView{ AZStd::fixed_string<128>{ "App" }.assign(AZStd::string_view{}) };
  1831. static_assert(test2 == "Hello");
  1832. static_assert(test3 == "Brown");
  1833. static_assert(test4 == "Blue");
  1834. static_assert(test5 == "Red");
  1835. static_assert(test6 == "XXXXX");
  1836. static_assert(test7 == "Green");
  1837. static_assert(testAssignFromEmptyStringView == "");
  1838. }
  1839. TEST_F(String, FixedString_InsertIsConstexpr_Succeeds)
  1840. {
  1841. constexpr AZStd::fixed_string<128> test1{ "Hello" };
  1842. constexpr AZStd::fixed_string<128> test2{ AZStd::fixed_string<128>{}.insert(0, test1) };
  1843. constexpr AZStd::fixed_string<128> test3{ AZStd::fixed_string<128>{}.insert(0, "Brown") };
  1844. constexpr AZStd::fixed_string<128> test4{ AZStd::fixed_string<128>{ "App" }.insert(0, AZStd::string_view("Blue")) };
  1845. constexpr AZStd::fixed_string<128> test5{ AZStd::fixed_string<128>{ "App" }.insert(0, test1, 2, 2) };
  1846. constexpr AZStd::fixed_string<128> test6{ AZStd::fixed_string<128>{ "App" }.insert(size_t(0), 5, 'X') };
  1847. constexpr AZStd::fixed_string<128> test7{ AZStd::fixed_string<128>{ "App" }.insert(0, "GreenTea", 5) };
  1848. auto MakeFixedStringWithInsertWithIteratorPos1 = []() constexpr
  1849. {
  1850. AZStd::fixed_string<128> bufferString;
  1851. AZStd::array testString{ 'O', 'r', 'a', 'n', 'g', 'e' };
  1852. bufferString.insert(bufferString.end(), testString.begin(), testString.end());
  1853. return bufferString;
  1854. };
  1855. constexpr AZStd::fixed_string<128> test8{ MakeFixedStringWithInsertWithIteratorPos1() };
  1856. auto MakeFixedStringWithInsertWithIteratorPos2 = []() constexpr
  1857. {
  1858. AZStd::fixed_string<128> bufferString;
  1859. bufferString.insert(bufferString.end(), { 'B', 'l', 'a', 'c', 'k' });
  1860. return bufferString;
  1861. };
  1862. constexpr AZStd::fixed_string<128> test9{ MakeFixedStringWithInsertWithIteratorPos2() };
  1863. static_assert(test2 == "Hello");
  1864. static_assert(test3 == "Brown");
  1865. static_assert(test4 == "BlueApp");
  1866. static_assert(test5 == "llApp");
  1867. static_assert(test6 == "XXXXXApp");
  1868. static_assert(test7 == "GreenApp");
  1869. static_assert(test8 == "Orange");
  1870. static_assert(test9 == "Black");
  1871. }
  1872. TEST_F(String, FixedString_ReplaceIsConstexpr_Succeeds)
  1873. {
  1874. constexpr AZStd::fixed_string<128> test1{ "Hello" };
  1875. constexpr AZStd::fixed_string<128> test2{ AZStd::fixed_string<128>{"Exe"}.replace(1, 1, test1) };
  1876. constexpr AZStd::fixed_string<128> test3{ AZStd::fixed_string<128>{"Exe"}.replace(1, 1, test1, 2, 2) };
  1877. constexpr AZStd::string_view aquaView{ "Aqua" };
  1878. constexpr AZStd::fixed_string<128> test4{ AZStd::fixed_string<128>{"Exe"}.replace(1, 1, aquaView, 1, 3) };
  1879. constexpr AZStd::fixed_string<128> test5{ AZStd::fixed_string<128>{"Hello{}"}.replace(5, 2, AZStd::string_view("World")) };
  1880. constexpr AZStd::fixed_string<128> test6{ AZStd::fixed_string<128>{"Hello{}"}.replace(5, 2, "BigString", 3) };
  1881. constexpr AZStd::fixed_string<128> test7{ AZStd::fixed_string<128>{"Hello{}"}.replace(5, 2, 3, 'V') };
  1882. auto MakeFixedStringWithReplaceWithIteratorPos1 = []() constexpr
  1883. {
  1884. AZStd::fixed_string<128> bufferString{"Jello"};
  1885. bufferString.replace(bufferString.begin(), bufferString.begin() + 3, "Hel");
  1886. return bufferString;
  1887. };
  1888. constexpr AZStd::fixed_string<128> test8{ MakeFixedStringWithReplaceWithIteratorPos1() };
  1889. auto MakeFixedStringWithReplaceWithIteratorPos2 = []() constexpr
  1890. {
  1891. AZStd::fixed_string<128> bufferString{ "Jello" };
  1892. bufferString.replace(bufferString.begin(), bufferString.begin() + 3, AZStd::string_view{ "Mel" });
  1893. return bufferString;
  1894. };
  1895. constexpr AZStd::fixed_string<128> test9{ MakeFixedStringWithReplaceWithIteratorPos2() };
  1896. auto MakeFixedStringWithInsertWithIteratorPos3 = []() constexpr
  1897. {
  1898. AZStd::fixed_string<128> bufferString{ "Othello" };
  1899. bufferString.replace(bufferString.begin() + 4, bufferString.end(), { 'r', 's' });
  1900. return bufferString;
  1901. };
  1902. constexpr AZStd::fixed_string<128> test10{ MakeFixedStringWithInsertWithIteratorPos3() };
  1903. auto MakeFixedStringWithInsertWithIteratorPos4 = []() constexpr
  1904. {
  1905. AZStd::fixed_string<128> bufferString{ "Theorello" };
  1906. constexpr AZStd::array testString{ 'l', 'a', 't', 'i', 'v', 'e' };
  1907. bufferString.replace(bufferString.begin() + 6, bufferString.end(), testString.begin(), testString.end());
  1908. return bufferString;
  1909. };
  1910. constexpr AZStd::fixed_string<128> test11{ MakeFixedStringWithInsertWithIteratorPos4() };
  1911. static_assert(test2 == "EHelloe");
  1912. static_assert(test3 == "Elle");
  1913. static_assert(test4 == "Equae");
  1914. static_assert(test5 == "HelloWorld");
  1915. static_assert(test6 == "HelloBig");
  1916. static_assert(test7 == "HelloVVV");
  1917. static_assert(test8 == "Hello");
  1918. static_assert(test9 == "Mello");
  1919. static_assert(test10 == "Others");
  1920. static_assert(test11 == "Theorelative");
  1921. }
  1922. TEST_F(String, FixedString_PushBackIsConstexpr_Succeeds)
  1923. {
  1924. constexpr AZStd::fixed_string<128> test1 = []() constexpr
  1925. {
  1926. AZStd::fixed_string<128> bufferString{ "Jello" };
  1927. bufferString.push_back('W');
  1928. bufferString.push_back('o');
  1929. bufferString.push_back('r');
  1930. bufferString.push_back('l');
  1931. bufferString.push_back('d');
  1932. return bufferString;
  1933. }();
  1934. static_assert(test1 == "JelloWorld");
  1935. }
  1936. TEST_F(String, FixedString_EraseIsConstexpr_Succeeds)
  1937. {
  1938. constexpr AZStd::fixed_string<128> test1 = []() constexpr
  1939. {
  1940. AZStd::fixed_string<128> bufferString{ "Fellow" };
  1941. bufferString.erase(bufferString.begin() + 5, bufferString.end());
  1942. bufferString.erase(bufferString.begin());
  1943. return bufferString;
  1944. }();
  1945. static_assert(test1 == "ello");
  1946. }
  1947. TEST_F(String, FixedString_FindMethodsAreConstexpr_Succeeds)
  1948. {
  1949. constexpr AZStd::fixed_string<128> bigString{ "skfhi3rildfhuy890uhklfjueosu8390hhklsahfiowh" };
  1950. static_assert(bigString.find("fh") == 2);
  1951. static_assert(bigString.find("fh", 4) == 10);
  1952. static_assert(bigString.find('0') == 16);
  1953. static_assert(bigString.find(AZStd::string_view{ "890" }) == 14);
  1954. static_assert(bigString.rfind("hh") == 32);
  1955. static_assert(bigString.rfind("hh", 31) == AZStd::fixed_string<128>::npos);
  1956. static_assert(bigString.rfind('o') == 41);
  1957. static_assert(bigString.rfind(AZStd::string_view{ "j" }) == 22);
  1958. static_assert(bigString.find_first_of("hf") == 2);
  1959. static_assert(bigString.find_first_of("hf", 4) == 10);
  1960. static_assert(bigString.find_first_of('0') == 16);
  1961. static_assert(bigString.find_first_of(AZStd::string_view{ "890" }) == 14);
  1962. static_assert(bigString.find_first_not_of("struct") == 1);
  1963. static_assert(bigString.find_first_not_of("struct", 17) == 18);
  1964. static_assert(bigString.find_first_not_of('w') == 0);
  1965. static_assert(bigString.find_first_not_of(AZStd::string_view{ "y" }, 13) == 14);
  1966. static_assert(bigString.find_last_of("hf") == 43);
  1967. static_assert(bigString.find_last_of("hf", 4) == 3);
  1968. static_assert(bigString.find_last_of('0') == 31);
  1969. static_assert(bigString.find_last_of(AZStd::string_view{ "893" }) == 30);
  1970. static_assert(bigString.find_last_not_of("hwoif") == 37);
  1971. static_assert(bigString.find_last_not_of("slh09a", 37) == 34);
  1972. static_assert(bigString.find_last_not_of('h') == 42);
  1973. static_assert(bigString.find_last_not_of(AZStd::string_view{ "why likes" }, 13) == 12);
  1974. }
  1975. TEST_F(String, FixedString_SwapIsConstexpr_Succeeds)
  1976. {
  1977. constexpr AZStd::fixed_string<64> test1 = []() constexpr
  1978. {
  1979. AZStd::fixed_string<64> bufferString1{ "First" };
  1980. AZStd::fixed_string<64> bufferString2{ "Second" };
  1981. bufferString1.swap(bufferString2);
  1982. return bufferString1;
  1983. }();
  1984. static_assert(test1 == "Second");
  1985. }
  1986. TEST_F(String, FixedString_DeductionGuide_Succeeds)
  1987. {
  1988. constexpr AZStd::basic_fixed_string deducedFixedString1{'H', 'e', 'l', 'l', 'o' };
  1989. static_assert(deducedFixedString1.max_size() == 5 );
  1990. static_assert(deducedFixedString1 == "Hello");
  1991. constexpr AZStd::basic_fixed_string deducedFixedString2{ L'H', L'e', L'l', L'l', L'o' };
  1992. static_assert(deducedFixedString2.max_size() == 5);
  1993. static_assert(deducedFixedString2 == L"Hello");
  1994. constexpr AZStd::basic_fixed_string deducedFromLiteralFixedString1 = "Hello";
  1995. static_assert(deducedFromLiteralFixedString1.max_size() == 5);
  1996. static_assert(deducedFromLiteralFixedString1 == "Hello");
  1997. constexpr AZStd::basic_fixed_string deducedFromLiteralFixedString2 = L"Hello";
  1998. static_assert(deducedFromLiteralFixedString2.max_size() == 5);
  1999. static_assert(deducedFromLiteralFixedString2 == L"Hello");
  2000. }
  2001. TEST_F(String, WildcardMatch_EmptyFilterWithNonEmptyValue_Fails)
  2002. {
  2003. AZStd::fixed_string<32> filter1;
  2004. AZStd::string testValue{ "test" };
  2005. EXPECT_FALSE(AZStd::wildcard_match(filter1, testValue));
  2006. }
  2007. TEST_F(String, WildcardMatch_EmptyFilterWithEmptyValue_Succeeds)
  2008. {
  2009. AZStd::fixed_string<32> filter1;
  2010. AZStd::fixed_string<32> emptyValue;
  2011. EXPECT_TRUE(AZStd::wildcard_match(filter1, emptyValue));
  2012. }
  2013. TEST_F(String, WildcardMatch_AsteriskOnlyFilterWithEmptyValue_Succeeds)
  2014. {
  2015. const char* filter1{ "*" };
  2016. const char* filter2{ "**" };
  2017. const char* emptyValue{ "" };
  2018. EXPECT_TRUE(AZStd::wildcard_match(filter1, emptyValue));
  2019. EXPECT_TRUE(AZStd::wildcard_match(filter2, emptyValue));
  2020. }
  2021. TEST_F(String, WildcardMatch_AsteriskQuestionMarkFilterWithEmptyValue_Failes)
  2022. {
  2023. // At least one character needs to be matched
  2024. const char* filter1{ "*?" };
  2025. const char* filter2{ "?*" };
  2026. const char* emptyValue{ "" };
  2027. EXPECT_FALSE(AZStd::wildcard_match(filter1, emptyValue));
  2028. EXPECT_FALSE(AZStd::wildcard_match(filter2, emptyValue));
  2029. }
  2030. TEST_F(String, WildcardMatch_DotValue_Succeeds)
  2031. {
  2032. const char* filter1{ "?" };
  2033. const char* dotValue{ "." };
  2034. EXPECT_TRUE(AZStd::wildcard_match(filter1, dotValue));
  2035. }
  2036. TEST_F(String, WildcardMatch_DoubleDotValue_Succeeds)
  2037. {
  2038. const char* filter1{ "??" };
  2039. const char* dotValue{ ".." };
  2040. EXPECT_TRUE(AZStd::wildcard_match(filter1, dotValue));
  2041. }
  2042. TEST_F(String, WildcardMatch_GlobFilters_Succeeds)
  2043. {
  2044. const char* filter1{ "*" };
  2045. const char* filter2{ "*?" };
  2046. const char* filter3{ "?*" };
  2047. EXPECT_TRUE(AZStd::wildcard_match(filter1, "Hello"));
  2048. EXPECT_TRUE(AZStd::wildcard_match(filter1, "?"));
  2049. EXPECT_TRUE(AZStd::wildcard_match(filter1, "*"));
  2050. EXPECT_TRUE(AZStd::wildcard_match(filter1, "Q"));
  2051. EXPECT_TRUE(AZStd::wildcard_match(filter2, "Hello"));
  2052. EXPECT_TRUE(AZStd::wildcard_match(filter2, "?"));
  2053. EXPECT_TRUE(AZStd::wildcard_match(filter2, "*"));
  2054. EXPECT_TRUE(AZStd::wildcard_match(filter2, "Q"));
  2055. EXPECT_TRUE(AZStd::wildcard_match(filter3, "Hello"));
  2056. EXPECT_TRUE(AZStd::wildcard_match(filter3, "?"));
  2057. EXPECT_TRUE(AZStd::wildcard_match(filter3, "*"));
  2058. EXPECT_TRUE(AZStd::wildcard_match(filter3, "Q"));
  2059. }
  2060. TEST_F(String, WildcardMatch_NormalString_Succeeds)
  2061. {
  2062. constexpr AZStd::string_view jpgFilter{ "**/*.jpg" };
  2063. EXPECT_FALSE(AZStd::wildcard_match(jpgFilter, "Test.jpg"));
  2064. EXPECT_FALSE(AZStd::wildcard_match(jpgFilter, "Test.jpfg"));
  2065. EXPECT_TRUE(AZStd::wildcard_match(jpgFilter, "Images/Other.jpg"));
  2066. EXPECT_FALSE(AZStd::wildcard_match(jpgFilter, "Pictures/Other.gif"));
  2067. constexpr AZStd::string_view tempDirFilter{ "temp/*" };
  2068. EXPECT_TRUE(AZStd::wildcard_match(tempDirFilter, "temp/"));
  2069. EXPECT_TRUE(AZStd::wildcard_match(tempDirFilter, "temp/f"));
  2070. EXPECT_FALSE(AZStd::wildcard_match(tempDirFilter, "tem1/"));
  2071. constexpr AZStd::string_view xmlFilter{ "test.xml" };
  2072. EXPECT_TRUE(AZStd::wildcard_match(xmlFilter, "Test.xml"));
  2073. EXPECT_TRUE(AZStd::wildcard_match(xmlFilter, "test.xml"));
  2074. EXPECT_FALSE(AZStd::wildcard_match(xmlFilter, "test.xmlschema"));
  2075. EXPECT_FALSE(AZStd::wildcard_match(xmlFilter, "Xtest.xml"));
  2076. }
  2077. TEST_F(String, WildcardMatchCase_CanBeCompileTimeEvaluated_Succeeds)
  2078. {
  2079. constexpr AZStd::string_view filter1{ "bl?h.*" };
  2080. constexpr AZStd::fixed_string<32> blahValue{ "blah.jpg" };
  2081. static_assert(AZStd::wildcard_match_case(filter1, blahValue));
  2082. }
  2083. TEST_F(String, StringCXX20Erase_Succeeds)
  2084. {
  2085. AZStd::string eraseIfTest = "ABC CBA";
  2086. auto erasePredicate = [](AZStd::string::value_type ch)
  2087. {
  2088. return ch == 'C';
  2089. };
  2090. auto eraseCount = AZStd::erase_if(eraseIfTest, erasePredicate);
  2091. EXPECT_EQ(2, eraseCount);
  2092. EXPECT_EQ(5, eraseIfTest.size());
  2093. EXPECT_STREQ("AB BA", eraseIfTest.c_str());
  2094. // Now erase the letter 'A';
  2095. eraseCount = AZStd::erase(eraseIfTest, 'A');
  2096. EXPECT_EQ(2, eraseCount);
  2097. EXPECT_EQ(3, eraseIfTest.size());
  2098. EXPECT_EQ("B B", eraseIfTest);
  2099. }
  2100. TEST_F(String, FixedStringCXX20Erase_Succeeds)
  2101. {
  2102. // Erase 'l' from the phrase "Hello" World"
  2103. constexpr auto eraseTest = [](const char* testString) constexpr
  2104. {
  2105. AZStd::fixed_string<16> testResult{ testString };
  2106. AZStd::erase(testResult, 'l');
  2107. return testResult;
  2108. }("HelloWorld");
  2109. static_assert(eraseTest == "HeoWord");
  2110. EXPECT_EQ("HeoWord", eraseTest);
  2111. // Use erase_if to erase both 'H' and 'e' from the remaining eraseTest string
  2112. constexpr auto eraseIfTest = [](AZStd::string_view testString) constexpr
  2113. {
  2114. AZStd::fixed_string<16> testResult{ testString };
  2115. auto erasePredicate = [](char ch)
  2116. {
  2117. return ch == 'H' || ch == 'e';
  2118. };
  2119. AZStd::erase_if(testResult, erasePredicate);
  2120. return testResult;
  2121. }(eraseTest);
  2122. static_assert(eraseIfTest == "oWord");
  2123. EXPECT_EQ("oWord", eraseIfTest);
  2124. }
  2125. TEST_F(String, StringWithStatelessAllocator_HasSizeOf_PointerPlus2IntTypes_Compiles)
  2126. {
  2127. // The expected size of a basic_string with a stateless allocator
  2128. // Is the size of the pointer (used for storing the memory address of the string)
  2129. // + the size of the string "size" member used to store the size of the string
  2130. // + the size of the string "capacity" member used to store the capacity of the string
  2131. size_t constexpr ExpectedBasicStringSize = sizeof(void*) + 2 * sizeof(size_t);
  2132. using StringStatelessAllocator = AZStd::basic_string<char, AZStd::char_traits<char>, AZStd::stateless_allocator>;
  2133. static_assert(ExpectedBasicStringSize == sizeof(StringStatelessAllocator),
  2134. "Stateless allocator is counting against the size of the basic_string class"
  2135. " A change has made to break the empty base optimization of the basic_string class");
  2136. }
  2137. TEST_F(String, StringWithStatefulAllocator_HasSizeOf_PointerPlus2IntTypesPlusAllocator_Compiles)
  2138. {
  2139. // The expected size of a basic_string with a stateless allocator
  2140. // Is the size of the pointer (used for storing the memory address of the string)
  2141. // + the size of the string "size" member used to store the size of the string
  2142. // + the size of the string "capacity" member used to store the capacity of the string
  2143. size_t constexpr ExpectedBasicStringSize = sizeof(void*) + 2 * sizeof(size_t);
  2144. static_assert(ExpectedBasicStringSize == sizeof(AZStd::string),
  2145. "Using Stateful allocator with basic_string class should result in a 24-byte string class"
  2146. " on 64-bit platforms ");
  2147. }
  2148. TEST_F(String, VectorOfChar_ConvertibleToStringView_Compiles)
  2149. {
  2150. // Validates the c++23 range constructor for AZStd::string_view
  2151. static_assert(AZStd::constructible_from<AZStd::string_view, AZStd::vector<char>>);
  2152. static_assert(AZStd::constructible_from<AZStd::string, AZStd::vector<char>>);
  2153. const auto testString = AZStd::string(AZStd::vector<char>{'H', 'e', 'l', 'l', 'o'});
  2154. EXPECT_EQ("Hello", testString);
  2155. }
  2156. TEST_F(String, AZStdString_DeductionGuide_Compiles)
  2157. {
  2158. constexpr AZStd::string_view testView{ "Hello" };
  2159. {
  2160. // legacy common iterator deduction guide
  2161. AZStd::basic_string testString(testView.begin(), testView.end());
  2162. EXPECT_EQ("Hello", testString);
  2163. }
  2164. {
  2165. // basic_string_view deduction guide
  2166. AZStd::basic_string testString(testView);
  2167. EXPECT_EQ("Hello", testString);
  2168. }
  2169. {
  2170. // basic_string_view with position and size deduction guide
  2171. AZStd::basic_string testString(testView, 1, 3);
  2172. EXPECT_EQ("ell", testString);
  2173. }
  2174. }
  2175. template <typename StringType>
  2176. class ImmutableStringFunctionsFixture
  2177. : public LeakDetectionFixture
  2178. {};
  2179. using StringTypesToTest = ::testing::Types<AZStd::string_view, AZStd::string, AZStd::fixed_string<1024>>;
  2180. TYPED_TEST_CASE(ImmutableStringFunctionsFixture, StringTypesToTest);
  2181. TYPED_TEST(ImmutableStringFunctionsFixture, Contains_Succeeds)
  2182. {
  2183. TypeParam testStrValue{ R"(C:\o3de\Assets\Materials\texture\image.png)" };
  2184. EXPECT_TRUE(testStrValue.contains("Materials"));
  2185. EXPECT_FALSE(testStrValue.contains("Animations"));
  2186. EXPECT_TRUE(testStrValue.contains('o'));
  2187. EXPECT_FALSE(testStrValue.contains('Q'));
  2188. TypeParam typeParamEntry{ R"(texture)" };
  2189. TypeParam typeParamNoEntry{ R"(physics)" };
  2190. EXPECT_TRUE(testStrValue.contains(typeParamEntry));
  2191. EXPECT_FALSE(testStrValue.contains(typeParamNoEntry));
  2192. }
  2193. template<typename T>
  2194. const T* GetFormatString()
  2195. {
  2196. return "%s";
  2197. }
  2198. template <>
  2199. const wchar_t* GetFormatString<wchar_t>()
  2200. {
  2201. return L"%s";
  2202. }
  2203. template<typename T>
  2204. class StringFormatFixture
  2205. : public UnitTest::LeakDetectionFixture
  2206. {
  2207. };
  2208. using StringFormatTypesToTest = ::testing::Types<AZStd::string>; //, AZStd::wstring>;
  2209. TYPED_TEST_CASE(StringFormatFixture, StringFormatTypesToTest);
  2210. TYPED_TEST(StringFormatFixture, CanFormatStringLongerThan2048Chars)
  2211. {
  2212. TypeParam str(4096, 'x');
  2213. TypeParam formatted = TypeParam::format(GetFormatString<typename TypeParam::value_type>(), str.c_str());
  2214. EXPECT_EQ(str, formatted);
  2215. }
  2216. template<typename T>
  2217. class StringTypeFixture
  2218. : public LeakDetectionFixture
  2219. {};
  2220. using StringTypeWithRangeFunctions = ::testing::Types<AZStd::string, AZStd::fixed_string<32>>;
  2221. TYPED_TEST_CASE(StringTypeFixture, StringTypeWithRangeFunctions);
  2222. TYPED_TEST(StringTypeFixture, RangeConstructor_Succeeds)
  2223. {
  2224. constexpr AZStd::string_view testView = "abc";
  2225. TypeParam testString(AZStd::from_range, testView);
  2226. EXPECT_EQ("abc", testString);
  2227. testString = TypeParam(AZStd::from_range, AZStd::vector<char>{testView.begin(), testView.end()});
  2228. EXPECT_EQ("abc", testString);
  2229. testString = TypeParam(AZStd::from_range, AZStd::list<char>{testView.begin(), testView.end()});
  2230. EXPECT_EQ("abc", testString);
  2231. testString = TypeParam(AZStd::from_range, AZStd::deque<char>{testView.begin(), testView.end()});
  2232. EXPECT_EQ("abc", testString);
  2233. testString = TypeParam(AZStd::from_range, AZStd::set<char>{testView.begin(), testView.end()});
  2234. EXPECT_EQ("abc", testString);
  2235. testString = TypeParam(AZStd::from_range, AZStd::unordered_set<char>{testView.begin(), testView.end()});
  2236. EXPECT_EQ("abc", testString);
  2237. testString = TypeParam(AZStd::from_range, AZStd::fixed_vector<char, 8>{testView.begin(), testView.end()});
  2238. EXPECT_EQ("abc", testString);
  2239. testString = TypeParam(AZStd::from_range, AZStd::array{ 'a', 'b', 'c' });
  2240. EXPECT_EQ("abc", testString);
  2241. testString = TypeParam(AZStd::from_range, AZStd::span(testView));
  2242. EXPECT_EQ("abc", testString);
  2243. AZStd::fixed_string<8> testValue(testView);
  2244. testString = TypeParam(AZStd::from_range, testValue);
  2245. EXPECT_EQ("abc", testString);
  2246. testString = TypeParam(AZStd::from_range, AZStd::string(testView));
  2247. EXPECT_EQ("abc", testString);
  2248. // Test Range views
  2249. testString = TypeParam(AZStd::from_range, testValue | AZStd::views::transform([](const char elem) -> char { return elem + 1; }));
  2250. EXPECT_EQ("bcd", testString);
  2251. // Test Ranges with different sentinel types
  2252. testString = TypeParam(AZStd::from_range, testValue | AZStd::views::transform([](const char elem)
  2253. { return AZStd::fixed_string<2>{ char(elem + 1) }; }) | AZStd::views::join);
  2254. EXPECT_EQ("bcd", testString);
  2255. }
  2256. TYPED_TEST(StringTypeFixture, InsertRange_Succeeds)
  2257. {
  2258. constexpr AZStd::string_view testView = "abc";
  2259. TypeParam testString{ 'd', 'e', 'f' };
  2260. testString.insert_range(testString.begin(), AZStd::vector<char>{testView.begin(), testView.end()});
  2261. testString.insert_range(testString.end(), testView | AZStd::views::transform([](const char elem) -> char { return elem + 6; }));
  2262. EXPECT_EQ("abcdefghi", testString);
  2263. }
  2264. TYPED_TEST(StringTypeFixture, AppendRange_Succeeds)
  2265. {
  2266. constexpr AZStd::string_view testView = "def";
  2267. TypeParam testString{ 'a', 'b', 'c' };
  2268. testString.append_range(AZStd::vector<char>{testView.begin(), testView.end()});
  2269. testString.append_range(testView | AZStd::views::transform([](const char elem) -> char { return elem + 3; }));
  2270. EXPECT_THAT(testString, ::testing::ElementsAre('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'));
  2271. EXPECT_EQ("abcdefghi", testString);
  2272. }
  2273. TYPED_TEST(StringTypeFixture, AssignRange_Succeeds)
  2274. {
  2275. constexpr AZStd::string_view testView = "def";
  2276. TypeParam testString{ 'a', 'b', 'c' };
  2277. testString.assign_range(AZStd::vector<char>{testView.begin(), testView.end()});
  2278. EXPECT_EQ("def", testString);
  2279. testString.assign_range(testView | AZStd::views::transform([](const char elem) -> char { return elem + 3; }));
  2280. EXPECT_EQ("ghi", testString);
  2281. }
  2282. TYPED_TEST(StringTypeFixture, ReplaceWithRange_Succeeds)
  2283. {
  2284. constexpr AZStd::string_view testView = "def";
  2285. TypeParam testString{ 'a', 'b', 'c' };
  2286. // Replace 'a' with 'd', 'e', 'f'
  2287. testString.replace_with_range(testString.begin(), testString.begin() + 1, AZStd::vector<char>{testView.begin(), testView.end()});
  2288. EXPECT_EQ("defbc", testString);
  2289. // Replace 'b', 'c' with 'g', 'h', 'i'
  2290. testString.replace_with_range(testString.begin() + 3, testString.end() + 5, testView | AZStd::views::transform([](const char elem) -> char { return elem + 3; }));
  2291. EXPECT_EQ("defghi", testString);
  2292. }
  2293. TYPED_TEST(StringTypeFixture, ResizeAndOverwrite_AddChars_Succeeds)
  2294. {
  2295. constexpr AZStd::string_view testView = "abcdef";
  2296. TypeParam testString("abc");
  2297. auto AppendCharacters = [oldSize = testString.size()](char* dataPtr, size_t newSize) -> size_t
  2298. {
  2299. constexpr AZStd::string_view appendChars = "def";
  2300. ::memcpy(dataPtr + oldSize, appendChars.data(), appendChars.size());
  2301. EXPECT_LE(oldSize + appendChars.size(), newSize);
  2302. return oldSize + appendChars.size();
  2303. };
  2304. testString.resize_and_overwrite(testView.size(), AppendCharacters);
  2305. ASSERT_EQ(testView.size(), testString.size());
  2306. EXPECT_EQ(testView, testString);
  2307. // Validate that a size larger than the new resize, shrinks to the
  2308. // exact size used
  2309. auto ReplaceCharacters = [&testView](char* dataPtr, size_t newSize) -> size_t
  2310. {
  2311. ::memcpy(dataPtr, testView.data(), testView.size());
  2312. EXPECT_LE(testView.size(), newSize);
  2313. return testView.size();
  2314. };
  2315. // Resize to 25 characters
  2316. testString.resize_and_overwrite(testView.size() + 25, ReplaceCharacters);
  2317. // Size of testString should be the size of the testView which is 6
  2318. ASSERT_EQ(testView.size(), testString.size());
  2319. EXPECT_EQ(testView, testString);
  2320. }
  2321. TYPED_TEST(StringTypeFixture, ResizeAndOverwrite_RemoveChars_Succeeds)
  2322. {
  2323. constexpr AZStd::string_view testView = "abc";
  2324. TypeParam testString("abcdef");
  2325. auto RemoveCharacters = [&testView](char* dataPtr, size_t newSize) -> size_t
  2326. {
  2327. ::memcpy(dataPtr, testView.data(), testView.size());
  2328. EXPECT_LE(testView.size(), newSize);
  2329. return testView.size();
  2330. };
  2331. // Resize from 6 to 3 characters
  2332. testString.resize_and_overwrite(testView.size(), RemoveCharacters);
  2333. ASSERT_EQ(testView.size(), testString.size());
  2334. EXPECT_EQ(testView, testString);
  2335. }
  2336. }
  2337. #if defined(HAVE_BENCHMARK)
  2338. namespace Benchmark
  2339. {
  2340. class StringBenchmarkFixture
  2341. : public ::UnitTest::AllocatorsBenchmarkFixture
  2342. {
  2343. protected:
  2344. template <typename Element, typename Traits, typename Allocator>
  2345. void SwapStringViaMemcpy(AZStd::basic_string<Element, Traits, Allocator>& left,
  2346. AZStd::basic_string<Element, Traits, Allocator>& right)
  2347. {
  2348. // Test Swapping the storage container for the string class
  2349. // Use aligned_storage to prevent constructors from slowing operation
  2350. AZStd::aligned_storage_for_t<decltype(left.m_storage.first())> tempStorage;
  2351. ::memcpy(&tempStorage, &left.m_storage.first(), sizeof(left.m_storage.first()));
  2352. ::memcpy(&left.m_storage.first(), &right.m_storage.first(), sizeof(right.m_storage.first()));
  2353. ::memcpy(&right.m_storage.first(), &tempStorage, sizeof(tempStorage));
  2354. }
  2355. template <typename Element, typename Traits, typename Allocator>
  2356. void SwapStringViaPointerSizedSwaps(AZStd::basic_string<Element, Traits, Allocator>& left,
  2357. AZStd::basic_string<Element, Traits, Allocator>& right)
  2358. {
  2359. using String = AZStd::basic_string<Element, Traits, Allocator>;
  2360. using PointerAlignedData = typename String::PointerAlignedData;
  2361. // Use pointer sized swaps to swap the string storage
  2362. auto& leftAlignedPointers = reinterpret_cast<PointerAlignedData&>(left.m_storage.first());
  2363. auto& rightAlignedPointers = reinterpret_cast<PointerAlignedData&>(right.m_storage.first());
  2364. constexpr size_t alignedPointerCount{ AZStd::size(PointerAlignedData{}.m_alignedValues) };
  2365. for (size_t i = 0; i < alignedPointerCount; ++i)
  2366. {
  2367. AZStd::swap(leftAlignedPointers.m_alignedValues[i], rightAlignedPointers.m_alignedValues[i]);
  2368. }
  2369. }
  2370. };
  2371. BENCHMARK_F(StringBenchmarkFixture, BM_StringPointerSwapShortString)(benchmark::State& state)
  2372. {
  2373. AZStd::string test1{ "foo bar"};
  2374. AZStd::string test2{ "bar foo" };
  2375. for ([[maybe_unused]] auto _ : state)
  2376. {
  2377. SwapStringViaPointerSizedSwaps(test1, test2);
  2378. }
  2379. }
  2380. BENCHMARK_F(StringBenchmarkFixture, BM_StringPointerSwapLongString)(benchmark::State& state)
  2381. {
  2382. AZStd::string test1{ "The brown quick wolf jumped over the hyperactive cat" };
  2383. AZStd::string test2{ "The quick brown fox jumped over the lazy dog" };
  2384. for ([[maybe_unused]] auto _ : state)
  2385. {
  2386. SwapStringViaPointerSizedSwaps(test1, test2);
  2387. }
  2388. }
  2389. BENCHMARK_F(StringBenchmarkFixture, BM_StringMemcpySwapShortString)(benchmark::State& state)
  2390. {
  2391. AZStd::string test1{ "foo bar" };
  2392. AZStd::string test2{ "bar foo" };
  2393. for ([[maybe_unused]] auto _ : state)
  2394. {
  2395. SwapStringViaMemcpy(test1, test2);
  2396. }
  2397. }
  2398. BENCHMARK_F(StringBenchmarkFixture, BM_StringMemcpySwapLongString)(benchmark::State& state)
  2399. {
  2400. AZStd::string test1{ "The brown quick wolf jumped over the hyperactive cat" };
  2401. AZStd::string test2{ "The quick brown fox jumped over the lazy dog" };
  2402. for ([[maybe_unused]] auto _ : state)
  2403. {
  2404. SwapStringViaMemcpy(test1, test2);
  2405. }
  2406. }
  2407. template <typename StringType>
  2408. class StringTemplateBenchmarkFixture
  2409. : public ::UnitTest::AllocatorsBenchmarkFixture
  2410. {};
  2411. // AZStd::string assign benchmarks
  2412. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignConstPointer_NullDelimited, AZStd::string)(benchmark::State& state)
  2413. {
  2414. AZStd::string sourceString(state.range(0), 'a');
  2415. const char* sourceAddress = sourceString.c_str();
  2416. for ([[maybe_unused]] auto _ : state)
  2417. {
  2418. AZStd::string assignString;
  2419. assignString.assign(sourceAddress);
  2420. }
  2421. }
  2422. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignConstPointer_NullDelimited)
  2423. ->RangeMultiplier(2)->Range(8, 32);
  2424. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignConstPointer_WithSize, AZStd::string)(benchmark::State& state)
  2425. {
  2426. AZStd::string sourceString(state.range(0), 'a');
  2427. const char* sourceAddress = sourceString.c_str();
  2428. const size_t sourceSize = sourceString.size();
  2429. for ([[maybe_unused]] auto _ : state)
  2430. {
  2431. AZStd::string assignString;
  2432. assignString.assign(sourceAddress, sourceSize);
  2433. }
  2434. }
  2435. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignConstPointer_WithSize)
  2436. ->RangeMultiplier(2)->Range(8, 32);
  2437. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromIterators, AZStd::string)(benchmark::State& state)
  2438. {
  2439. AZStd::string sourceString(state.range(0), 'a');
  2440. auto sourceBegin = sourceString.begin();
  2441. auto sourceEnd = sourceString.end();
  2442. for ([[maybe_unused]] auto _ : state)
  2443. {
  2444. AZStd::string assignString;
  2445. assignString.assign(sourceBegin, sourceEnd);
  2446. }
  2447. }
  2448. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignFromIterators)
  2449. ->RangeMultiplier(2)->Range(8, 32);
  2450. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromStringView, AZStd::string)(benchmark::State& state)
  2451. {
  2452. AZStd::string sourceString(state.range(0), 'a');
  2453. AZStd::string_view sourceView(sourceString);
  2454. for ([[maybe_unused]] auto _ : state)
  2455. {
  2456. AZStd::string assignString;
  2457. assignString.assign(sourceView);
  2458. }
  2459. }
  2460. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignFromStringView)
  2461. ->RangeMultiplier(2)->Range(8, 32);
  2462. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromString_LValue, AZStd::string)(benchmark::State& state)
  2463. {
  2464. AZStd::string sourceString(state.range(0), 'a');
  2465. for ([[maybe_unused]] auto _ : state)
  2466. {
  2467. AZStd::string assignString;
  2468. assignString.assign(sourceString);
  2469. }
  2470. }
  2471. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignFromString_LValue)
  2472. ->RangeMultiplier(2)->Range(8, 32);
  2473. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromString_RValue, AZStd::string)(benchmark::State& state)
  2474. {
  2475. AZStd::string sourceString(state.range(0), 'a');
  2476. for ([[maybe_unused]] auto _ : state)
  2477. {
  2478. AZStd::string assignString;
  2479. assignString.assign(AZStd::move(sourceString));
  2480. }
  2481. }
  2482. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignFromString_RValue)
  2483. ->RangeMultiplier(2)->Range(8, 32);
  2484. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_StringAssignFromSingleCharacter, AZStd::string)(benchmark::State& state)
  2485. {
  2486. for ([[maybe_unused]] auto _ : state)
  2487. {
  2488. AZStd::string assignString;
  2489. assignString.assign(state.range(0), 'a');
  2490. }
  2491. }
  2492. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_StringAssignFromSingleCharacter)
  2493. ->RangeMultiplier(2)->Range(8, 32);
  2494. // AZStd::fixed_string assign benchmarks
  2495. // NOTE: This is a copy-and-paste of above because Google Benchmark doesn't support real templated benchmarks like Googletest
  2496. // https://github.com/google/benchmark/issues/541
  2497. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignConstPointer_NullDelimited, AZStd::fixed_string<1024>)(benchmark::State& state)
  2498. {
  2499. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2500. const char* sourceAddress = sourceString.c_str();
  2501. for ([[maybe_unused]] auto _ : state)
  2502. {
  2503. AZStd::fixed_string<1024> assignString;
  2504. assignString.assign(sourceAddress);
  2505. }
  2506. }
  2507. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignConstPointer_NullDelimited)
  2508. ->RangeMultiplier(2)->Range(8, 32);
  2509. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignConstPointer_WithSize, AZStd::fixed_string<1024>)(benchmark::State& state)
  2510. {
  2511. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2512. const char* sourceAddress = sourceString.c_str();
  2513. const size_t sourceSize = sourceString.size();
  2514. for ([[maybe_unused]] auto _ : state)
  2515. {
  2516. AZStd::fixed_string<1024> assignString;
  2517. assignString.assign(sourceAddress, sourceSize);
  2518. }
  2519. }
  2520. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignConstPointer_WithSize)
  2521. ->RangeMultiplier(2)->Range(8, 32);
  2522. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromIterators, AZStd::fixed_string<1024>)(benchmark::State& state)
  2523. {
  2524. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2525. auto sourceBegin = sourceString.begin();
  2526. auto sourceEnd = sourceString.end();
  2527. for ([[maybe_unused]] auto _ : state)
  2528. {
  2529. AZStd::fixed_string<1024> assignString;
  2530. assignString.assign(sourceBegin, sourceEnd);
  2531. }
  2532. }
  2533. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromIterators)
  2534. ->RangeMultiplier(2)->Range(8, 32);
  2535. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromStringView, AZStd::fixed_string<1024>)(benchmark::State& state)
  2536. {
  2537. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2538. AZStd::string_view sourceView(sourceString);
  2539. for ([[maybe_unused]] auto _ : state)
  2540. {
  2541. AZStd::fixed_string<1024> assignString;
  2542. assignString.assign(sourceView);
  2543. }
  2544. }
  2545. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromStringView)
  2546. ->RangeMultiplier(2)->Range(8, 32);
  2547. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromString_LValue, AZStd::fixed_string<1024>)(benchmark::State& state)
  2548. {
  2549. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2550. for ([[maybe_unused]] auto _ : state)
  2551. {
  2552. AZStd::fixed_string<1024> assignString;
  2553. assignString.assign(sourceString);
  2554. }
  2555. }
  2556. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromString_LValue)
  2557. ->RangeMultiplier(2)->Range(8, 32);
  2558. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromString_RValue, AZStd::fixed_string<1024>)(benchmark::State& state)
  2559. {
  2560. AZStd::fixed_string<1024> sourceString(state.range(0), 'a');
  2561. for ([[maybe_unused]] auto _ : state)
  2562. {
  2563. AZStd::fixed_string<1024> assignString;
  2564. assignString.assign(AZStd::move(sourceString));
  2565. }
  2566. }
  2567. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromString_RValue)
  2568. ->RangeMultiplier(2)->Range(8, 32);
  2569. BENCHMARK_TEMPLATE_DEFINE_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromSingleCharacter, AZStd::fixed_string<1024>)(benchmark::State& state)
  2570. {
  2571. for ([[maybe_unused]] auto _ : state)
  2572. {
  2573. AZStd::fixed_string<1024> assignString;
  2574. assignString.assign(state.range(0), 'a');
  2575. }
  2576. }
  2577. BENCHMARK_REGISTER_F(StringTemplateBenchmarkFixture, BM_FixedStringAssignFromSingleCharacter)
  2578. ->RangeMultiplier(2)->Range(8, 32);
  2579. }
  2580. #endif