@@ -678,3 +678,344 @@ TEST_F (StringTests, Loops)
678678 for (auto c : str)
679679 EXPECT_EQ (c, parts[index++]);
680680}
681+
682+ TEST_F (StringTests, LineManipulation)
683+ {
684+ String multiline (" line1\n line2\n line3\n\n line4" );
685+
686+ // Test indentLines
687+ String indented = multiline.indentLines (" " );
688+ EXPECT_EQ (indented, String (" line1\n line2\n line3\n\n line4" ));
689+
690+ String indentedWithBlanks = multiline.indentLines (" >>" , true );
691+ EXPECT_EQ (indentedWithBlanks, String (" >>line1\n >>line2\n >> line3\n >>\n >>line4" ));
692+
693+ // Test dedentLines
694+ String indentedText (" line1\n line2\n line3\n line4" );
695+ String dedented = indentedText.dedentLines ();
696+ EXPECT_EQ (dedented, String (" line1\n line2\n line3\n line4" ));
697+
698+ // Test dedentLines with mixed indentation
699+ String mixedIndent (" \t line1\n \t line2\n \t line3" );
700+ String dedentedMixed = mixedIndent.dedentLines ();
701+ EXPECT_EQ (dedentedMixed, String (" line1\n line2\n line3" ));
702+ }
703+
704+ TEST_F (StringTests, PaddingMethods)
705+ {
706+ String short_str (" abc" );
707+
708+ // Test paddedLeft
709+ EXPECT_EQ (short_str.paddedLeft (' ' , 10 ), String (" abc" ));
710+ EXPECT_EQ (short_str.paddedLeft (' *' , 5 ), String (" **abc" ));
711+ EXPECT_EQ (short_str.paddedLeft (' -' , 3 ), String (" abc" )); // No padding needed
712+ EXPECT_EQ (short_str.paddedLeft (' 0' , 1 ), String (" abc" )); // Shorter than minimum
713+
714+ // Test paddedRight
715+ EXPECT_EQ (short_str.paddedRight (' ' , 10 ), String (" abc " ));
716+ EXPECT_EQ (short_str.paddedRight (' *' , 5 ), String (" abc**" ));
717+ EXPECT_EQ (short_str.paddedRight (' -' , 3 ), String (" abc" )); // No padding needed
718+ EXPECT_EQ (short_str.paddedRight (' 0' , 1 ), String (" abc" )); // Shorter than minimum
719+ }
720+
721+ TEST_F (StringTests, CharacterTrimming)
722+ {
723+ String test_str (" ...Hello World!!!" );
724+
725+ // Test trimCharactersAtStart
726+ EXPECT_EQ (test_str.trimCharactersAtStart (" ." ), String (" Hello World!!!" ));
727+ EXPECT_EQ (test_str.trimCharactersAtStart (" .*" ), String (" Hello World!!!" ));
728+ EXPECT_EQ (String (" \t text" ).trimCharactersAtStart (" \t " ), String (" text" ));
729+
730+ // Test trimCharactersAtEnd
731+ EXPECT_EQ (test_str.trimCharactersAtEnd (" !" ), String (" ...Hello World" ));
732+ EXPECT_EQ (test_str.trimCharactersAtEnd (" !." ), String (" ...Hello World" ));
733+ EXPECT_EQ (String (" text \t " ).trimCharactersAtEnd (" \t " ), String (" text" ));
734+
735+ // Test with empty string
736+ EXPECT_EQ (String ().trimCharactersAtStart (" abc" ), String ());
737+ EXPECT_EQ (String ().trimCharactersAtEnd (" abc" ), String ());
738+ }
739+
740+ TEST_F (StringTests, SectionReplacement)
741+ {
742+ String base (" Hello World" );
743+
744+ // Test replaceSection
745+ EXPECT_EQ (base.replaceSection (0 , 5 , " Hi" ), String (" Hi World" ));
746+ EXPECT_EQ (base.replaceSection (6 , 5 , " Universe" ), String (" Hello Universe" ));
747+ EXPECT_EQ (base.replaceSection (5 , 1 , " " ), String (" HelloWorld" ));
748+ EXPECT_EQ (base.replaceSection (0 , 0 , " Well, " ), String (" Well, Hello World" ));
749+
750+ // Test replaceFirstOccurrenceOf
751+ String repeated (" abc abc abc" );
752+ EXPECT_EQ (repeated.replaceFirstOccurrenceOf (" abc" , " xyz" ), String (" xyz abc abc" ));
753+ EXPECT_EQ (repeated.replaceFirstOccurrenceOf (" abc" , " xyz" , true ), String (" xyz abc abc" ));
754+ EXPECT_EQ (repeated.replaceFirstOccurrenceOf (" ABC" , " xyz" , true ), String (" xyz abc abc" ));
755+ EXPECT_EQ (repeated.replaceFirstOccurrenceOf (" ABC" , " xyz" , false ), String (" abc abc abc" ));
756+ EXPECT_EQ (repeated.replaceFirstOccurrenceOf (" def" , " xyz" ), String (" abc abc abc" ));
757+ }
758+
759+ TEST_F (StringTests, StringReversing)
760+ {
761+ // Test reversed with basic ASCII strings
762+ EXPECT_EQ (String (" hello" ).reversed (), String (" olleh" ));
763+ EXPECT_EQ (String (" a" ).reversed (), String (" a" ));
764+ EXPECT_EQ (String ().reversed (), String ());
765+ EXPECT_EQ (String (" 12345" ).reversed (), String (" 54321" ));
766+
767+ // Test with Unicode characters - this is the critical test for UTF-8 handling
768+ String unicode_str (L" café" );
769+ String reversed_unicode = unicode_str.reversed ();
770+ EXPECT_EQ (reversed_unicode, String (L" éfac" )); // Should correctly reverse Unicode characters
771+
772+ // Test with more complex Unicode strings
773+ String unicode_complex (CharPointer_UTF8 (" Hello, 世界!" ));
774+ String reversed_complex = unicode_complex.reversed ();
775+ EXPECT_EQ (reversed_complex, String (CharPointer_UTF8 (" !界世 ,olleH" )));
776+
777+ // Test with emojis and other complex Unicode
778+ String emoji_str (CharPointer_UTF8 (" 🌟⭐" ));
779+ String reversed_emoji = emoji_str.reversed ();
780+ EXPECT_EQ (reversed_emoji, String (CharPointer_UTF8 (" ⭐🌟" )));
781+
782+ // Test reversibility (reversing twice should give original)
783+ String original (CharPointer_UTF8 (" Test string with UTF-8: café" ));
784+ String double_reversed = original.reversed ().reversed ();
785+ EXPECT_EQ (double_reversed, original);
786+
787+ // Test with mixed ASCII and Unicode
788+ String mixed (CharPointer_UTF8 (" abc世界def" ));
789+ String reversed_mixed = mixed.reversed ();
790+ EXPECT_EQ (reversed_mixed, String (CharPointer_UTF8 (" fed界世cba" )));
791+ }
792+
793+ TEST_F (StringTests, RepeatedString)
794+ {
795+ // Test repeatedString
796+ EXPECT_EQ (String::repeatedString (" abc" , 3 ), String (" abcabcabc" ));
797+ EXPECT_EQ (String::repeatedString (" x" , 5 ), String (" xxxxx" ));
798+ EXPECT_EQ (String::repeatedString (" hello" , 0 ), String ());
799+ EXPECT_EQ (String::repeatedString (" " , 10 ), String ());
800+ EXPECT_EQ (String::repeatedString (" test" , 1 ), String (" test" ));
801+ }
802+
803+ TEST_F (StringTests, BufferCopyMethods)
804+ {
805+ String test_str (L" Hello, 世界!" );
806+
807+ // Test copyToUTF8
808+ char utf8_buffer[100 ];
809+ size_t utf8_bytes = test_str.copyToUTF8 (utf8_buffer, sizeof (utf8_buffer));
810+ EXPECT_GT (utf8_bytes, 0 );
811+ EXPECT_EQ (String::fromUTF8 (utf8_buffer), test_str);
812+
813+ // Test getNumBytesAsUTF8
814+ size_t required_bytes = test_str.getNumBytesAsUTF8 ();
815+ EXPECT_GT (required_bytes, test_str.length ()); // Should be more due to unicode chars
816+
817+ // Test copyToUTF16
818+ CharPointer_UTF16::CharType utf16_buffer[100 ];
819+ size_t utf16_bytes = test_str.copyToUTF16 (utf16_buffer, sizeof (utf16_buffer));
820+ EXPECT_GT (utf16_bytes, 0 );
821+
822+ // Test copyToUTF32
823+ CharPointer_UTF32::CharType utf32_buffer[100 ];
824+ size_t utf32_bytes = test_str.copyToUTF32 (utf32_buffer, sizeof (utf32_buffer));
825+ EXPECT_GT (utf32_bytes, 0 );
826+
827+ // Test with null buffer (should return required size)
828+ size_t utf8_required = test_str.copyToUTF8 (nullptr , 0 );
829+ EXPECT_GT (utf8_required, 0 );
830+ }
831+
832+ TEST_F (StringTests, PreallocationAndReferenceCounting)
833+ {
834+ String str1 (" test" );
835+ String str2 = str1; // This should share the same data
836+
837+ // Test getReferenceCount
838+ EXPECT_EQ (str1.getReferenceCount (), str2.getReferenceCount ());
839+ EXPECT_GE (str1.getReferenceCount (), 2 );
840+
841+ // Test preallocateBytes
842+ String growing_str;
843+ growing_str.preallocateBytes (1000 );
844+ // After preallocation, adding strings should be more efficient
845+ for (int i = 0 ; i < 10 ; ++i)
846+ growing_str += " some text " ;
847+ EXPECT_GT (growing_str.length (), 0 );
848+ }
849+
850+ TEST_F (StringTests, FormattedStrings)
851+ {
852+ // Test formatted (basic cases)
853+ String formatted_str = String::formatted (" Hello %s" , " World" );
854+ EXPECT_TRUE (formatted_str.contains (" Hello" ));
855+ EXPECT_TRUE (formatted_str.contains (" World" ));
856+
857+ String formatted_int = String::formatted (" Number: %d" , 42 );
858+ EXPECT_TRUE (formatted_int.contains (" Number" ));
859+ EXPECT_TRUE (formatted_int.contains (" 42" ));
860+
861+ String formatted_float = String::formatted (" Value: %.2f" , 3.14159 );
862+ EXPECT_TRUE (formatted_float.contains (" Value" ));
863+ EXPECT_TRUE (formatted_float.contains (" 3.14" ));
864+ }
865+
866+ TEST_F (StringTests, StringCreationFromData)
867+ {
868+ // Test createStringFromData
869+ const char * ascii_data = " Hello World" ;
870+ String from_ascii = String::createStringFromData (ascii_data, (int ) strlen (ascii_data));
871+ EXPECT_EQ (from_ascii, String (" Hello World" ));
872+
873+ // Test with UTF-8 data
874+ const char * utf8_data = " Hello, 世界!" ;
875+ String from_utf8 = String::createStringFromData (utf8_data, (int ) strlen (utf8_data));
876+ EXPECT_TRUE (from_utf8.contains (" Hello" ));
877+ EXPECT_TRUE (from_utf8.contains (" 世界" ));
878+
879+ // Test with zero size
880+ String empty_from_data = String::createStringFromData (ascii_data, 0 );
881+ EXPECT_TRUE (empty_from_data.isEmpty ());
882+ }
883+
884+ TEST_F (StringTests, FromUTF8)
885+ {
886+ // Test fromUTF8
887+ const char * utf8_text = " Hello, 世界!" ;
888+ String from_utf8 = String::fromUTF8 (utf8_text);
889+ EXPECT_TRUE (from_utf8.contains (" Hello" ));
890+ EXPECT_TRUE (from_utf8.contains (" 世界" ));
891+
892+ // Test with explicit length
893+ String partial_utf8 = String::fromUTF8 (utf8_text, 5 );
894+ EXPECT_EQ (partial_utf8, String (" Hello" ));
895+
896+ // Test with null input
897+ String null_utf8 = String::fromUTF8 (nullptr );
898+ EXPECT_TRUE (null_utf8.isEmpty ());
899+ }
900+
901+ TEST_F (StringTests, NaturalComparison)
902+ {
903+ // Test compareNatural
904+ EXPECT_EQ (String (" file1.txt" ).compareNatural (" file1.txt" ), 0 );
905+ EXPECT_LT (String (" file1.txt" ).compareNatural (" file10.txt" ), 0 );
906+ EXPECT_GT (String (" file10.txt" ).compareNatural (" file2.txt" ), 0 );
907+ EXPECT_EQ (String (" abc" ).compareNatural (" ABC" , false ), 0 ); // Case insensitive
908+ EXPECT_NE (String (" abc" ).compareNatural (" ABC" , true ), 0 ); // Case sensitive
909+
910+ // Test with numbers
911+ EXPECT_LT (String (" version1.2" ).compareNatural (" version1.10" ), 0 );
912+ EXPECT_GT (String (" version2.0" ).compareNatural (" version1.10" ), 0 );
913+ }
914+
915+ TEST_F (StringTests, StandardLibraryIntegration)
916+ {
917+ // Test std::string integration
918+ std::string std_str = " Hello from std::string" ;
919+ String yup_str (std_str);
920+ EXPECT_EQ (yup_str.toStdString (), std_str);
921+
922+ // Test std::wstring integration
923+ std::wstring wide_str = L" Hello from std::wstring" ;
924+ String yup_wide_str (wide_str);
925+ EXPECT_TRUE (yup_wide_str.contains (" Hello" ));
926+
927+ // Test std::string_view integration
928+ std::string_view string_view = " Hello from string_view" ;
929+ String yup_view_str (string_view);
930+ EXPECT_EQ (yup_view_str, String (" Hello from string_view" ));
931+
932+ // Test std::wstring_view integration
933+ std::wstring_view wide_view = L" Hello from wstring_view" ;
934+ String yup_wide_view_str (wide_view);
935+ EXPECT_TRUE (yup_wide_view_str.contains (" Hello" ));
936+ }
937+
938+ TEST_F (StringTests, CaseConversionEdgeCases)
939+ {
940+ // Test toUpperCase with edge cases
941+ String mixed_case (L" Hello, 世界! 123" );
942+ String upper_case = mixed_case.toUpperCase ();
943+ EXPECT_EQ (upper_case, String (L" HELLO, 世界! 123" ));
944+
945+ // Test toLowerCase with edge cases
946+ String lower_case = mixed_case.toLowerCase ();
947+ EXPECT_EQ (lower_case, String (L" hello, 世界! 123" ));
948+
949+ // Test with empty string
950+ EXPECT_EQ (String ().toUpperCase (), String ());
951+ EXPECT_EQ (String ().toLowerCase (), String ());
952+
953+ // Test with numbers only
954+ String numbers (" 12345" );
955+ EXPECT_EQ (numbers.toUpperCase (), String (" 12345" ));
956+ EXPECT_EQ (numbers.toLowerCase (), String (" 12345" ));
957+ }
958+
959+ TEST_F (StringTests, AdditionalUtilityMethods)
960+ {
961+ // Test swapWith
962+ String str1 (" Hello" );
963+ String str2 (" World" );
964+ String original1 = str1;
965+ String original2 = str2;
966+
967+ str1.swapWith (str2);
968+ EXPECT_EQ (str1, original2);
969+ EXPECT_EQ (str2, original1);
970+
971+ // Test hash method
972+ String hash_test (" test string" );
973+ size_t hash1 = hash_test.hash ();
974+ size_t hash2 = String (" test string" ).hash ();
975+ size_t hash3 = String (" different string" ).hash ();
976+
977+ EXPECT_EQ (hash1, hash2); // Same strings should have same hash
978+ EXPECT_NE (hash1, hash3); // Different strings should have different hashes
979+
980+ // Test begin/end iterators
981+ String iter_test (" abc" );
982+ auto it = iter_test.begin ();
983+ EXPECT_EQ (*it, ' a' );
984+ ++it;
985+ EXPECT_EQ (*it, ' b' );
986+ ++it;
987+ EXPECT_EQ (*it, ' c' );
988+ ++it;
989+ EXPECT_EQ (it, iter_test.end ());
990+ }
991+
992+ TEST_F (StringTests, EdgeCasesAndBoundaryConditions)
993+ {
994+ // Test with very long strings
995+ String long_str = String::repeatedString (" a" , 10000 );
996+ EXPECT_EQ (long_str.length (), 10000 );
997+ EXPECT_TRUE (long_str.startsWith (" aaa" ));
998+ EXPECT_TRUE (long_str.endsWith (" aaa" ));
999+
1000+ // Test with single character
1001+ String single_char (" x" );
1002+ EXPECT_EQ (single_char.length (), 1 );
1003+ EXPECT_EQ (single_char[0 ], ' x' );
1004+ EXPECT_EQ (single_char.getLastCharacter (), ' x' );
1005+
1006+ // Test boundary conditions for substring
1007+ String boundary_test (" hello" );
1008+ EXPECT_EQ (boundary_test.substring (-5 , 10 ), String (" hello" ));
1009+ EXPECT_EQ (boundary_test.substring (0 , 0 ), String ());
1010+ EXPECT_EQ (boundary_test.substring (5 , 5 ), String ());
1011+ EXPECT_EQ (boundary_test.substring (100 , 200 ), String ());
1012+
1013+ // Test with null characters
1014+ String null_char_test = String::charToString (0 );
1015+ EXPECT_EQ (null_char_test, String ());
1016+
1017+ // Test very large numbers
1018+ String large_num (std::numeric_limits<long long >::max ());
1019+ EXPECT_GT (large_num.length (), 0 );
1020+ EXPECT_EQ (large_num.getLargeIntValue (), std::numeric_limits<long long >::max ());
1021+ }
0 commit comments