mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 23:20:25 +08:00
171 lines
4.2 KiB
Go
171 lines
4.2 KiB
Go
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cloud .
|
|
|
|
package runes
|
|
|
|
// ContainsAnyWordRunes 直接使用rune检查字符串是否包含任一单词
|
|
func ContainsAnyWordRunes(s string, words [][]rune, isCaseInsensitive bool) bool {
|
|
var allRunes = []rune(s)
|
|
if len(allRunes) == 0 || len(words) == 0 {
|
|
return false
|
|
}
|
|
|
|
var lastRune rune // last searching rune in s
|
|
var lastIndex = -2 // -2: not started, -1: not found, >=0: rune index
|
|
for _, wordRunes := range words {
|
|
if len(wordRunes) == 0 {
|
|
continue
|
|
}
|
|
|
|
if lastIndex > -2 && lastRune == wordRunes[0] {
|
|
if lastIndex >= 0 {
|
|
result, _ := ContainsWordRunes(allRunes[lastIndex:], wordRunes, isCaseInsensitive)
|
|
if result {
|
|
return true
|
|
}
|
|
}
|
|
continue
|
|
} else {
|
|
result, firstIndex := ContainsWordRunes(allRunes, wordRunes, isCaseInsensitive)
|
|
lastIndex = firstIndex
|
|
if result {
|
|
return true
|
|
}
|
|
}
|
|
lastRune = wordRunes[0]
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ContainsAnyWord 检查字符串是否包含任一单词
|
|
func ContainsAnyWord(s string, words []string, isCaseInsensitive bool) bool {
|
|
var allRunes = []rune(s)
|
|
if len(allRunes) == 0 || len(words) == 0 {
|
|
return false
|
|
}
|
|
|
|
var lastRune rune // last searching rune in s
|
|
var lastIndex = -2 // -2: not started, -1: not found, >=0: rune index
|
|
for _, word := range words {
|
|
var wordRunes = []rune(word)
|
|
if len(wordRunes) == 0 {
|
|
continue
|
|
}
|
|
|
|
if lastIndex > -2 && lastRune == wordRunes[0] {
|
|
if lastIndex >= 0 {
|
|
result, _ := ContainsWordRunes(allRunes[lastIndex:], wordRunes, isCaseInsensitive)
|
|
if result {
|
|
return true
|
|
}
|
|
}
|
|
continue
|
|
} else {
|
|
result, firstIndex := ContainsWordRunes(allRunes, wordRunes, isCaseInsensitive)
|
|
lastIndex = firstIndex
|
|
if result {
|
|
return true
|
|
}
|
|
}
|
|
lastRune = wordRunes[0]
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ContainsAllWords 检查字符串是否包含所有单词
|
|
func ContainsAllWords(s string, words []string, isCaseInsensitive bool) bool {
|
|
var allRunes = []rune(s)
|
|
if len(allRunes) == 0 || len(words) == 0 {
|
|
return false
|
|
}
|
|
|
|
for _, word := range words {
|
|
if result, _ := ContainsWordRunes(allRunes, []rune(word), isCaseInsensitive); !result {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ContainsWordRunes 检查字符列表是否包含某个单词子字符列表
|
|
func ContainsWordRunes(allRunes []rune, subRunes []rune, isCaseInsensitive bool) (result bool, firstIndex int) {
|
|
firstIndex = -1
|
|
|
|
var l = len(subRunes)
|
|
if l == 0 {
|
|
return false, 0
|
|
}
|
|
|
|
var al = len(allRunes)
|
|
|
|
for index, r := range allRunes {
|
|
if EqualRune(r, subRunes[0], isCaseInsensitive) && (index == 0 || !isChar(allRunes[index-1]) /**boundary check **/) {
|
|
if firstIndex < 0 {
|
|
firstIndex = index
|
|
}
|
|
|
|
var found = true
|
|
if l > 1 {
|
|
for i := 1; i < l; i++ {
|
|
var subIndex = index + i
|
|
if subIndex > al-1 || !EqualRune(allRunes[subIndex], subRunes[i], isCaseInsensitive) {
|
|
found = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// check after charset
|
|
if found && (al <= index+l || !isChar(allRunes[index+l]) /**boundary check **/) {
|
|
return true, firstIndex
|
|
}
|
|
}
|
|
}
|
|
|
|
return false, firstIndex
|
|
}
|
|
|
|
// ContainsSubRunes 检查字符列表是否包含某个子子字符列表
|
|
// 与 ContainsWordRunes 不同,这里不需要检查边界符号
|
|
func ContainsSubRunes(allRunes []rune, subRunes []rune, isCaseInsensitive bool) bool {
|
|
var l = len(subRunes)
|
|
if l == 0 {
|
|
return false
|
|
}
|
|
|
|
var al = len(allRunes)
|
|
|
|
for index, r := range allRunes {
|
|
if EqualRune(r, subRunes[0], isCaseInsensitive) {
|
|
var found = true
|
|
if l > 1 {
|
|
for i := 1; i < l; i++ {
|
|
var subIndex = index + i
|
|
if subIndex > al-1 || !EqualRune(allRunes[subIndex], subRunes[i], isCaseInsensitive) {
|
|
found = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// check after charset
|
|
if found {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// EqualRune 判断两个rune是否相同
|
|
func EqualRune(r1 rune, r2 rune, isCaseInsensitive bool) bool {
|
|
const d = 'a' - 'A'
|
|
return r1 == r2 ||
|
|
(isCaseInsensitive && r1 >= 'a' && r1 <= 'z' && r1-r2 == d) ||
|
|
(isCaseInsensitive && r1 >= 'A' && r1 <= 'Z' && r1-r2 == -d)
|
|
}
|
|
|
|
func isChar(r rune) bool {
|
|
return r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9'
|
|
}
|