strings.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: tests/strings/strings.cpp
  3. // Purpose: wxString unit test
  4. // Author: Vadim Zeitlin, Wlodzimierz ABX Skiba
  5. // Created: 2004-04-19
  6. // Copyright: (c) 2004 Vadim Zeitlin, Wlodzimierz Skiba
  7. ///////////////////////////////////////////////////////////////////////////////
  8. // ----------------------------------------------------------------------------
  9. // headers
  10. // ----------------------------------------------------------------------------
  11. #include "testprec.h"
  12. #ifdef __BORLANDC__
  13. #pragma hdrstop
  14. #endif
  15. #ifndef WX_PRECOMP
  16. #include "wx/wx.h"
  17. #endif // WX_PRECOMP
  18. // ----------------------------------------------------------------------------
  19. // test class
  20. // ----------------------------------------------------------------------------
  21. class StringTestCase : public CppUnit::TestCase
  22. {
  23. public:
  24. StringTestCase();
  25. private:
  26. CPPUNIT_TEST_SUITE( StringTestCase );
  27. CPPUNIT_TEST( String );
  28. CPPUNIT_TEST( PChar );
  29. CPPUNIT_TEST( Format );
  30. CPPUNIT_TEST( FormatUnicode );
  31. CPPUNIT_TEST( Constructors );
  32. CPPUNIT_TEST( StaticConstructors );
  33. CPPUNIT_TEST( Extraction );
  34. CPPUNIT_TEST( Trim );
  35. CPPUNIT_TEST( Find );
  36. CPPUNIT_TEST( Replace );
  37. CPPUNIT_TEST( Match );
  38. CPPUNIT_TEST( CaseChanges );
  39. CPPUNIT_TEST( Compare );
  40. CPPUNIT_TEST( CompareNoCase );
  41. CPPUNIT_TEST( Contains );
  42. CPPUNIT_TEST( ToLong );
  43. CPPUNIT_TEST( ToULong );
  44. #ifdef wxLongLong_t
  45. CPPUNIT_TEST( ToLongLong );
  46. CPPUNIT_TEST( ToULongLong );
  47. #endif // wxLongLong_t
  48. CPPUNIT_TEST( ToDouble );
  49. CPPUNIT_TEST( FromDouble );
  50. CPPUNIT_TEST( StringBuf );
  51. CPPUNIT_TEST( UTF8Buf );
  52. CPPUNIT_TEST( CStrDataTernaryOperator );
  53. CPPUNIT_TEST( CStrDataOperators );
  54. CPPUNIT_TEST( CStrDataImplicitConversion );
  55. CPPUNIT_TEST( ExplicitConversion );
  56. CPPUNIT_TEST( IndexedAccess );
  57. CPPUNIT_TEST( BeforeAndAfter );
  58. CPPUNIT_TEST( ScopedBuffers );
  59. CPPUNIT_TEST_SUITE_END();
  60. void String();
  61. void PChar();
  62. void Format();
  63. void FormatUnicode();
  64. void Constructors();
  65. void StaticConstructors();
  66. void Extraction();
  67. void Trim();
  68. void Find();
  69. void Replace();
  70. void Match();
  71. void CaseChanges();
  72. void Compare();
  73. void CompareNoCase();
  74. void Contains();
  75. void ToLong();
  76. void ToULong();
  77. #ifdef wxLongLong_t
  78. void ToLongLong();
  79. void ToULongLong();
  80. #endif // wxLongLong_t
  81. void ToDouble();
  82. void FromDouble();
  83. void StringBuf();
  84. void UTF8Buf();
  85. void CStrDataTernaryOperator();
  86. void DoCStrDataTernaryOperator(bool cond);
  87. void CStrDataOperators();
  88. void CStrDataImplicitConversion();
  89. void ExplicitConversion();
  90. void IndexedAccess();
  91. void BeforeAndAfter();
  92. void ScopedBuffers();
  93. DECLARE_NO_COPY_CLASS(StringTestCase)
  94. };
  95. // register in the unnamed registry so that these tests are run by default
  96. CPPUNIT_TEST_SUITE_REGISTRATION( StringTestCase );
  97. // also include in its own registry so that these tests can be run alone
  98. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( StringTestCase, "StringTestCase" );
  99. StringTestCase::StringTestCase()
  100. {
  101. }
  102. void StringTestCase::String()
  103. {
  104. wxString a, b, c;
  105. a.reserve (128);
  106. b.reserve (128);
  107. c.reserve (128);
  108. for (int i = 0; i < 2; ++i)
  109. {
  110. a = wxT("Hello");
  111. b = wxT(" world");
  112. c = wxT("! How'ya doin'?");
  113. a += b;
  114. a += c;
  115. c = wxT("Hello world! What's up?");
  116. CPPUNIT_ASSERT( c != a );
  117. }
  118. }
  119. void StringTestCase::PChar()
  120. {
  121. wxChar a [128];
  122. wxChar b [128];
  123. wxChar c [128];
  124. for (int i = 0; i < 2; ++i)
  125. {
  126. wxStrcpy (a, wxT("Hello"));
  127. wxStrcpy (b, wxT(" world"));
  128. wxStrcpy (c, wxT("! How'ya doin'?"));
  129. wxStrcat (a, b);
  130. wxStrcat (a, c);
  131. wxStrcpy (c, wxT("Hello world! What's up?"));
  132. CPPUNIT_ASSERT( wxStrcmp (c, a) != 0 );
  133. }
  134. }
  135. void StringTestCase::Format()
  136. {
  137. wxString s1,s2;
  138. s1.Printf(wxT("%03d"), 18);
  139. CPPUNIT_ASSERT( s1 == wxString::Format(wxT("%03d"), 18) );
  140. s2.Printf(wxT("Number 18: %s\n"), s1.c_str());
  141. CPPUNIT_ASSERT( s2 == wxString::Format(wxT("Number 18: %s\n"), s1.c_str()) );
  142. static const size_t lengths[] = { 1, 512, 1024, 1025, 2048, 4096, 4097 };
  143. for ( size_t n = 0; n < WXSIZEOF(lengths); n++ )
  144. {
  145. const size_t len = lengths[n];
  146. wxString s(wxT('Z'), len);
  147. CPPUNIT_ASSERT_EQUAL( len, wxString::Format(wxT("%s"), s.c_str()).length());
  148. }
  149. CPPUNIT_ASSERT_EQUAL
  150. (
  151. "two one",
  152. wxString::Format(wxT("%2$s %1$s"), wxT("one"), wxT("two"))
  153. );
  154. }
  155. void StringTestCase::FormatUnicode()
  156. {
  157. #if wxUSE_UNICODE
  158. const char *UNICODE_STR = "Iestat\xC4\xAB %i%i";
  159. //const char *UNICODE_STR = "Iestat\xCC\x84 %i%i";
  160. wxString fmt = wxString::FromUTF8(UNICODE_STR);
  161. wxString s = wxString::Format(fmt, 1, 1);
  162. wxString expected(fmt);
  163. expected.Replace("%i", "1");
  164. CPPUNIT_ASSERT_EQUAL( expected, s );
  165. #endif // wxUSE_UNICODE
  166. }
  167. void StringTestCase::Constructors()
  168. {
  169. CPPUNIT_ASSERT_EQUAL( "", wxString('Z', 0) );
  170. CPPUNIT_ASSERT_EQUAL( "Z", wxString('Z') );
  171. CPPUNIT_ASSERT_EQUAL( "ZZZZ", wxString('Z', 4) );
  172. CPPUNIT_ASSERT_EQUAL( "Hell", wxString("Hello", 4) );
  173. CPPUNIT_ASSERT_EQUAL( "Hello", wxString("Hello", 5) );
  174. #if wxUSE_UNICODE
  175. CPPUNIT_ASSERT_EQUAL( L"", wxString(L'Z', 0) );
  176. CPPUNIT_ASSERT_EQUAL( L"Z", wxString(L'Z') );
  177. CPPUNIT_ASSERT_EQUAL( L"ZZZZ", wxString(L'Z', 4) );
  178. CPPUNIT_ASSERT_EQUAL( L"Hell", wxString(L"Hello", 4) );
  179. CPPUNIT_ASSERT_EQUAL( L"Hello", wxString(L"Hello", 5) );
  180. #endif // wxUSE_UNICODE
  181. CPPUNIT_ASSERT_EQUAL( 0, wxString(wxString(), 17).length() );
  182. #if wxUSE_UNICODE_UTF8
  183. // This string has 3 characters (<h>, <e'> and <l>), not 4 when using UTF-8
  184. // locale!
  185. if ( wxConvLibc.IsUTF8() )
  186. {
  187. wxString s3("h\xc3\xa9llo", 4);
  188. CPPUNIT_ASSERT_EQUAL( 3, s3.length() );
  189. CPPUNIT_ASSERT_EQUAL( 'l', (char)s3[2] );
  190. }
  191. #endif // wxUSE_UNICODE_UTF8
  192. static const char *s = "?really!";
  193. const char *start = wxStrchr(s, 'r');
  194. const char *end = wxStrchr(s, '!');
  195. CPPUNIT_ASSERT_EQUAL( "really", wxString(start, end) );
  196. // test if creating string from NULL C pointer works:
  197. CPPUNIT_ASSERT_EQUAL( "", wxString((const char *)NULL) );
  198. }
  199. void StringTestCase::StaticConstructors()
  200. {
  201. CPPUNIT_ASSERT_EQUAL( "", wxString::FromAscii("") );
  202. CPPUNIT_ASSERT_EQUAL( "", wxString::FromAscii("Hello", 0) );
  203. CPPUNIT_ASSERT_EQUAL( "Hell", wxString::FromAscii("Hello", 4) );
  204. CPPUNIT_ASSERT_EQUAL( "Hello", wxString::FromAscii("Hello", 5) );
  205. CPPUNIT_ASSERT_EQUAL( "Hello", wxString::FromAscii("Hello") );
  206. // FIXME: this doesn't work currently but should!
  207. //CPPUNIT_ASSERT_EQUAL( 1, wxString::FromAscii("", 1).length() );
  208. CPPUNIT_ASSERT_EQUAL( "", wxString::FromUTF8("") );
  209. CPPUNIT_ASSERT_EQUAL( "", wxString::FromUTF8("Hello", 0) );
  210. CPPUNIT_ASSERT_EQUAL( "Hell", wxString::FromUTF8("Hello", 4) );
  211. CPPUNIT_ASSERT_EQUAL( "Hello", wxString::FromUTF8("Hello", 5) );
  212. CPPUNIT_ASSERT_EQUAL( "Hello", wxString::FromUTF8("Hello") );
  213. CPPUNIT_ASSERT_EQUAL( 2, wxString::FromUTF8("h\xc3\xa9llo", 3).length() );
  214. //CPPUNIT_ASSERT_EQUAL( 1, wxString::FromUTF8("", 1).length() );
  215. }
  216. void StringTestCase::Extraction()
  217. {
  218. wxString s(wxT("Hello, world!"));
  219. CPPUNIT_ASSERT( wxStrcmp( s.c_str() , wxT("Hello, world!") ) == 0 );
  220. CPPUNIT_ASSERT( wxStrcmp( s.Left(5).c_str() , wxT("Hello") ) == 0 );
  221. CPPUNIT_ASSERT( wxStrcmp( s.Right(6).c_str() , wxT("world!") ) == 0 );
  222. CPPUNIT_ASSERT( wxStrcmp( s(3, 5).c_str() , wxT("lo, w") ) == 0 );
  223. CPPUNIT_ASSERT( wxStrcmp( s.Mid(3).c_str() , wxT("lo, world!") ) == 0 );
  224. CPPUNIT_ASSERT( wxStrcmp( s.substr(3, 5).c_str() , wxT("lo, w") ) == 0 );
  225. CPPUNIT_ASSERT( wxStrcmp( s.substr(3).c_str() , wxT("lo, world!") ) == 0 );
  226. #if wxUSE_UNICODE
  227. static const char *germanUTF8 = "Oberfl\303\244che";
  228. wxString strUnicode(wxString::FromUTF8(germanUTF8));
  229. CPPUNIT_ASSERT( strUnicode.Mid(0, 10) == strUnicode );
  230. CPPUNIT_ASSERT( strUnicode.Mid(7, 2) == "ch" );
  231. #endif // wxUSE_UNICODE
  232. wxString rest;
  233. #define TEST_STARTS_WITH(prefix, correct_rest, result) \
  234. CPPUNIT_ASSERT_EQUAL(result, s.StartsWith(prefix, &rest)); \
  235. if ( result ) \
  236. CPPUNIT_ASSERT_EQUAL(correct_rest, rest)
  237. TEST_STARTS_WITH( wxT("Hello"), wxT(", world!"), true );
  238. TEST_STARTS_WITH( wxT("Hello, "), wxT("world!"), true );
  239. TEST_STARTS_WITH( wxT("Hello, world!"), wxT(""), true );
  240. TEST_STARTS_WITH( wxT("Hello, world!!!"), wxT(""), false );
  241. TEST_STARTS_WITH( wxT(""), wxT("Hello, world!"), true );
  242. TEST_STARTS_WITH( wxT("Goodbye"), wxT(""), false );
  243. TEST_STARTS_WITH( wxT("Hi"), wxT(""), false );
  244. #undef TEST_STARTS_WITH
  245. rest = "Hello world";
  246. CPPUNIT_ASSERT( rest.StartsWith("Hello ", &rest) );
  247. CPPUNIT_ASSERT_EQUAL("world", rest);
  248. #define TEST_ENDS_WITH(suffix, correct_rest, result) \
  249. CPPUNIT_ASSERT_EQUAL(result, s.EndsWith(suffix, &rest)); \
  250. if ( result ) \
  251. CPPUNIT_ASSERT_EQUAL(correct_rest, rest)
  252. TEST_ENDS_WITH( wxT(""), wxT("Hello, world!"), true );
  253. TEST_ENDS_WITH( wxT("!"), wxT("Hello, world"), true );
  254. TEST_ENDS_WITH( wxT(", world!"), wxT("Hello"), true );
  255. TEST_ENDS_WITH( wxT("ello, world!"), wxT("H"), true );
  256. TEST_ENDS_WITH( wxT("Hello, world!"), wxT(""), true );
  257. TEST_ENDS_WITH( wxT("very long string"), wxT(""), false );
  258. TEST_ENDS_WITH( wxT("?"), wxT(""), false );
  259. TEST_ENDS_WITH( wxT("Hello, world"), wxT(""), false );
  260. TEST_ENDS_WITH( wxT("Gello, world!"), wxT(""), false );
  261. #undef TEST_ENDS_WITH
  262. }
  263. void StringTestCase::Trim()
  264. {
  265. #define TEST_TRIM( str , dir , result ) \
  266. CPPUNIT_ASSERT( wxString(str).Trim(dir) == result )
  267. TEST_TRIM( wxT(" Test "), true, wxT(" Test") );
  268. TEST_TRIM( wxT(" "), true, wxT("") );
  269. TEST_TRIM( wxT(" "), true, wxT("") );
  270. TEST_TRIM( wxT(""), true, wxT("") );
  271. TEST_TRIM( wxT(" Test "), false, wxT("Test ") );
  272. TEST_TRIM( wxT(" "), false, wxT("") );
  273. TEST_TRIM( wxT(" "), false, wxT("") );
  274. TEST_TRIM( wxT(""), false, wxT("") );
  275. #undef TEST_TRIM
  276. }
  277. void StringTestCase::Find()
  278. {
  279. #define TEST_FIND( str , start , result ) \
  280. CPPUNIT_ASSERT( wxString(str).find(wxT("ell"), start) == result );
  281. TEST_FIND( wxT("Well, hello world"), 0, 1 );
  282. TEST_FIND( wxT("Well, hello world"), 6, 7 );
  283. TEST_FIND( wxT("Well, hello world"), 9, wxString::npos );
  284. #undef TEST_FIND
  285. }
  286. void StringTestCase::Replace()
  287. {
  288. #define TEST_REPLACE( original , pos , len , replacement , result ) \
  289. { \
  290. wxString s = original; \
  291. s.replace( pos , len , replacement ); \
  292. CPPUNIT_ASSERT_EQUAL( result, s ); \
  293. }
  294. TEST_REPLACE( wxT("012-AWORD-XYZ"), 4, 5, wxT("BWORD"), wxT("012-BWORD-XYZ") );
  295. TEST_REPLACE( wxT("increase"), 0, 2, wxT("de"), wxT("decrease") );
  296. TEST_REPLACE( wxT("wxWindow"), 8, 0, wxT("s"), wxT("wxWindows") );
  297. TEST_REPLACE( wxT("foobar"), 3, 0, wxT("-"), wxT("foo-bar") );
  298. TEST_REPLACE( wxT("barfoo"), 0, 6, wxT("foobar"), wxT("foobar") );
  299. #define TEST_NULLCHARREPLACE( o , olen, pos , len , replacement , r, rlen ) \
  300. { \
  301. wxString s(o,olen); \
  302. s.replace( pos , len , replacement ); \
  303. CPPUNIT_ASSERT_EQUAL( wxString(r,rlen), s ); \
  304. }
  305. TEST_NULLCHARREPLACE( wxT("null\0char"), 9, 5, 1, wxT("d"),
  306. wxT("null\0dhar"), 9 );
  307. #define TEST_WXREPLACE( o , olen, olds, news, all, r, rlen ) \
  308. { \
  309. wxString s(o,olen); \
  310. s.Replace( olds, news, all ); \
  311. CPPUNIT_ASSERT_EQUAL( wxString(r,rlen), s ); \
  312. }
  313. TEST_WXREPLACE( wxT("null\0char"), 9, wxT("c"), wxT("de"), true,
  314. wxT("null\0dehar"), 10 );
  315. TEST_WXREPLACE( wxT("null\0dehar"), 10, wxT("de"), wxT("c"), true,
  316. wxT("null\0char"), 9 );
  317. TEST_WXREPLACE( "life", 4, "f", "", false, "lie", 3 );
  318. TEST_WXREPLACE( "life", 4, "f", "", true, "lie", 3 );
  319. TEST_WXREPLACE( "life", 4, "fe", "ve", true, "live", 4 );
  320. TEST_WXREPLACE( "xx", 2, "x", "yy", true, "yyyy", 4 );
  321. TEST_WXREPLACE( "xxx", 3, "xx", "z", true, "zx", 2 );
  322. #undef TEST_WXREPLACE
  323. #undef TEST_NULLCHARREPLACE
  324. #undef TEST_REPLACE
  325. }
  326. void StringTestCase::Match()
  327. {
  328. #define TEST_MATCH( s1 , s2 , result ) \
  329. CPPUNIT_ASSERT( wxString(s1).Matches(s2) == result )
  330. TEST_MATCH( "foobar", "foo*", true );
  331. TEST_MATCH( "foobar", "*oo*", true );
  332. TEST_MATCH( "foobar", "*bar", true );
  333. TEST_MATCH( "foobar", "??????", true );
  334. TEST_MATCH( "foobar", "f??b*", true );
  335. TEST_MATCH( "foobar", "f?b*", false );
  336. TEST_MATCH( "foobar", "*goo*", false );
  337. TEST_MATCH( "foobar", "*foo", false );
  338. TEST_MATCH( "foobarfoo", "*foo", true );
  339. TEST_MATCH( "", "*", true );
  340. TEST_MATCH( "", "?", false );
  341. #undef TEST_MATCH
  342. }
  343. void StringTestCase::CaseChanges()
  344. {
  345. wxString s1(wxT("Hello!"));
  346. wxString s1u(s1);
  347. wxString s1l(s1);
  348. s1u.MakeUpper();
  349. s1l.MakeLower();
  350. CPPUNIT_ASSERT_EQUAL( wxT("HELLO!"), s1u );
  351. CPPUNIT_ASSERT_EQUAL( wxT("hello!"), s1l );
  352. wxString s2u, s2l;
  353. s2u.MakeUpper();
  354. s2l.MakeLower();
  355. CPPUNIT_ASSERT_EQUAL( "", s2u );
  356. CPPUNIT_ASSERT_EQUAL( "", s2l );
  357. wxString s3("good bye");
  358. CPPUNIT_ASSERT_EQUAL( "Good bye", s3.Capitalize() );
  359. s3.MakeCapitalized();
  360. CPPUNIT_ASSERT_EQUAL( "Good bye", s3 );
  361. CPPUNIT_ASSERT_EQUAL( "Abc", wxString("ABC").Capitalize() );
  362. CPPUNIT_ASSERT_EQUAL( "", wxString().Capitalize() );
  363. }
  364. void StringTestCase::Compare()
  365. {
  366. wxString s1 = wxT("AHH");
  367. wxString eq = wxT("AHH");
  368. wxString neq1 = wxT("HAH");
  369. wxString neq2 = wxT("AH");
  370. wxString neq3 = wxT("AHHH");
  371. wxString neq4 = wxT("AhH");
  372. CPPUNIT_ASSERT( s1 == eq );
  373. CPPUNIT_ASSERT( s1 != neq1 );
  374. CPPUNIT_ASSERT( s1 != neq2 );
  375. CPPUNIT_ASSERT( s1 != neq3 );
  376. CPPUNIT_ASSERT( s1 != neq4 );
  377. CPPUNIT_ASSERT( s1 == wxT("AHH") );
  378. CPPUNIT_ASSERT( s1 != wxT("no") );
  379. CPPUNIT_ASSERT( s1 < wxT("AZ") );
  380. CPPUNIT_ASSERT( s1 <= wxT("AZ") );
  381. CPPUNIT_ASSERT( s1 <= wxT("AHH") );
  382. CPPUNIT_ASSERT( s1 > wxT("AA") );
  383. CPPUNIT_ASSERT( s1 >= wxT("AA") );
  384. CPPUNIT_ASSERT( s1 >= wxT("AHH") );
  385. // test comparison with C strings in Unicode build (must work in ANSI as
  386. // well, of course):
  387. CPPUNIT_ASSERT( s1 == "AHH" );
  388. CPPUNIT_ASSERT( s1 != "no" );
  389. CPPUNIT_ASSERT( s1 < "AZ" );
  390. CPPUNIT_ASSERT( s1 <= "AZ" );
  391. CPPUNIT_ASSERT( s1 <= "AHH" );
  392. CPPUNIT_ASSERT( s1 > "AA" );
  393. CPPUNIT_ASSERT( s1 >= "AA" );
  394. CPPUNIT_ASSERT( s1 >= "AHH" );
  395. // wxString _s1 = wxT("A\0HH");
  396. // wxString _eq = wxT("A\0HH");
  397. // wxString _neq1 = wxT("H\0AH");
  398. // wxString _neq2 = wxT("A\0H");
  399. // wxString _neq3 = wxT("A\0HHH");
  400. // wxString _neq4 = wxT("A\0hH");
  401. s1.insert(1,1,'\0');
  402. eq.insert(1,1,'\0');
  403. neq1.insert(1,1,'\0');
  404. neq2.insert(1,1,'\0');
  405. neq3.insert(1,1,'\0');
  406. neq4.insert(1,1,'\0');
  407. CPPUNIT_ASSERT( s1 == eq );
  408. CPPUNIT_ASSERT( s1 != neq1 );
  409. CPPUNIT_ASSERT( s1 != neq2 );
  410. CPPUNIT_ASSERT( s1 != neq3 );
  411. CPPUNIT_ASSERT( s1 != neq4 );
  412. CPPUNIT_ASSERT( wxString("\n").Cmp(" ") < 0 );
  413. CPPUNIT_ASSERT( wxString("'").Cmp("!") > 0 );
  414. CPPUNIT_ASSERT( wxString("!").Cmp("z") < 0 );
  415. }
  416. void StringTestCase::CompareNoCase()
  417. {
  418. wxString s1 = wxT("AHH");
  419. wxString eq = wxT("AHH");
  420. wxString eq2 = wxT("AhH");
  421. wxString eq3 = wxT("ahh");
  422. wxString neq = wxT("HAH");
  423. wxString neq2 = wxT("AH");
  424. wxString neq3 = wxT("AHHH");
  425. #define CPPUNIT_CNCEQ_ASSERT(s1, s2) CPPUNIT_ASSERT( s1.CmpNoCase(s2) == 0)
  426. #define CPPUNIT_CNCNEQ_ASSERT(s1, s2) CPPUNIT_ASSERT( s1.CmpNoCase(s2) != 0)
  427. CPPUNIT_CNCEQ_ASSERT( s1, eq );
  428. CPPUNIT_CNCEQ_ASSERT( s1, eq2 );
  429. CPPUNIT_CNCEQ_ASSERT( s1, eq3 );
  430. CPPUNIT_CNCNEQ_ASSERT( s1, neq );
  431. CPPUNIT_CNCNEQ_ASSERT( s1, neq2 );
  432. CPPUNIT_CNCNEQ_ASSERT( s1, neq3 );
  433. // wxString _s1 = wxT("A\0HH");
  434. // wxString _eq = wxT("A\0HH");
  435. // wxString _eq2 = wxT("A\0hH");
  436. // wxString _eq3 = wxT("a\0hh");
  437. // wxString _neq = wxT("H\0AH");
  438. // wxString _neq2 = wxT("A\0H");
  439. // wxString _neq3 = wxT("A\0HHH");
  440. s1.insert(1,1,'\0');
  441. eq.insert(1,1,'\0');
  442. eq2.insert(1,1,'\0');
  443. eq3.insert(1,1,'\0');
  444. neq.insert(1,1,'\0');
  445. neq2.insert(1,1,'\0');
  446. neq3.insert(1,1,'\0');
  447. CPPUNIT_CNCEQ_ASSERT( s1, eq );
  448. CPPUNIT_CNCEQ_ASSERT( s1, eq2 );
  449. CPPUNIT_CNCEQ_ASSERT( s1, eq3 );
  450. CPPUNIT_CNCNEQ_ASSERT( s1, neq );
  451. CPPUNIT_CNCNEQ_ASSERT( s1, neq2 );
  452. CPPUNIT_CNCNEQ_ASSERT( s1, neq3 );
  453. CPPUNIT_ASSERT( wxString("\n").CmpNoCase(" ") < 0 );
  454. CPPUNIT_ASSERT( wxString("'").CmpNoCase("!") > 0);
  455. CPPUNIT_ASSERT( wxString("!").Cmp("Z") < 0 );
  456. }
  457. void StringTestCase::Contains()
  458. {
  459. static const struct ContainsData
  460. {
  461. const wxChar *hay;
  462. const wxChar *needle;
  463. bool contains;
  464. } containsData[] =
  465. {
  466. { wxT(""), wxT(""), true },
  467. { wxT(""), wxT("foo"), false },
  468. { wxT("foo"), wxT(""), true },
  469. { wxT("foo"), wxT("f"), true },
  470. { wxT("foo"), wxT("o"), true },
  471. { wxT("foo"), wxT("oo"), true },
  472. { wxT("foo"), wxT("ooo"), false },
  473. { wxT("foo"), wxT("oooo"), false },
  474. { wxT("foo"), wxT("fooo"), false },
  475. };
  476. for ( size_t n = 0; n < WXSIZEOF(containsData); n++ )
  477. {
  478. const ContainsData& cd = containsData[n];
  479. CPPUNIT_ASSERT_EQUAL( cd.contains, wxString(cd.hay).Contains(cd.needle) );
  480. }
  481. }
  482. // flags used in ToLongData.flags
  483. enum
  484. {
  485. Number_Ok = 0,
  486. Number_Invalid = 1,
  487. Number_Unsigned = 2, // if not specified, works for signed conversion
  488. Number_Signed = 4, // if not specified, works for unsigned
  489. Number_LongLong = 8, // only for long long tests
  490. Number_Long = 16 // only for long tests
  491. };
  492. static const struct ToLongData
  493. {
  494. const wxChar *str;
  495. #ifdef wxLongLong_t
  496. wxLongLong_t value;
  497. #else
  498. long value;
  499. #endif // wxLongLong_t
  500. int flags;
  501. int base;
  502. long LValue() const { return value; }
  503. unsigned long ULValue() const { return value; }
  504. #ifdef wxLongLong_t
  505. wxLongLong_t LLValue() const { return value; }
  506. wxULongLong_t ULLValue() const { return (wxULongLong_t)value; }
  507. #endif // wxLongLong_t
  508. bool IsOk() const { return !(flags & Number_Invalid); }
  509. } longData[] =
  510. {
  511. { wxT("1"), 1, Number_Ok },
  512. { wxT("0"), 0, Number_Ok },
  513. { wxT("a"), 0, Number_Invalid },
  514. { wxT("12345"), 12345, Number_Ok },
  515. { wxT("--1"), 0, Number_Invalid },
  516. { wxT("-1"), -1, Number_Signed | Number_Long },
  517. // this is surprising but consistent with strtoul() behaviour
  518. { wxT("-1"), ULONG_MAX, Number_Unsigned | Number_Long },
  519. // this must overflow, even with 64 bit long
  520. { wxT("922337203685477580711"), 0, Number_Invalid },
  521. #ifdef wxLongLong_t
  522. { wxT("2147483648"), wxLL(2147483648), Number_LongLong },
  523. { wxT("-2147483648"), wxLL(-2147483648), Number_LongLong | Number_Signed },
  524. { wxT("9223372036854775808"), wxULL(9223372036854775808), Number_LongLong |
  525. Number_Unsigned },
  526. #endif // wxLongLong_t
  527. // Base tests.
  528. { wxT("010"), 10, Number_Ok, 10 },
  529. { wxT("010"), 8, Number_Ok, 0 },
  530. { wxT("010"), 8, Number_Ok, 8 },
  531. { wxT("010"), 16, Number_Ok, 16 },
  532. { wxT("0010"), 10, Number_Ok, 10 },
  533. { wxT("0010"), 8, Number_Ok, 0 },
  534. { wxT("0010"), 8, Number_Ok, 8 },
  535. { wxT("0010"), 16, Number_Ok, 16 },
  536. { wxT("0x11"), 0, Number_Invalid, 10 },
  537. { wxT("0x11"), 17, Number_Ok, 0 },
  538. { wxT("0x11"), 0, Number_Invalid, 8 },
  539. { wxT("0x11"), 17, Number_Ok, 16 },
  540. };
  541. void StringTestCase::ToLong()
  542. {
  543. long l;
  544. for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
  545. {
  546. const ToLongData& ld = longData[n];
  547. if ( ld.flags & (Number_LongLong | Number_Unsigned) )
  548. continue;
  549. // NOTE: unless you're using some exotic locale, ToCLong and ToLong
  550. // should behave the same for our test data set:
  551. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  552. wxString(ld.str).ToCLong(&l, ld.base) );
  553. if ( ld.IsOk() )
  554. CPPUNIT_ASSERT_EQUAL( ld.LValue(), l );
  555. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  556. wxString(ld.str).ToLong(&l, ld.base) );
  557. if ( ld.IsOk() )
  558. CPPUNIT_ASSERT_EQUAL( ld.LValue(), l );
  559. }
  560. // special case: check that the output is not modified if the parsing
  561. // failed completely
  562. l = 17;
  563. CPPUNIT_ASSERT( !wxString("foo").ToLong(&l) );
  564. CPPUNIT_ASSERT_EQUAL( 17, l );
  565. // also check that it is modified if we did parse something successfully in
  566. // the beginning of the string
  567. CPPUNIT_ASSERT( !wxString("9 cats").ToLong(&l) );
  568. CPPUNIT_ASSERT_EQUAL( 9, l );
  569. }
  570. void StringTestCase::ToULong()
  571. {
  572. unsigned long ul;
  573. for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
  574. {
  575. const ToLongData& ld = longData[n];
  576. if ( ld.flags & (Number_LongLong | Number_Signed) )
  577. continue;
  578. // NOTE: unless you're using some exotic locale, ToCLong and ToLong
  579. // should behave the same for our test data set:
  580. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  581. wxString(ld.str).ToCULong(&ul, ld.base) );
  582. if ( ld.IsOk() )
  583. CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul );
  584. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  585. wxString(ld.str).ToULong(&ul, ld.base) );
  586. if ( ld.IsOk() )
  587. CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul );
  588. }
  589. }
  590. #ifdef wxLongLong_t
  591. void StringTestCase::ToLongLong()
  592. {
  593. wxLongLong_t l;
  594. for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
  595. {
  596. const ToLongData& ld = longData[n];
  597. if ( ld.flags & (Number_Long | Number_Unsigned) )
  598. continue;
  599. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  600. wxString(ld.str).ToLongLong(&l, ld.base) );
  601. if ( ld.IsOk() )
  602. CPPUNIT_ASSERT_EQUAL( ld.LLValue(), l );
  603. }
  604. }
  605. void StringTestCase::ToULongLong()
  606. {
  607. wxULongLong_t ul;
  608. for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
  609. {
  610. const ToLongData& ld = longData[n];
  611. if ( ld.flags & (Number_Long | Number_Signed) )
  612. continue;
  613. CPPUNIT_ASSERT_EQUAL( ld.IsOk(),
  614. wxString(ld.str).ToULongLong(&ul, ld.base) );
  615. if ( ld.IsOk() )
  616. CPPUNIT_ASSERT_EQUAL( ld.ULLValue(), ul );
  617. }
  618. }
  619. #endif // wxLongLong_t
  620. void StringTestCase::ToDouble()
  621. {
  622. double d;
  623. static const struct ToDoubleData
  624. {
  625. const wxChar *str;
  626. double value;
  627. bool ok;
  628. } doubleData[] =
  629. {
  630. { wxT("1"), 1, true },
  631. { wxT("1.23"), 1.23, true },
  632. { wxT(".1"), .1, true },
  633. { wxT("1."), 1, true },
  634. { wxT("1.."), 0, false },
  635. { wxT("0"), 0, true },
  636. { wxT("a"), 0, false },
  637. { wxT("12345"), 12345, true },
  638. { wxT("-1"), -1, true },
  639. { wxT("--1"), 0, false },
  640. { wxT("-3E-5"), -3E-5, true },
  641. { wxT("-3E-abcde5"), 0, false },
  642. };
  643. // test ToCDouble() first:
  644. size_t n;
  645. for ( n = 0; n < WXSIZEOF(doubleData); n++ )
  646. {
  647. const ToDoubleData& ld = doubleData[n];
  648. CPPUNIT_ASSERT_EQUAL( ld.ok, wxString(ld.str).ToCDouble(&d) );
  649. if ( ld.ok )
  650. CPPUNIT_ASSERT_EQUAL( ld.value, d );
  651. }
  652. // test ToDouble() now:
  653. // NOTE: for the test to be reliable, we need to set the locale explicitly
  654. // so that we know the decimal point character to use
  655. if (!wxLocale::IsAvailable(wxLANGUAGE_FRENCH))
  656. return; // you should have french support installed to continue this test!
  657. wxLocale locale;
  658. // don't load default catalog, it may be unavailable:
  659. CPPUNIT_ASSERT( locale.Init(wxLANGUAGE_FRENCH, wxLOCALE_DONT_LOAD_DEFAULT) );
  660. static const struct ToDoubleData doubleData2[] =
  661. {
  662. { wxT("1"), 1, true },
  663. { wxT("1,23"), 1.23, true },
  664. { wxT(",1"), .1, true },
  665. { wxT("1,"), 1, true },
  666. { wxT("1,,"), 0, false },
  667. { wxT("0"), 0, true },
  668. { wxT("a"), 0, false },
  669. { wxT("12345"), 12345, true },
  670. { wxT("-1"), -1, true },
  671. { wxT("--1"), 0, false },
  672. { wxT("-3E-5"), -3E-5, true },
  673. { wxT("-3E-abcde5"), 0, false },
  674. };
  675. for ( n = 0; n < WXSIZEOF(doubleData2); n++ )
  676. {
  677. const ToDoubleData& ld = doubleData2[n];
  678. CPPUNIT_ASSERT_EQUAL( ld.ok, wxString(ld.str).ToDouble(&d) );
  679. if ( ld.ok )
  680. CPPUNIT_ASSERT_EQUAL( ld.value, d );
  681. }
  682. }
  683. void StringTestCase::FromDouble()
  684. {
  685. static const struct FromDoubleTestData
  686. {
  687. double value;
  688. int prec;
  689. const char *str;
  690. } testData[] =
  691. {
  692. { 1.23, -1, "1.23" },
  693. // NB: there are no standards about the minimum exponent width
  694. // and newer MSVC versions use 3 digits as minimum exponent
  695. // width while GNU libc uses 2 digits as minimum width...
  696. #ifdef wxUSING_VC_CRT_IO
  697. { -3e-10, -1, "-3e-010" },
  698. #else
  699. { -3e-10, -1, "-3e-10" },
  700. #endif
  701. { -0.45678, -1, "-0.45678" },
  702. { 1.2345678, 0, "1" },
  703. { 1.2345678, 1, "1.2" },
  704. { 1.2345678, 2, "1.23" },
  705. { 1.2345678, 3, "1.235" },
  706. };
  707. for ( unsigned n = 0; n < WXSIZEOF(testData); n++ )
  708. {
  709. const FromDoubleTestData& td = testData[n];
  710. CPPUNIT_ASSERT_EQUAL( td.str, wxString::FromCDouble(td.value, td.prec) );
  711. }
  712. if ( !wxLocale::IsAvailable(wxLANGUAGE_FRENCH) )
  713. return;
  714. wxLocale locale;
  715. CPPUNIT_ASSERT( locale.Init(wxLANGUAGE_FRENCH, wxLOCALE_DONT_LOAD_DEFAULT) );
  716. for ( unsigned m = 0; m < WXSIZEOF(testData); m++ )
  717. {
  718. const FromDoubleTestData& td = testData[m];
  719. wxString str(td.str);
  720. str.Replace(".", ",");
  721. CPPUNIT_ASSERT_EQUAL( str, wxString::FromDouble(td.value, td.prec) );
  722. }
  723. }
  724. void StringTestCase::StringBuf()
  725. {
  726. // check that buffer can be used to write into the string
  727. wxString s;
  728. wxStrcpy(wxStringBuffer(s, 10), wxT("foo"));
  729. CPPUNIT_ASSERT_EQUAL(3, s.length());
  730. CPPUNIT_ASSERT(wxT('f') == s[0u]);
  731. CPPUNIT_ASSERT(wxT('o') == s[1]);
  732. CPPUNIT_ASSERT(wxT('o') == s[2]);
  733. {
  734. // also check that the buffer initially contains the original string
  735. // contents
  736. wxStringBuffer buf(s, 10);
  737. CPPUNIT_ASSERT_EQUAL( wxT('f'), buf[0] );
  738. CPPUNIT_ASSERT_EQUAL( wxT('o'), buf[1] );
  739. CPPUNIT_ASSERT_EQUAL( wxT('o'), buf[2] );
  740. CPPUNIT_ASSERT_EQUAL( wxT('\0'), buf[3] );
  741. }
  742. {
  743. wxStringBufferLength buf(s, 10);
  744. CPPUNIT_ASSERT_EQUAL( wxT('f'), buf[0] );
  745. CPPUNIT_ASSERT_EQUAL( wxT('o'), buf[1] );
  746. CPPUNIT_ASSERT_EQUAL( wxT('o'), buf[2] );
  747. CPPUNIT_ASSERT_EQUAL( wxT('\0'), buf[3] );
  748. // and check that it can be used to write only the specified number of
  749. // characters to the string
  750. wxStrcpy(buf, wxT("barrbaz"));
  751. buf.SetLength(4);
  752. }
  753. CPPUNIT_ASSERT_EQUAL(4, s.length());
  754. CPPUNIT_ASSERT(wxT('b') == s[0u]);
  755. CPPUNIT_ASSERT(wxT('a') == s[1]);
  756. CPPUNIT_ASSERT(wxT('r') == s[2]);
  757. CPPUNIT_ASSERT(wxT('r') == s[3]);
  758. // check that creating buffer of length smaller than string works, i.e. at
  759. // least doesn't crash (it would if we naively copied the entire original
  760. // string contents in the buffer)
  761. *wxStringBuffer(s, 1) = '!';
  762. }
  763. void StringTestCase::UTF8Buf()
  764. {
  765. #if wxUSE_UNICODE
  766. // "czech" in Czech ("cestina"):
  767. static const char *textUTF8 = "\304\215e\305\241tina";
  768. static const wchar_t textUTF16[] = {0x10D, 0x65, 0x161, 0x74, 0x69, 0x6E, 0x61, 0};
  769. wxString s;
  770. wxStrcpy(wxUTF8StringBuffer(s, 9), textUTF8);
  771. CPPUNIT_ASSERT(s == textUTF16);
  772. {
  773. wxUTF8StringBufferLength buf(s, 20);
  774. wxStrcpy(buf, textUTF8);
  775. buf.SetLength(5);
  776. }
  777. CPPUNIT_ASSERT(s == wxString(textUTF16, 0, 3));
  778. #endif // wxUSE_UNICODE
  779. }
  780. void StringTestCase::CStrDataTernaryOperator()
  781. {
  782. DoCStrDataTernaryOperator(true);
  783. DoCStrDataTernaryOperator(false);
  784. }
  785. template<typename T> bool CheckStr(const wxString& expected, T s)
  786. {
  787. return expected == wxString(s);
  788. }
  789. void StringTestCase::DoCStrDataTernaryOperator(bool cond)
  790. {
  791. // test compilation of wxCStrData when used with operator?: (the asserts
  792. // are not very important, we're testing if the code compiles at all):
  793. wxString s("foo");
  794. const wchar_t *wcStr = L"foo";
  795. CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : wcStr)) );
  796. CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : L"foo")) );
  797. CPPUNIT_ASSERT( CheckStr(s, (cond ? wcStr : s.c_str())) );
  798. CPPUNIT_ASSERT( CheckStr(s, (cond ? L"foo" : s.c_str())) );
  799. const char *mbStr = "foo";
  800. CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : mbStr)) );
  801. CPPUNIT_ASSERT( CheckStr(s, (cond ? s.c_str() : "foo")) );
  802. CPPUNIT_ASSERT( CheckStr(s, (cond ? mbStr : s.c_str())) );
  803. CPPUNIT_ASSERT( CheckStr(s, (cond ? "foo" : s.c_str())) );
  804. wxString empty("");
  805. CPPUNIT_ASSERT( CheckStr(empty, (cond ? empty.c_str() : wxEmptyString)) );
  806. CPPUNIT_ASSERT( CheckStr(empty, (cond ? wxEmptyString : empty.c_str())) );
  807. }
  808. void StringTestCase::CStrDataOperators()
  809. {
  810. wxString s("hello");
  811. CPPUNIT_ASSERT( s.c_str()[0] == 'h' );
  812. CPPUNIT_ASSERT( s.c_str()[1] == 'e' );
  813. // IMPORTANT: at least with the CRT coming with MSVC++ 2008 trying to access
  814. // the final character results in an assert failure (with debug CRT)
  815. //CPPUNIT_ASSERT( s.c_str()[5] == '\0' );
  816. CPPUNIT_ASSERT( *s.c_str() == 'h' );
  817. CPPUNIT_ASSERT( *(s.c_str() + 2) == 'l' );
  818. //CPPUNIT_ASSERT( *(s.c_str() + 5) == '\0' );
  819. }
  820. bool CheckStrChar(const wxString& expected, char *s)
  821. { return CheckStr(expected, s); }
  822. bool CheckStrWChar(const wxString& expected, wchar_t *s)
  823. { return CheckStr(expected, s); }
  824. bool CheckStrConstChar(const wxString& expected, const char *s)
  825. { return CheckStr(expected, s); }
  826. bool CheckStrConstWChar(const wxString& expected, const wchar_t *s)
  827. { return CheckStr(expected, s); }
  828. void StringTestCase::CStrDataImplicitConversion()
  829. {
  830. wxString s("foo");
  831. CPPUNIT_ASSERT( CheckStrConstWChar(s, s.c_str()) );
  832. CPPUNIT_ASSERT( CheckStrConstChar(s, s.c_str()) );
  833. // implicit conversion of wxString is not available in STL build
  834. #if !wxUSE_STL
  835. CPPUNIT_ASSERT( CheckStrConstWChar(s, s) );
  836. CPPUNIT_ASSERT( CheckStrConstChar(s, s) );
  837. #endif
  838. }
  839. void StringTestCase::ExplicitConversion()
  840. {
  841. wxString s("foo");
  842. CPPUNIT_ASSERT( CheckStr(s, s.mb_str()) );
  843. CPPUNIT_ASSERT( CheckStrConstChar(s, s.mb_str()) );
  844. CPPUNIT_ASSERT( CheckStrChar(s, s.char_str()) );
  845. CPPUNIT_ASSERT( CheckStr(s, s.wc_str()) );
  846. CPPUNIT_ASSERT( CheckStrConstWChar(s, s.wc_str()) );
  847. CPPUNIT_ASSERT( CheckStrWChar(s, s.wchar_str()) );
  848. }
  849. void StringTestCase::IndexedAccess()
  850. {
  851. wxString s("bar");
  852. CPPUNIT_ASSERT_EQUAL( 'r', (char)s[2] );
  853. // this tests for a possible bug in UTF-8 based wxString implementation:
  854. // the 3rd character of the underlying byte string is going to change, but
  855. // the 3rd character of wxString should remain the same
  856. s[0] = L'\xe9';
  857. CPPUNIT_ASSERT_EQUAL( 'r', (char)s[2] );
  858. }
  859. void StringTestCase::BeforeAndAfter()
  860. {
  861. // Construct a string with 2 equal signs in it by concatenating its three
  862. // parts: before the first "=", in between the two "="s and after the last
  863. // one. This allows to avoid duplicating the string contents (which has to
  864. // be different for Unicode and ANSI builds) in the tests below.
  865. #if wxUSE_UNICODE
  866. #define FIRST_PART L"letter"
  867. #define MIDDLE_PART L"\xe9;\xe7a"
  868. #define LAST_PART L"l\xe0"
  869. #else // !wxUSE_UNICODE
  870. #define FIRST_PART "letter"
  871. #define MIDDLE_PART "e;ca"
  872. #define LAST_PART "la"
  873. #endif // wxUSE_UNICODE/!wxUSE_UNICODE
  874. const wxString s(FIRST_PART wxT("=") MIDDLE_PART wxT("=") LAST_PART);
  875. wxString r;
  876. CPPUNIT_ASSERT_EQUAL( FIRST_PART, s.BeforeFirst('=', &r) );
  877. CPPUNIT_ASSERT_EQUAL( MIDDLE_PART wxT("=") LAST_PART, r );
  878. CPPUNIT_ASSERT_EQUAL( s, s.BeforeFirst('!', &r) );
  879. CPPUNIT_ASSERT_EQUAL( "", r );
  880. CPPUNIT_ASSERT_EQUAL( FIRST_PART wxT("=") MIDDLE_PART, s.BeforeLast('=', &r) );
  881. CPPUNIT_ASSERT_EQUAL( LAST_PART, r );
  882. CPPUNIT_ASSERT_EQUAL( "", s.BeforeLast('!', &r) );
  883. CPPUNIT_ASSERT_EQUAL( s, r );
  884. CPPUNIT_ASSERT_EQUAL( MIDDLE_PART wxT("=") LAST_PART, s.AfterFirst('=') );
  885. CPPUNIT_ASSERT_EQUAL( "", s.AfterFirst('!') );
  886. CPPUNIT_ASSERT_EQUAL( LAST_PART, s.AfterLast('=') );
  887. CPPUNIT_ASSERT_EQUAL( s, s.AfterLast('!') );
  888. #undef LAST_PART
  889. #undef MIDDLE_PART
  890. #undef FIRST_PART
  891. }
  892. void StringTestCase::ScopedBuffers()
  893. {
  894. // wxString relies on efficient buffers, verify they work as they should
  895. const char *literal = "Hello World!";
  896. // non-owned buffer points to the string passed to it
  897. wxScopedCharBuffer sbuf = wxScopedCharBuffer::CreateNonOwned(literal);
  898. CPPUNIT_ASSERT( sbuf.data() == literal );
  899. // a copy of scoped non-owned buffer still points to the same string
  900. wxScopedCharBuffer sbuf2(sbuf);
  901. CPPUNIT_ASSERT( sbuf.data() == sbuf2.data() );
  902. // but assigning it to wxCharBuffer makes a full copy
  903. wxCharBuffer buf(sbuf);
  904. CPPUNIT_ASSERT( buf.data() != literal );
  905. CPPUNIT_ASSERT_EQUAL( literal, buf.data() );
  906. wxCharBuffer buf2 = sbuf;
  907. CPPUNIT_ASSERT( buf2.data() != literal );
  908. CPPUNIT_ASSERT_EQUAL( literal, buf.data() );
  909. // Check that extending the buffer keeps it NUL-terminated.
  910. size_t len = 10;
  911. wxCharBuffer buf3(len);
  912. CPPUNIT_ASSERT_EQUAL('\0', buf3.data()[len]);
  913. wxCharBuffer buf4;
  914. buf4.extend(len);
  915. CPPUNIT_ASSERT_EQUAL('\0', buf4.data()[len]);
  916. wxCharBuffer buf5(5);
  917. buf5.extend(len);
  918. CPPUNIT_ASSERT_EQUAL('\0', buf5.data()[len]);
  919. }