· 10 years ago · Mar 04, 2016, 10:06 AM
1// Contains check if the string contains the substring.
2func Contains(str, substring string) bool {
3 return strings.Contains(str, substring)
4}
5
6// Matches check if string matches the pattern (pattern is regular expression)
7// In case of error return false
8func Matches(str, pattern string) bool {
9 match, _ := regexp.MatchString(pattern, str)
10 return match
11}
12
13// LeftTrim trim characters from the left-side of the input.
14// If second argument is empty, it's will be remove leading spaces.
15func LeftTrim(str, chars string) string {
16 pattern := ""
17 if chars == "" {
18 pattern = "^\\s+"
19 } else {
20 pattern = "^[" + chars + "]+"
21 }
22 r, _ := regexp.Compile(pattern)
23 return string(r.ReplaceAll([]byte(str), []byte("")))
24}
25
26// RightTrim trim characters from the right-side of the input.
27// If second argument is empty, it's will be remove spaces.
28func RightTrim(str, chars string) string {
29 pattern := ""
30 if chars == "" {
31 pattern = "\\s+$"
32 } else {
33 pattern = "[" + chars + "]+$"
34 }
35 r, _ := regexp.Compile(pattern)
36 return string(r.ReplaceAll([]byte(str), []byte("")))
37}
38
39// Trim trim characters from both sides of the input.
40// If second argument is empty, it's will be remove spaces.
41func Trim(str, chars string) string {
42 return LeftTrim(RightTrim(str, chars), chars)
43}
44
45// WhiteList remove characters that do not appear in the whitelist.
46func WhiteList(str, chars string) string {
47 pattern := "[^" + chars + "]+"
48 r, _ := regexp.Compile(pattern)
49 return string(r.ReplaceAll([]byte(str), []byte("")))
50}
51
52// BlackList remove characters that appear in the blacklist.
53func BlackList(str, chars string) string {
54 pattern := "[" + chars + "]+"
55 r, _ := regexp.Compile(pattern)
56 return string(r.ReplaceAll([]byte(str), []byte("")))
57}
58
59// StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
60// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
61func StripLow(str string, keepNewLines bool) string {
62 chars := ""
63 if keepNewLines {
64 chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
65 } else {
66 chars = "\x00-\x1F\x7F"
67 }
68 return BlackList(str, chars)
69}
70
71// ReplacePattern replace regular expression pattern in string
72func ReplacePattern(str, pattern, replace string) string {
73 r, _ := regexp.Compile(pattern)
74 return string(r.ReplaceAll([]byte(str), []byte(replace)))
75}
76
77// Escape replace <, >, & and " with HTML entities.
78var Escape = html.EscapeString
79
80func addSegment(inrune, segment []rune) []rune {
81 if len(segment) == 0 {
82 return inrune
83 }
84 if len(inrune) != 0 {
85 inrune = append(inrune, '_')
86 }
87 inrune = append(inrune, segment...)
88 return inrune
89}
90
91// UnderscoreToCamelCase converts from underscore separated form to camel case form.
92// Ex.: my_func => MyFunc
93func UnderscoreToCamelCase(s string) string {
94 return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
95}
96
97// CamelCaseToUnderscore converts from camel case form to underscore separated form.
98// Ex.: MyFunc => my_func
99func CamelCaseToUnderscore(str string) string {
100 var output []rune
101 var segment []rune
102 for _, r := range str {
103 if !unicode.IsLower(r) {
104 output = addSegment(output, segment)
105 segment = nil
106 }
107 segment = append(segment, unicode.ToLower(r))
108 }
109 output = addSegment(output, segment)
110 return string(output)
111}
112
113// Reverse return reversed string
114func Reverse(s string) string {
115 r := []rune(s)
116 for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
117 r[i], r[j] = r[j], r[i]
118 }
119 return string(r)
120}
121
122// GetLines split string by "\n" and return array of lines
123func GetLines(s string) []string {
124 return strings.Split(s, "\n")
125}
126
127// GetLine return specified line of multiline string
128func GetLine(s string, index int) (string, error) {
129 lines := GetLines(s)
130 if index < 0 || index >= len(lines) {
131 return "", errors.New("line index out of bounds")
132 }
133 return lines[index], nil
134}
135
136// RemoveTags remove all tags from HTML string
137func RemoveTags(s string) string {
138 return ReplacePattern(s, "<[^>]*>", "")
139}
140
141// SafeFileName return safe string that can be used in file names
142func SafeFileName(str string) string {
143 name := strings.ToLower(str)
144 name = path.Clean(path.Base(name))
145 name = strings.Trim(name, " ")
146 separators, err := regexp.Compile(`[ &_=+:]`)
147 if err == nil {
148 name = separators.ReplaceAllString(name, "-")
149 }
150 legal, err := regexp.Compile(`[^[:alnum:]-.]`)
151 if err == nil {
152 name = legal.ReplaceAllString(name, "")
153 }
154 for strings.Contains(name, "--") {
155 name = strings.Replace(name, "--", "-", -1)
156 }
157 return name
158}
159
160// NormalizeEmail canonicalize an email address.
161// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
162// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
163// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
164// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
165// normalized to @gmail.com.
166func NormalizeEmail(str string) (string, error) {
167 if !IsEmail(str) {
168 return "", fmt.Errorf("%s is not an email", str)
169 }
170 parts := strings.Split(str, "@")
171 parts[0] = strings.ToLower(parts[0])
172 parts[1] = strings.ToLower(parts[1])
173 if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
174 parts[1] = "gmail.com"
175 parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
176 }
177 return strings.Join(parts, "@"), nil
178}
179
180// Will truncate a string closest length without breaking words.
181func Truncate(str string, length int, ending string) string {
182 var aftstr, befstr string
183 if len(str) > length {
184 words := strings.Fields(str)
185 before, present := 0, 0
186 for i := range words {
187 befstr = aftstr
188 before = present
189 aftstr = aftstr + words[i] + " "
190 present = len(aftstr)
191 if present > length && i != 0 {
192 if (length - before) < (present - length) {
193 return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
194 } else {
195 return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
196 }
197 }
198 }
199 }
200
201 return str
202}