String.cpp 126 KB

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