You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			407 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			407 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
package nstr
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"net"
 | 
						|
	"net/url"
 | 
						|
	"reflect"
 | 
						|
	"regexp"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"unicode"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	alphaMatcher         = regexp.MustCompile(`^[a-zA-Z]+$`)
 | 
						|
	letterRegexMatcher   = regexp.MustCompile(`[a-zA-Z]`)
 | 
						|
	intStrMatcher        = regexp.MustCompile(`^[\+-]?\d+$`)
 | 
						|
	urlMatcher           = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
 | 
						|
	dnsMatcher           = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
 | 
						|
	emailMatcher         = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
 | 
						|
	chineseMobileMatcher = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
 | 
						|
	chineseIdMatcher     = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
 | 
						|
	chineseMatcher       = regexp.MustCompile("[\u4e00-\u9fa5]")
 | 
						|
	chinesePhoneMatcher  = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
 | 
						|
	creditCardMatcher    = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
 | 
						|
	base64Matcher        = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
 | 
						|
)
 | 
						|
 | 
						|
// IsString check if the value data type is string or not.
 | 
						|
func IsString(v any) bool {
 | 
						|
	if v == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	switch v.(type) {
 | 
						|
	case string:
 | 
						|
		return true
 | 
						|
	default:
 | 
						|
		return false
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// IsAlpha checks if the string contains only letters (a-zA-Z).
 | 
						|
func IsAlpha(str string) bool {
 | 
						|
	return alphaMatcher.MatchString(str)
 | 
						|
}
 | 
						|
 | 
						|
// IsAllUpper check if the string is all upper case letters A-Z.
 | 
						|
func IsAllUpper(str string) bool {
 | 
						|
	for _, r := range str {
 | 
						|
		if !unicode.IsUpper(r) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return str != ""
 | 
						|
}
 | 
						|
 | 
						|
// IsAllLower check if the string is all lower case letters a-z.
 | 
						|
func IsAllLower(str string) bool {
 | 
						|
	for _, r := range str {
 | 
						|
		if !unicode.IsLower(r) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return str != ""
 | 
						|
}
 | 
						|
 | 
						|
// ContainUpper check if the string contain at least one upper case letter A-Z.
 | 
						|
func ContainUpper(str string) bool {
 | 
						|
	for _, r := range str {
 | 
						|
		if unicode.IsUpper(r) && unicode.IsLetter(r) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// ContainLower check if the string contain at least one lower case letter a-z.
 | 
						|
func ContainLower(str string) bool {
 | 
						|
	for _, r := range str {
 | 
						|
		if unicode.IsLower(r) && unicode.IsLetter(r) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// ContainLetter check if the string contain at least one letter.
 | 
						|
func ContainLetter(str string) bool {
 | 
						|
	return letterRegexMatcher.MatchString(str)
 | 
						|
}
 | 
						|
 | 
						|
// IsJSON checks if the string is valid JSON.
 | 
						|
func IsJSON(str string) bool {
 | 
						|
	return json.Valid([]byte(str))
 | 
						|
}
 | 
						|
 | 
						|
// IsNumberStr check if the string can convert to a number.
 | 
						|
func IsNumberStr(s string) bool {
 | 
						|
	return IsIntStr(s) || IsFloatStr(s)
 | 
						|
}
 | 
						|
 | 
						|
// IsFloatStr check if the string can convert to a float.
 | 
						|
func IsFloatStr(str string) bool {
 | 
						|
	_, e := strconv.ParseFloat(str, 64)
 | 
						|
	return e == nil
 | 
						|
}
 | 
						|
 | 
						|
// IsIntStr check if the string can convert to a integer.
 | 
						|
func IsIntStr(str string) bool {
 | 
						|
	return intStrMatcher.MatchString(str)
 | 
						|
}
 | 
						|
 | 
						|
// IsIp check if the string is an ip address.
 | 
						|
func IsIp(ipstr string) bool {
 | 
						|
	ip := net.ParseIP(ipstr)
 | 
						|
	return ip != nil
 | 
						|
}
 | 
						|
 | 
						|
// IsIpV4 check if the string is a ipv4 address.
 | 
						|
func IsIpV4(ipstr string) bool {
 | 
						|
	ip := net.ParseIP(ipstr)
 | 
						|
	if ip == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return strings.Contains(ipstr, ".")
 | 
						|
}
 | 
						|
 | 
						|
// IsIpV6 check if the string is a ipv6 address.
 | 
						|
func IsIpV6(ipstr string) bool {
 | 
						|
	ip := net.ParseIP(ipstr)
 | 
						|
	if ip == nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return strings.Contains(ipstr, ":")
 | 
						|
}
 | 
						|
 | 
						|
// IsPort check if the string is a valid net port.
 | 
						|
func IsPort(str string) bool {
 | 
						|
	if i, err := strconv.ParseInt(str, 10, 64); err == nil && i > 0 && i < 65536 {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// IsUrl check if the string is url.
 | 
						|
func IsUrl(str string) bool {
 | 
						|
	if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	u, err := url.Parse(str)
 | 
						|
	if err != nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if strings.HasPrefix(u.Host, ".") {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	return urlMatcher.MatchString(str)
 | 
						|
}
 | 
						|
 | 
						|
// IsDns check if the string is dns.
 | 
						|
func IsDns(dns string) bool {
 | 
						|
	return dnsMatcher.MatchString(dns)
 | 
						|
}
 | 
						|
 | 
						|
// IsEmail check if the string is a email address.
 | 
						|
func IsEmail(email string) bool {
 | 
						|
	return emailMatcher.MatchString(email)
 | 
						|
}
 | 
						|
 | 
						|
// IsChineseMobile check if the string is chinese mobile number.
 | 
						|
func IsChineseMobile(mobileNum string) bool {
 | 
						|
	return chineseMobileMatcher.MatchString(mobileNum)
 | 
						|
}
 | 
						|
 | 
						|
// IsChineseIdNum check if the string is chinese id card.
 | 
						|
func IsChineseIdNum(id string) bool {
 | 
						|
	return chineseIdMatcher.MatchString(id)
 | 
						|
}
 | 
						|
 | 
						|
// ContainChinese check if the string contain mandarin chinese.
 | 
						|
func ContainChinese(s string) bool {
 | 
						|
	return chineseMatcher.MatchString(s)
 | 
						|
}
 | 
						|
 | 
						|
// IsChinesePhone check if the string is chinese phone number.
 | 
						|
// Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx.
 | 
						|
func IsChinesePhone(phone string) bool {
 | 
						|
	return chinesePhoneMatcher.MatchString(phone)
 | 
						|
}
 | 
						|
 | 
						|
// IsCreditCard check if the string is credit card.
 | 
						|
func IsCreditCard(creditCart string) bool {
 | 
						|
	return creditCardMatcher.MatchString(creditCart)
 | 
						|
}
 | 
						|
 | 
						|
// IsBase64 check if the string is base64 string.
 | 
						|
func IsBase64(base64 string) bool {
 | 
						|
	return base64Matcher.MatchString(base64)
 | 
						|
}
 | 
						|
 | 
						|
// IsEmptyString check if the string is empty.
 | 
						|
func IsEmptyString(str string) bool {
 | 
						|
	return len(str) == 0
 | 
						|
}
 | 
						|
 | 
						|
// IsRegexMatch check if the string match the regexp.
 | 
						|
func IsRegexMatch(str, regex string) bool {
 | 
						|
	reg := regexp.MustCompile(regex)
 | 
						|
	return reg.MatchString(str)
 | 
						|
}
 | 
						|
 | 
						|
// IsStrongPassword check if the string is strong password, if len(password) is less than the length param, return false
 | 
						|
// Strong password: alpha(lower+upper) + number + special chars(!@#$%^&*()?><).
 | 
						|
func IsStrongPassword(password string, length int) bool {
 | 
						|
	if len(password) < length {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	var num, lower, upper, special bool
 | 
						|
	for _, r := range password {
 | 
						|
		switch {
 | 
						|
		case unicode.IsDigit(r):
 | 
						|
			num = true
 | 
						|
		case unicode.IsUpper(r):
 | 
						|
			upper = true
 | 
						|
		case unicode.IsLower(r):
 | 
						|
			lower = true
 | 
						|
		case unicode.IsSymbol(r), unicode.IsPunct(r):
 | 
						|
			special = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return num && lower && upper && special
 | 
						|
}
 | 
						|
 | 
						|
// IsWeakPassword check if the string is weak password
 | 
						|
// only letter or only number or letter + number.
 | 
						|
func IsWeakPassword(password string) bool {
 | 
						|
	var num, letter, special bool
 | 
						|
	for _, r := range password {
 | 
						|
		switch {
 | 
						|
		case unicode.IsDigit(r):
 | 
						|
			num = true
 | 
						|
		case unicode.IsLetter(r):
 | 
						|
			letter = true
 | 
						|
		case unicode.IsSymbol(r), unicode.IsPunct(r):
 | 
						|
			special = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return (num || letter) && !special
 | 
						|
}
 | 
						|
 | 
						|
// IsZeroValue checks if value is a zero value.
 | 
						|
func IsZeroValue(value any) bool {
 | 
						|
	if value == nil {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	rv := reflect.ValueOf(value)
 | 
						|
	if rv.Kind() == reflect.Ptr {
 | 
						|
		rv = rv.Elem()
 | 
						|
	}
 | 
						|
 | 
						|
	if !rv.IsValid() {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	switch rv.Kind() {
 | 
						|
	case reflect.String:
 | 
						|
		return rv.Len() == 0
 | 
						|
	case reflect.Bool:
 | 
						|
		return !rv.Bool()
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		return rv.Int() == 0
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | 
						|
		return rv.Uint() == 0
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		return rv.Float() == 0
 | 
						|
	case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Interface, reflect.Slice, reflect.Map:
 | 
						|
		return rv.IsNil()
 | 
						|
	}
 | 
						|
 | 
						|
	return reflect.DeepEqual(rv.Interface(), reflect.Zero(rv.Type()).Interface())
 | 
						|
}
 | 
						|
 | 
						|
// ----- refer from github.com/yuin/goldmark/util
 | 
						|
 | 
						|
// refer from github.com/yuin/goldmark/util
 | 
						|
var spaceTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
						|
 | 
						|
// IsSpace returns true if the given character is a space, otherwise false.
 | 
						|
func IsSpace(c byte) bool { return spaceTable[c] == 1 }
 | 
						|
 | 
						|
// IsEmpty returns true if the given string is empty.
 | 
						|
func IsEmpty(s string) bool { return len(s) == 0 }
 | 
						|
 | 
						|
// IsBlank returns true if the given string is all space characters.
 | 
						|
func IsBlank(s string) bool { return IsBlankBytes([]byte(s)) }
 | 
						|
 | 
						|
// IsNotBlank returns true if the given string is not blank.
 | 
						|
func IsNotBlank(s string) bool { return !IsBlankBytes([]byte(s)) }
 | 
						|
 | 
						|
// IsBlankBytes returns true if the given []byte is all space characters.
 | 
						|
func IsBlankBytes(bs []byte) bool {
 | 
						|
	for _, b := range bs {
 | 
						|
		if !IsSpace(b) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// IsSymbol reports whether the rune is a symbolic character.
 | 
						|
func IsSymbol(r rune) bool { return unicode.IsSymbol(r) }
 | 
						|
 | 
						|
// HasEmpty value for input strings
 | 
						|
func HasEmpty(ss ...string) bool {
 | 
						|
	for _, s := range ss {
 | 
						|
		if s == "" {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// IsAllEmpty for input strings
 | 
						|
func IsAllEmpty(ss ...string) bool {
 | 
						|
	for _, s := range ss {
 | 
						|
		if s != "" {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// ContainsByte in given string.
 | 
						|
func ContainsByte(s string, c byte) bool {
 | 
						|
	return strings.IndexByte(s, c) >= 0
 | 
						|
}
 | 
						|
 | 
						|
// ContainsOne substr(s) in the given string. alias of HasOneSub()
 | 
						|
func ContainsOne(s string, subs []string) bool { return HasOneSub(s, subs) }
 | 
						|
 | 
						|
// HasOneSub substr(s) in the given string.
 | 
						|
func HasOneSub(s string, subs []string) bool {
 | 
						|
	for _, sub := range subs {
 | 
						|
		if strings.Contains(s, sub) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// ContainsAll substr(s) in the given string. alias of HasAllSubs()
 | 
						|
func ContainsAll(s string, subs []string) bool { return HasAllSubs(s, subs) }
 | 
						|
 | 
						|
// HasAllSubs all substr in the given string.
 | 
						|
func HasAllSubs(s string, subs []string) bool {
 | 
						|
	for _, sub := range subs {
 | 
						|
		if !strings.Contains(s, sub) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// IsStartsOf alias of the HasOnePrefix
 | 
						|
func IsStartsOf(s string, prefixes []string) bool {
 | 
						|
	return HasOnePrefix(s, prefixes)
 | 
						|
}
 | 
						|
 | 
						|
// HasOnePrefix the string start withs one of the subs
 | 
						|
func HasOnePrefix(s string, prefixes []string) bool {
 | 
						|
	for _, prefix := range prefixes {
 | 
						|
		if strings.HasPrefix(s, prefix) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// HasPrefix substr in the given string.
 | 
						|
func HasPrefix(s string, prefix string) bool { return strings.HasPrefix(s, prefix) }
 | 
						|
 | 
						|
// IsStartOf alias of the strings.HasPrefix
 | 
						|
func IsStartOf(s, prefix string) bool { return strings.HasPrefix(s, prefix) }
 | 
						|
 | 
						|
// HasSuffix substr in the given string.
 | 
						|
func HasSuffix(s string, suffix string) bool { return strings.HasSuffix(s, suffix) }
 | 
						|
 | 
						|
// IsEndOf alias of the strings.HasSuffix
 | 
						|
func IsEndOf(s, suffix string) bool { return strings.HasSuffix(s, suffix) }
 | 
						|
 | 
						|
// HasOneSuffix the string end withs one of the subs
 | 
						|
func HasOneSuffix(s string, suffixes []string) bool {
 | 
						|
	for _, suffix := range suffixes {
 | 
						|
		if strings.HasSuffix(s, suffix) {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 |