From c7eca3dfad578492f243d631e4a407487de975c9 Mon Sep 17 00:00:00 2001 From: Baraa Al-Masri Date: Fri, 12 Nov 2021 10:34:59 +0200 Subject: [PATCH] added reverse function that reverses only arabic text! --- stringutils.go | 73 ++++++++++++++++++++++++++++++++++++++++----- stringutils_test.go | 33 ++++++++++++++++++++ 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/stringutils.go b/stringutils.go index ba81fb8..2ea94b8 100644 --- a/stringutils.go +++ b/stringutils.go @@ -10,6 +10,61 @@ func Reverse(s string) string { return string(r) } +// ReverseArabicChars returns a string reversed +func ReverseArabicChars(s string) string { + s = Reverse(s) + + var ( + arabicChars = getNonArabicCharsRanges(s) + runes = []rune(s) + ) + + for _, c := range arabicChars { + after := runes[c.end+1:] + runes = append(runes[0:c.start], []rune(Reverse(string(runes[c.start:c.end+1])))...) + runes = append(runes, after...) + } + + return string(runes) +} + +type _range struct { + start, end int +} + +// getNonArabicCharsRanges returns ranges of the string where non arabic characters exist! +func getNonArabicCharsRanges(s string) []_range { + var ( + start, end = 0, 0 + indexes = []_range{} + foundArabic = false + ) + + i := 0 + for _, c := range s { + if !isArabicChar(c) { + if !foundArabic { + start = i + foundArabic = true + } + } else { + end = i - 1 + if end > start { + indexes = append(indexes, _range{start, end}) + } + start = i + foundArabic = false + } + i++ + } + + if len(indexes) == 0 || indexes[len(indexes)-1].end != len(s)-1 { + indexes = append(indexes, _range{start, i - 1}) + } + + return indexes +} + // SmartLength returns the length of the given string // without considering the Arabic Vowels (Tashkeel). func SmartLength(s *string) int { @@ -139,18 +194,22 @@ func getHarf(char rune) Harf { return Harf{Unicode: char, Isolated: char, Medium: char, Final: char} } +// isArabicChar checks whether the character is from the arabic alphabet or not +func isArabicChar(chr rune) bool { + for _, c := range alphabet { + if c.equals(chr) { + return true + } + } + return false +} + //RemoveAllNonAlphabetChars deletes all characters which are not included in Arabic Alphabet func RemoveAllNonArabicChars(text string) string { runes := []rune(text) newText := []rune{} for _, current := range runes { - inAlphabet := false - for _, s := range alphabet { - if s.equals(current) { - inAlphabet = true - } - } - if inAlphabet { + if isArabicChar(current) { newText = append(newText, current) } } diff --git a/stringutils_test.go b/stringutils_test.go index ac7ca8e..ed14b2b 100644 --- a/stringutils_test.go +++ b/stringutils_test.go @@ -107,3 +107,36 @@ func TestRemoveAllNonArabicChars(t *testing.T) { } } } + +func eqArr(a1, a2 []_range) bool { + if len(a1) != len(a2) { + return false + } + + for i := 0; i < len(a1); i++ { + if a1[i].start != a2[i].start && a1[i].end != a2[i].end { + return false + } + } + + return true +} + +func TestGetArabicCharsIndexes(t *testing.T) { + cases := []struct { + in, want string + }{ + {"نص عربي", "يبرع صن"}, + {"السلام عليكم", "مكيلع مالسلا"}, + {"مرhبا يا friends اصدقاء", "ءاقدصا friends اي ابhرم"}, + {"Hello World!", "Hello World!"}, + } + + for _, c := range cases { + out := ReverseArabicChars(c.in) + if out != c.want { + t.Errorf("getArabicCharsRanges(%s) == %s, want %s\n", c.in, out, c.want) + } + } + +}