forked from p30928647/excelize
Optimizing regexp calls to improve performance (#1532)
This commit is contained in:
parent
63d8a09082
commit
787453c6f0
50
calc.go
50
calc.go
|
@ -193,6 +193,24 @@ var (
|
||||||
return fmt.Sprintf("R[%d]C[%d]", row, col), nil
|
return fmt.Sprintf("R[%d]C[%d]", row, col), nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
formularFormats = []*regexp.Regexp{
|
||||||
|
regexp.MustCompile(`^(\d+)$`),
|
||||||
|
regexp.MustCompile(`^=(.*)$`),
|
||||||
|
regexp.MustCompile(`^<>(.*)$`),
|
||||||
|
regexp.MustCompile(`^<=(.*)$`),
|
||||||
|
regexp.MustCompile(`^>=(.*)$`),
|
||||||
|
regexp.MustCompile(`^<(.*)$`),
|
||||||
|
regexp.MustCompile(`^>(.*)$`),
|
||||||
|
}
|
||||||
|
formularCriterias = []byte{
|
||||||
|
criteriaEq,
|
||||||
|
criteriaEq,
|
||||||
|
criteriaNe,
|
||||||
|
criteriaLe,
|
||||||
|
criteriaGe,
|
||||||
|
criteriaL,
|
||||||
|
criteriaG,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// calcContext defines the formula execution context.
|
// calcContext defines the formula execution context.
|
||||||
|
@ -1654,33 +1672,11 @@ func formulaCriteriaParser(exp string) (fc *formulaCriteria) {
|
||||||
if exp == "" {
|
if exp == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if match := regexp.MustCompile(`^(\d+)$`).FindStringSubmatch(exp); len(match) > 1 {
|
for i, re := range formularFormats {
|
||||||
fc.Type, fc.Condition = criteriaEq, match[1]
|
if match := re.FindStringSubmatch(exp); len(match) > 1 {
|
||||||
return
|
fc.Type, fc.Condition = formularCriterias[i], match[1]
|
||||||
}
|
return
|
||||||
if match := regexp.MustCompile(`^=(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
}
|
||||||
fc.Type, fc.Condition = criteriaEq, match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if match := regexp.MustCompile(`^<>(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
|
||||||
fc.Type, fc.Condition = criteriaNe, match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if match := regexp.MustCompile(`^<=(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
|
||||||
fc.Type, fc.Condition = criteriaLe, match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if match := regexp.MustCompile(`^>=(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
|
||||||
fc.Type, fc.Condition = criteriaGe, match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if match := regexp.MustCompile(`^<(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
|
||||||
fc.Type, fc.Condition = criteriaL, match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if match := regexp.MustCompile(`^>(.*)$`).FindStringSubmatch(exp); len(match) > 1 {
|
|
||||||
fc.Type, fc.Condition = criteriaG, match[1]
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if strings.Contains(exp, "?") {
|
if strings.Contains(exp, "?") {
|
||||||
exp = strings.ReplaceAll(exp, "?", ".")
|
exp = strings.ReplaceAll(exp, "?", ".")
|
||||||
|
|
2
sheet.go
2
sheet.go
|
@ -977,6 +977,7 @@ func (f *File) searchSheet(name, value string, regSearch bool) (result []string,
|
||||||
if sst, err = f.sharedStringsReader(); err != nil {
|
if sst, err = f.sharedStringsReader(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
regex := regexp.MustCompile(value)
|
||||||
decoder := f.xmlNewDecoder(bytes.NewReader(f.readBytes(name)))
|
decoder := f.xmlNewDecoder(bytes.NewReader(f.readBytes(name)))
|
||||||
for {
|
for {
|
||||||
var token xml.Token
|
var token xml.Token
|
||||||
|
@ -1001,7 +1002,6 @@ func (f *File) searchSheet(name, value string, regSearch bool) (result []string,
|
||||||
_ = decoder.DecodeElement(&colCell, &xmlElement)
|
_ = decoder.DecodeElement(&colCell, &xmlElement)
|
||||||
val, _ := colCell.getValueFrom(f, sst, false)
|
val, _ := colCell.getValueFrom(f, sst, false)
|
||||||
if regSearch {
|
if regSearch {
|
||||||
regex := regexp.MustCompile(value)
|
|
||||||
if !regex.MatchString(val) {
|
if !regex.MatchString(val) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
17
table.go
17
table.go
|
@ -23,6 +23,13 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
expressionFormat = regexp.MustCompile(`"(?:[^"]|"")*"|\S+`)
|
||||||
|
conditionFormat = regexp.MustCompile(`(or|\|\|)`)
|
||||||
|
blankFormat = regexp.MustCompile("blanks|nonblanks")
|
||||||
|
matchFormat = regexp.MustCompile("[*?]")
|
||||||
|
)
|
||||||
|
|
||||||
// parseTableOptions provides a function to parse the format settings of the
|
// parseTableOptions provides a function to parse the format settings of the
|
||||||
// table with default value.
|
// table with default value.
|
||||||
func parseTableOptions(opts *Table) (*Table, error) {
|
func parseTableOptions(opts *Table) (*Table, error) {
|
||||||
|
@ -400,8 +407,7 @@ func (f *File) autoFilter(sheet, ref string, columns, col int, opts []AutoFilter
|
||||||
return fmt.Errorf("incorrect index of column '%s'", opt.Column)
|
return fmt.Errorf("incorrect index of column '%s'", opt.Column)
|
||||||
}
|
}
|
||||||
fc := &xlsxFilterColumn{ColID: offset}
|
fc := &xlsxFilterColumn{ColID: offset}
|
||||||
re := regexp.MustCompile(`"(?:[^"]|"")*"|\S+`)
|
token := expressionFormat.FindAllString(opt.Expression, -1)
|
||||||
token := re.FindAllString(opt.Expression, -1)
|
|
||||||
if len(token) != 3 && len(token) != 7 {
|
if len(token) != 3 && len(token) != 7 {
|
||||||
return fmt.Errorf("incorrect number of tokens in criteria '%s'", opt.Expression)
|
return fmt.Errorf("incorrect number of tokens in criteria '%s'", opt.Expression)
|
||||||
}
|
}
|
||||||
|
@ -484,8 +490,7 @@ func (f *File) parseFilterExpression(expression string, tokens []string) ([]int,
|
||||||
// expressions).
|
// expressions).
|
||||||
conditional := 0
|
conditional := 0
|
||||||
c := tokens[3]
|
c := tokens[3]
|
||||||
re, _ := regexp.Match(`(or|\|\|)`, []byte(c))
|
if conditionFormat.Match([]byte(c)) {
|
||||||
if re {
|
|
||||||
conditional = 1
|
conditional = 1
|
||||||
}
|
}
|
||||||
expression1, token1, err := f.parseFilterTokens(expression, tokens[:3])
|
expression1, token1, err := f.parseFilterTokens(expression, tokens[:3])
|
||||||
|
@ -533,7 +538,7 @@ func (f *File) parseFilterTokens(expression string, tokens []string) ([]int, str
|
||||||
}
|
}
|
||||||
token := tokens[2]
|
token := tokens[2]
|
||||||
// Special handling for Blanks/NonBlanks.
|
// Special handling for Blanks/NonBlanks.
|
||||||
re, _ := regexp.Match("blanks|nonblanks", []byte(strings.ToLower(token)))
|
re := blankFormat.Match([]byte(strings.ToLower(token)))
|
||||||
if re {
|
if re {
|
||||||
// Only allow Equals or NotEqual in this context.
|
// Only allow Equals or NotEqual in this context.
|
||||||
if operator != 2 && operator != 5 {
|
if operator != 2 && operator != 5 {
|
||||||
|
@ -558,7 +563,7 @@ func (f *File) parseFilterTokens(expression string, tokens []string) ([]int, str
|
||||||
}
|
}
|
||||||
// If the string token contains an Excel match character then change the
|
// If the string token contains an Excel match character then change the
|
||||||
// operator type to indicate a non "simple" equality.
|
// operator type to indicate a non "simple" equality.
|
||||||
re, _ = regexp.Match("[*?]", []byte(token))
|
re = matchFormat.Match([]byte(token))
|
||||||
if operator == 2 && re {
|
if operator == 2 && re {
|
||||||
operator = 22
|
operator = 22
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue