forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/asaskevich/govalidator/utils.go

456 lines
8.0 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
package govalidator
import (
"errors"
"fmt"
"html"
"math"
"path"
"regexp"
"strings"
"unicode"
"unicode/utf8"
)
// Contains checks if the string contains the substring.
2024-02-18 10:42:21 +00:00
func Contains(str, substring string) bool {
2024-02-18 10:42:21 +00:00
return strings.Contains(str, substring)
2024-02-18 10:42:21 +00:00
}
// Matches checks if string matches the pattern (pattern is regular expression)
2024-02-18 10:42:21 +00:00
// In case of error return false
2024-02-18 10:42:21 +00:00
func Matches(str, pattern string) bool {
2024-02-18 10:42:21 +00:00
match, _ := regexp.MatchString(pattern, str)
2024-02-18 10:42:21 +00:00
return match
2024-02-18 10:42:21 +00:00
}
// LeftTrim trims characters from the left side of the input.
2024-02-18 10:42:21 +00:00
// If second argument is empty, it will remove leading spaces.
2024-02-18 10:42:21 +00:00
func LeftTrim(str, chars string) string {
2024-02-18 10:42:21 +00:00
if chars == "" {
2024-02-18 10:42:21 +00:00
return strings.TrimLeftFunc(str, unicode.IsSpace)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
r, _ := regexp.Compile("^[" + chars + "]+")
2024-02-18 10:42:21 +00:00
return r.ReplaceAllString(str, "")
2024-02-18 10:42:21 +00:00
}
// RightTrim trims characters from the right side of the input.
2024-02-18 10:42:21 +00:00
// If second argument is empty, it will remove trailing spaces.
2024-02-18 10:42:21 +00:00
func RightTrim(str, chars string) string {
2024-02-18 10:42:21 +00:00
if chars == "" {
2024-02-18 10:42:21 +00:00
return strings.TrimRightFunc(str, unicode.IsSpace)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
r, _ := regexp.Compile("[" + chars + "]+$")
2024-02-18 10:42:21 +00:00
return r.ReplaceAllString(str, "")
2024-02-18 10:42:21 +00:00
}
// Trim trims characters from both sides of the input.
2024-02-18 10:42:21 +00:00
// If second argument is empty, it will remove spaces.
2024-02-18 10:42:21 +00:00
func Trim(str, chars string) string {
2024-02-18 10:42:21 +00:00
return LeftTrim(RightTrim(str, chars), chars)
2024-02-18 10:42:21 +00:00
}
// WhiteList removes characters that do not appear in the whitelist.
2024-02-18 10:42:21 +00:00
func WhiteList(str, chars string) string {
2024-02-18 10:42:21 +00:00
pattern := "[^" + chars + "]+"
2024-02-18 10:42:21 +00:00
r, _ := regexp.Compile(pattern)
2024-02-18 10:42:21 +00:00
return r.ReplaceAllString(str, "")
2024-02-18 10:42:21 +00:00
}
// BlackList removes characters that appear in the blacklist.
2024-02-18 10:42:21 +00:00
func BlackList(str, chars string) string {
2024-02-18 10:42:21 +00:00
pattern := "[" + chars + "]+"
2024-02-18 10:42:21 +00:00
r, _ := regexp.Compile(pattern)
2024-02-18 10:42:21 +00:00
return r.ReplaceAllString(str, "")
2024-02-18 10:42:21 +00:00
}
// StripLow removes characters with a numerical value < 32 and 127, mostly control characters.
2024-02-18 10:42:21 +00:00
// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
2024-02-18 10:42:21 +00:00
func StripLow(str string, keepNewLines bool) string {
2024-02-18 10:42:21 +00:00
chars := ""
2024-02-18 10:42:21 +00:00
if keepNewLines {
2024-02-18 10:42:21 +00:00
chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
2024-02-18 10:42:21 +00:00
} else {
2024-02-18 10:42:21 +00:00
chars = "\x00-\x1F\x7F"
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return BlackList(str, chars)
2024-02-18 10:42:21 +00:00
}
// ReplacePattern replaces regular expression pattern in string
2024-02-18 10:42:21 +00:00
func ReplacePattern(str, pattern, replace string) string {
2024-02-18 10:42:21 +00:00
r, _ := regexp.Compile(pattern)
2024-02-18 10:42:21 +00:00
return r.ReplaceAllString(str, replace)
2024-02-18 10:42:21 +00:00
}
// Escape replaces <, >, & and " with HTML entities.
2024-02-18 10:42:21 +00:00
var Escape = html.EscapeString
func addSegment(inrune, segment []rune) []rune {
2024-02-18 10:42:21 +00:00
if len(segment) == 0 {
2024-02-18 10:42:21 +00:00
return inrune
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if len(inrune) != 0 {
2024-02-18 10:42:21 +00:00
inrune = append(inrune, '_')
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
inrune = append(inrune, segment...)
2024-02-18 10:42:21 +00:00
return inrune
2024-02-18 10:42:21 +00:00
}
// UnderscoreToCamelCase converts from underscore separated form to camel case form.
2024-02-18 10:42:21 +00:00
// Ex.: my_func => MyFunc
2024-02-18 10:42:21 +00:00
func UnderscoreToCamelCase(s string) string {
2024-02-18 10:42:21 +00:00
return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
2024-02-18 10:42:21 +00:00
}
// CamelCaseToUnderscore converts from camel case form to underscore separated form.
2024-02-18 10:42:21 +00:00
// Ex.: MyFunc => my_func
2024-02-18 10:42:21 +00:00
func CamelCaseToUnderscore(str string) string {
2024-02-18 10:42:21 +00:00
var output []rune
2024-02-18 10:42:21 +00:00
var segment []rune
2024-02-18 10:42:21 +00:00
for _, r := range str {
// not treat number as separate segment
2024-02-18 10:42:21 +00:00
if !unicode.IsLower(r) && string(r) != "_" && !unicode.IsNumber(r) {
2024-02-18 10:42:21 +00:00
output = addSegment(output, segment)
2024-02-18 10:42:21 +00:00
segment = nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
segment = append(segment, unicode.ToLower(r))
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
output = addSegment(output, segment)
2024-02-18 10:42:21 +00:00
return string(output)
2024-02-18 10:42:21 +00:00
}
// Reverse returns reversed string
2024-02-18 10:42:21 +00:00
func Reverse(s string) string {
2024-02-18 10:42:21 +00:00
r := []rune(s)
2024-02-18 10:42:21 +00:00
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
2024-02-18 10:42:21 +00:00
r[i], r[j] = r[j], r[i]
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return string(r)
2024-02-18 10:42:21 +00:00
}
// GetLines splits string by "\n" and return array of lines
2024-02-18 10:42:21 +00:00
func GetLines(s string) []string {
2024-02-18 10:42:21 +00:00
return strings.Split(s, "\n")
2024-02-18 10:42:21 +00:00
}
// GetLine returns specified line of multiline string
2024-02-18 10:42:21 +00:00
func GetLine(s string, index int) (string, error) {
2024-02-18 10:42:21 +00:00
lines := GetLines(s)
2024-02-18 10:42:21 +00:00
if index < 0 || index >= len(lines) {
2024-02-18 10:42:21 +00:00
return "", errors.New("line index out of bounds")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return lines[index], nil
2024-02-18 10:42:21 +00:00
}
// RemoveTags removes all tags from HTML string
2024-02-18 10:42:21 +00:00
func RemoveTags(s string) string {
2024-02-18 10:42:21 +00:00
return ReplacePattern(s, "<[^>]*>", "")
2024-02-18 10:42:21 +00:00
}
// SafeFileName returns safe string that can be used in file names
2024-02-18 10:42:21 +00:00
func SafeFileName(str string) string {
2024-02-18 10:42:21 +00:00
name := strings.ToLower(str)
2024-02-18 10:42:21 +00:00
name = path.Clean(path.Base(name))
2024-02-18 10:42:21 +00:00
name = strings.Trim(name, " ")
2024-02-18 10:42:21 +00:00
separators, err := regexp.Compile(`[ &_=+:]`)
2024-02-18 10:42:21 +00:00
if err == nil {
2024-02-18 10:42:21 +00:00
name = separators.ReplaceAllString(name, "-")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
legal, err := regexp.Compile(`[^[:alnum:]-.]`)
2024-02-18 10:42:21 +00:00
if err == nil {
2024-02-18 10:42:21 +00:00
name = legal.ReplaceAllString(name, "")
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
for strings.Contains(name, "--") {
2024-02-18 10:42:21 +00:00
name = strings.Replace(name, "--", "-", -1)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return name
2024-02-18 10:42:21 +00:00
}
// NormalizeEmail canonicalize an email address.
2024-02-18 10:42:21 +00:00
// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
2024-02-18 10:42:21 +00:00
// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
2024-02-18 10:42:21 +00:00
// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
2024-02-18 10:42:21 +00:00
// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
2024-02-18 10:42:21 +00:00
// normalized to @gmail.com.
2024-02-18 10:42:21 +00:00
func NormalizeEmail(str string) (string, error) {
2024-02-18 10:42:21 +00:00
if !IsEmail(str) {
2024-02-18 10:42:21 +00:00
return "", fmt.Errorf("%s is not an email", str)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
parts := strings.Split(str, "@")
2024-02-18 10:42:21 +00:00
parts[0] = strings.ToLower(parts[0])
2024-02-18 10:42:21 +00:00
parts[1] = strings.ToLower(parts[1])
2024-02-18 10:42:21 +00:00
if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
2024-02-18 10:42:21 +00:00
parts[1] = "gmail.com"
2024-02-18 10:42:21 +00:00
parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return strings.Join(parts, "@"), nil
2024-02-18 10:42:21 +00:00
}
// Truncate a string to the closest length without breaking words.
2024-02-18 10:42:21 +00:00
func Truncate(str string, length int, ending string) string {
2024-02-18 10:42:21 +00:00
var aftstr, befstr string
2024-02-18 10:42:21 +00:00
if len(str) > length {
2024-02-18 10:42:21 +00:00
words := strings.Fields(str)
2024-02-18 10:42:21 +00:00
before, present := 0, 0
2024-02-18 10:42:21 +00:00
for i := range words {
2024-02-18 10:42:21 +00:00
befstr = aftstr
2024-02-18 10:42:21 +00:00
before = present
2024-02-18 10:42:21 +00:00
aftstr = aftstr + words[i] + " "
2024-02-18 10:42:21 +00:00
present = len(aftstr)
2024-02-18 10:42:21 +00:00
if present > length && i != 0 {
2024-02-18 10:42:21 +00:00
if (length - before) < (present - length) {
2024-02-18 10:42:21 +00:00
return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
return str
2024-02-18 10:42:21 +00:00
}
// PadLeft pads left side of a string if size of string is less then indicated pad length
2024-02-18 10:42:21 +00:00
func PadLeft(str string, padStr string, padLen int) string {
2024-02-18 10:42:21 +00:00
return buildPadStr(str, padStr, padLen, true, false)
2024-02-18 10:42:21 +00:00
}
// PadRight pads right side of a string if size of string is less then indicated pad length
2024-02-18 10:42:21 +00:00
func PadRight(str string, padStr string, padLen int) string {
2024-02-18 10:42:21 +00:00
return buildPadStr(str, padStr, padLen, false, true)
2024-02-18 10:42:21 +00:00
}
// PadBoth pads both sides of a string if size of string is less then indicated pad length
2024-02-18 10:42:21 +00:00
func PadBoth(str string, padStr string, padLen int) string {
2024-02-18 10:42:21 +00:00
return buildPadStr(str, padStr, padLen, true, true)
2024-02-18 10:42:21 +00:00
}
// PadString either left, right or both sides.
2024-02-18 10:42:21 +00:00
// Note that padding string can be unicode and more then one character
2024-02-18 10:42:21 +00:00
func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string {
// When padded length is less then the current string size
2024-02-18 10:42:21 +00:00
if padLen < utf8.RuneCountInString(str) {
2024-02-18 10:42:21 +00:00
return str
2024-02-18 10:42:21 +00:00
}
padLen -= utf8.RuneCountInString(str)
targetLen := padLen
targetLenLeft := targetLen
2024-02-18 10:42:21 +00:00
targetLenRight := targetLen
2024-02-18 10:42:21 +00:00
if padLeft && padRight {
2024-02-18 10:42:21 +00:00
targetLenLeft = padLen / 2
2024-02-18 10:42:21 +00:00
targetLenRight = padLen - targetLenLeft
2024-02-18 10:42:21 +00:00
}
strToRepeatLen := utf8.RuneCountInString(padStr)
repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen)))
2024-02-18 10:42:21 +00:00
repeatedString := strings.Repeat(padStr, repeatTimes)
leftSide := ""
2024-02-18 10:42:21 +00:00
if padLeft {
2024-02-18 10:42:21 +00:00
leftSide = repeatedString[0:targetLenLeft]
2024-02-18 10:42:21 +00:00
}
rightSide := ""
2024-02-18 10:42:21 +00:00
if padRight {
2024-02-18 10:42:21 +00:00
rightSide = repeatedString[0:targetLenRight]
2024-02-18 10:42:21 +00:00
}
return leftSide + str + rightSide
2024-02-18 10:42:21 +00:00
}
// TruncatingErrorf removes extra args from fmt.Errorf if not formatted in the str object
2024-02-18 10:42:21 +00:00
func TruncatingErrorf(str string, args ...interface{}) error {
2024-02-18 10:42:21 +00:00
n := strings.Count(str, "%s")
2024-02-18 10:42:21 +00:00
return fmt.Errorf(str, args[:n]...)
2024-02-18 10:42:21 +00:00
}