From 9ad9d1805beccf87a67c0f801025337558a9b192 Mon Sep 17 00:00:00 2001 From: donutloop Date: Sun, 26 Dec 2021 14:16:20 +0100 Subject: [PATCH] Regex validators: Precompile all known regex patterns (#3) Reduce executions time of pattern matching, regex patterns are expensive to compile at runtime. --- validator/validator.go | 59 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/validator/validator.go b/validator/validator.go index c8b1da2..8b6128e 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -11,11 +11,11 @@ import ( "unicode" ) +var isAlphaRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`) + // IsAlpha checks if the string contains only letters (a-zA-Z) func IsAlpha(s string) bool { - pattern := `^[a-zA-Z]+$` - reg := regexp.MustCompile(pattern) - return reg.MatchString(s) + return isAlphaRegexMatcher.MatchString(s) } // IsNumberStr check if the string can convert to a number. @@ -29,10 +29,11 @@ func IsFloatStr(s string) bool { return e == nil } +var isIntStrRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`) + // IsIntStr check if the string can convert to a integer. func IsIntStr(s string) bool { - match, _ := regexp.MatchString(`^[\+-]?\d+$`, s) - return match + return isIntStrRegexMatcher.MatchString(s) } // IsIp check if the string is a ip address. @@ -71,61 +72,61 @@ func IsIpV6(ipstr string) bool { return false } +var isDnsRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`) + // IsDns check if the string is dns. func IsDns(dns string) bool { - pattern := `^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$` - reg := regexp.MustCompile(pattern) - return reg.MatchString(dns) + return isDnsRegexMatcher.MatchString(dns) } +var isEmailRegexMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`) + // IsEmail check if the string is a email address. func IsEmail(email string) bool { - pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` - reg := regexp.MustCompile(pattern) - return reg.MatchString(email) + return isEmailRegexMatcher.MatchString(email) } +var isChineseMobileRegexMatcher *regexp.Regexp = regexp.MustCompile("^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$") + // IsChineseMobile check if the string is chinese mobile number. func IsChineseMobile(mobileNum string) bool { - pattern := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$" - reg := regexp.MustCompile(pattern) - return reg.MatchString(mobileNum) + return isChineseMobileRegexMatcher.MatchString(mobileNum) } +var isChineseIdNumRegexMatcher *regexp.Regexp = 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]$`) + // IsChineseIdNum check if the string is chinese id number. func IsChineseIdNum(id string) bool { - pattern := `^[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]$` - reg := regexp.MustCompile(pattern) - return reg.MatchString(id) + return isChineseIdNumRegexMatcher.MatchString(id) } +var containChineseRegexMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]") + // ContainChinese check if the string contain mandarin chinese. func ContainChinese(s string) bool { - pattern := "[\u4e00-\u9fa5]" - reg := regexp.MustCompile(pattern) - return reg.MatchString(s) + return containChineseRegexMatcher.MatchString(s) } +var isChinesePhoneRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}`) + // IsChinesePhone check if the string is chinese phone number. // Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx func IsChinesePhone(phone string) bool { - pattern := `\d{3}-\d{8}|\d{4}-\d{7}` - reg := regexp.MustCompile(pattern) - return reg.MatchString(phone) + return isChinesePhoneRegexMatcher.MatchString(phone) } +var isCreditCardRegexMatcher *regexp.Regexp = 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})$`) + // IsCreditCard check if the string is credit card. func IsCreditCard(creditCart string) bool { - pattern := `^(?: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})$` - reg := regexp.MustCompile(pattern) - return reg.MatchString(creditCart) + return isCreditCardRegexMatcher.MatchString(creditCart) } +var isBase64RegexMatcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`) + // IsBase64 check if the string is base64 string. func IsBase64(base64 string) bool { - pattern := `^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$` - reg := regexp.MustCompile(pattern) - return reg.MatchString(base64) + return isBase64RegexMatcher.MatchString(base64) } // IsEmptyString check if the string is empty.