Browse Source

feat: Adding CamelCaseSplit

Matthias Ladkau 3 years ago
parent
commit
daa1ea8646
2 changed files with 103 additions and 0 deletions
  1. 65 0
      stringutil/stringutil.go
  2. 38 0
      stringutil/stringutil_test.go

+ 65 - 0
stringutil/stringutil.go

@@ -21,6 +21,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"unicode"
 	"unicode/utf8"
 )
 
@@ -725,3 +726,67 @@ func LengthConstantEquals(str1 []byte, str2 []byte) bool {
 
 	return diff == 0
 }
+
+/*
+CamelCaseSplit splits a camel case string into a slice.
+*/
+func CamelCaseSplit(src string) []string {
+	var result []string
+
+	if !utf8.ValidString(src) {
+		result = []string{src}
+
+	} else {
+
+		type rType int
+		const (
+			undefined rType = iota
+			lower
+			upper
+			digit
+			other
+		)
+
+		var current, previous rType
+		var runes [][]rune
+
+		for _, r := range src {
+			if unicode.IsLower(r) {
+				current = lower
+			} else if unicode.IsUpper(r) {
+				current = upper
+			} else if unicode.IsDigit(r) {
+				current = digit
+			} else {
+				current = other
+			}
+
+			if current == previous {
+				runes[len(runes)-1] = append(runes[len(runes)-1], r)
+			} else {
+				runes = append(runes, []rune{r})
+				previous = current
+			}
+		}
+
+		for i := 0; i < len(runes)-1; i++ {
+
+			// Detect cases like "ROCKH" "ard" and correct them to
+			// "ROCK" "Hard"
+
+			if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) {
+
+				runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
+				runes[i] = runes[i][:len(runes[i])-1]
+			}
+		}
+
+		for _, s := range runes {
+			if len(s) > 0 {
+				result = append(result, string(s))
+			}
+		}
+	}
+
+	return result
+}

+ 38 - 0
stringutil/stringutil_test.go

@@ -694,3 +694,41 @@ foo
 	}
 
 }
+
+func TestCamelCaseSplit(t *testing.T) {
+
+	if res := fmt.Sprint(CamelCaseSplit("FooBar")); res != "[Foo Bar]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("FooB#ar")); res != "[Foo B # ar]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("fOObAR")); res != "[f O Ob AR]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("lower")); res != "[lower]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("foo1bar")); res != "[foo 1 bar]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("Low\xf2\xe6Er1")); res != "[Low\xf2\xe6Er1]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+
+	if res := fmt.Sprint(CamelCaseSplit("ROCKHard")); res != "[ROCK Hard]" {
+		t.Error("Unexpected result:", res)
+		return
+	}
+}