diff --git a/go.mod b/go.mod index 8a9903dfa110..20dde38ea42d 100644 --- a/go.mod +++ b/go.mod @@ -381,7 +381,7 @@ exclude k8s.io/client-go v8.0.0+incompatible replace github.com/hashicorp/memberlist => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe // Insist on the optimised version of grafana/regexp -replace github.com/grafana/regexp => github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd +replace github.com/grafana/regexp => github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc replace github.com/grafana/loki/pkg/push => ./pkg/push diff --git a/go.sum b/go.sum index 502a8d2f15da..76b72595a521 100644 --- a/go.sum +++ b/go.sum @@ -1049,8 +1049,8 @@ github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe h1:yIXAAbLswn github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grafana/tail v0.0.0-20230510142333-77b18831edf0 h1:bjh0PVYSVVFxzINqPFYJmAmJNrWPgnVjuSdYJGHmtFU= github.com/grafana/tail v0.0.0-20230510142333-77b18831edf0/go.mod h1:7t5XR+2IA8P2qggOAHTj/GCZfoLBle3OvNSYh1VkRBU= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= diff --git a/vendor/github.com/grafana/regexp/backtrack.go b/vendor/github.com/grafana/regexp/backtrack.go index 0739f5ff5886..7c37c66a80c7 100644 --- a/vendor/github.com/grafana/regexp/backtrack.go +++ b/vendor/github.com/grafana/regexp/backtrack.go @@ -91,9 +91,7 @@ func (b *bitState) reset(prog *syntax.Prog, end int, ncap int) { b.visited = make([]uint32, visitedSize, maxBacktrackVector/visitedBits) } else { b.visited = b.visited[:visitedSize] - for i := range b.visited { - b.visited[i] = 0 - } + clear(b.visited) // set to 0 } if cap(b.cap) < ncap { diff --git a/vendor/github.com/grafana/regexp/onepass.go b/vendor/github.com/grafana/regexp/onepass.go index bc47f4c4a830..53cbd9583941 100644 --- a/vendor/github.com/grafana/regexp/onepass.go +++ b/vendor/github.com/grafana/regexp/onepass.go @@ -6,7 +6,7 @@ package regexp import ( "regexp/syntax" - "sort" + "slices" "strings" "unicode" "unicode/utf8" @@ -33,11 +33,11 @@ type onePassInst struct { Next []uint32 } -// OnePassPrefix returns a literal string that all matches for the +// onePassPrefix returns a literal string that all matches for the // regexp must start with. Complete is true if the prefix // is the entire match. Pc is the index of the last rune instruction -// in the string. The OnePassPrefix skips over the mandatory -// EmptyBeginText +// in the string. The onePassPrefix skips over the mandatory +// EmptyBeginText. func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) { i := &p.Inst[p.Start] if i.Op != syntax.InstEmptyWidth || (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText == 0 { @@ -68,7 +68,7 @@ func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) { return buf.String(), complete, pc } -// OnePassNext selects the next actionable state of the prog, based on the input character. +// onePassNext selects the next actionable state of the prog, based on the input character. // It should only be called when i.Op == InstAlt or InstAltMatch, and from the one-pass machine. // One of the alternates may ultimately lead without input to end of line. If the instruction // is InstAltMatch the path to the InstMatch is in i.Out, the normal node in i.Next. @@ -218,7 +218,7 @@ func cleanupOnePass(prog *onePassProg, original *syntax.Prog) { } } -// onePassCopy creates a copy of the original Prog, as we'll be modifying it +// onePassCopy creates a copy of the original Prog, as we'll be modifying it. func onePassCopy(prog *syntax.Prog) *onePassProg { p := &onePassProg{ Start: prog.Start, @@ -282,13 +282,6 @@ func onePassCopy(prog *syntax.Prog) *onePassProg { return p } -// runeSlice exists to permit sorting the case-folded rune sets. -type runeSlice []rune - -func (p runeSlice) Len() int { return len(p) } -func (p runeSlice) Less(i, j int) bool { return p[i] < p[j] } -func (p runeSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune} var anyRune = []rune{0, unicode.MaxRune} @@ -383,7 +376,7 @@ func makeOnePass(p *onePassProg) *onePassProg { for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) { runes = append(runes, r1, r1) } - sort.Sort(runeSlice(runes)) + slices.Sort(runes) } else { runes = append(runes, inst.Rune...) } @@ -407,7 +400,7 @@ func makeOnePass(p *onePassProg) *onePassProg { for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) { runes = append(runes, r1, r1) } - sort.Sort(runeSlice(runes)) + slices.Sort(runes) } else { runes = append(runes, inst.Rune[0], inst.Rune[0]) } diff --git a/vendor/github.com/grafana/regexp/regexp.go b/vendor/github.com/grafana/regexp/regexp.go index 7958a397285d..d1218ad0e872 100644 --- a/vendor/github.com/grafana/regexp/regexp.go +++ b/vendor/github.com/grafana/regexp/regexp.go @@ -8,9 +8,7 @@ // general syntax used by Perl, Python, and other languages. // More precisely, it is the syntax accepted by RE2 and described at // https://golang.org/s/re2syntax, except for \C. -// For an overview of the syntax, run -// -// go doc regexp/syntax +// For an overview of the syntax, see the [regexp/syntax] package. // // The regexp implementation provided by this package is // guaranteed to run in time linear in the size of the input. @@ -23,10 +21,10 @@ // or any book about automata theory. // // All characters are UTF-8-encoded code points. -// Following utf8.DecodeRune, each byte of an invalid UTF-8 sequence +// Following [utf8.DecodeRune], each byte of an invalid UTF-8 sequence // is treated as if it encoded utf8.RuneError (U+FFFD). // -// There are 16 methods of Regexp that match a regular expression and identify +// There are 16 methods of [Regexp] that match a regular expression and identify // the matched text. Their names are matched by this regular expression: // // Find(All)?(String)?(Submatch)?(Index)? @@ -82,7 +80,7 @@ import ( // Regexp is the representation of a compiled regular expression. // A Regexp is safe for concurrent use by multiple goroutines, -// except for configuration methods, such as Longest. +// except for configuration methods, such as [Regexp.Longest]. type Regexp struct { expr string // as passed to Compile prog *syntax.Prog // compiled program @@ -110,21 +108,21 @@ func (re *Regexp) String() string { return re.expr } -// Copy returns a new Regexp object copied from re. -// Calling Longest on one copy does not affect another. +// Copy returns a new [Regexp] object copied from re. +// Calling [Regexp.Longest] on one copy does not affect another. // -// Deprecated: In earlier releases, when using a Regexp in multiple goroutines, +// Deprecated: In earlier releases, when using a [Regexp] in multiple goroutines, // giving each goroutine its own copy helped to avoid lock contention. // As of Go 1.12, using Copy is no longer necessary to avoid lock contention. // Copy may still be appropriate if the reason for its use is to make -// two copies with different Longest settings. +// two copies with different [Regexp.Longest] settings. func (re *Regexp) Copy() *Regexp { re2 := *re return &re2 } // Compile parses a regular expression and returns, if successful, -// a Regexp object that can be used to match against text. +// a [Regexp] object that can be used to match against text. // // When matching against text, the regexp returns a match that // begins as early as possible in the input (leftmost), and among those @@ -132,12 +130,12 @@ func (re *Regexp) Copy() *Regexp { // This so-called leftmost-first matching is the same semantics // that Perl, Python, and other implementations use, although this // package implements it without the expense of backtracking. -// For POSIX leftmost-longest matching, see CompilePOSIX. +// For POSIX leftmost-longest matching, see [CompilePOSIX]. func Compile(expr string) (*Regexp, error) { return compile(expr, syntax.Perl, false) } -// CompilePOSIX is like Compile but restricts the regular expression +// CompilePOSIX is like [Compile] but restricts the regular expression // to POSIX ERE (egrep) syntax and changes the match semantics to // leftmost-longest. // @@ -164,7 +162,7 @@ func CompilePOSIX(expr string) (*Regexp, error) { // That is, when matching against text, the regexp returns a match that // begins as early as possible in the input (leftmost), and among those // it chooses a match that is as long as possible. -// This method modifies the Regexp and may not be called concurrently +// This method modifies the [Regexp] and may not be called concurrently // with any other methods. func (re *Regexp) Longest() { re.longest = true @@ -270,7 +268,7 @@ func (re *Regexp) put(m *machine) { matchPool[re.mpool].Put(m) } -// minInputLen walks the regexp to find the minimum length of any matchable input +// minInputLen walks the regexp to find the minimum length of any matchable input. func minInputLen(re *syntax.Regexp) int { switch re.Op { default: @@ -310,7 +308,7 @@ func minInputLen(re *syntax.Regexp) int { } } -// MustCompile is like Compile but panics if the expression cannot be parsed. +// MustCompile is like [Compile] but panics if the expression cannot be parsed. // It simplifies safe initialization of global variables holding compiled regular // expressions. func MustCompile(str string) *Regexp { @@ -321,7 +319,7 @@ func MustCompile(str string) *Regexp { return regexp } -// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed. +// MustCompilePOSIX is like [CompilePOSIX] but panics if the expression cannot be parsed. // It simplifies safe initialization of global variables holding compiled regular // expressions. func MustCompilePOSIX(str string) *Regexp { @@ -339,13 +337,13 @@ func quote(s string) string { return strconv.Quote(s) } -// NumSubexp returns the number of parenthesized subexpressions in this Regexp. +// NumSubexp returns the number of parenthesized subexpressions in this [Regexp]. func (re *Regexp) NumSubexp() int { return re.numSubexp } // SubexpNames returns the names of the parenthesized subexpressions -// in this Regexp. The name for the first sub-expression is names[1], +// in this [Regexp]. The name for the first sub-expression is names[1], // so that if m is a match slice, the name for m[i] is SubexpNames()[i]. // Since the Regexp as a whole cannot be named, names[0] is always // the empty string. The slice should not be modified. @@ -521,7 +519,7 @@ func (re *Regexp) LiteralPrefix() (prefix string, complete bool) { return re.prefix, re.prefixComplete } -// MatchReader reports whether the text returned by the RuneReader +// MatchReader reports whether the text returned by the [io.RuneReader] // contains any match of the regular expression re. func (re *Regexp) MatchReader(r io.RuneReader) bool { return re.doMatch(r, nil, "") @@ -541,7 +539,7 @@ func (re *Regexp) Match(b []byte) bool { // MatchReader reports whether the text returned by the RuneReader // contains any match of the regular expression pattern. -// More complicated queries need to use Compile and the full Regexp interface. +// More complicated queries need to use [Compile] and the full [Regexp] interface. func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) { re, err := Compile(pattern) if err != nil { @@ -552,7 +550,7 @@ func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) { // MatchString reports whether the string s // contains any match of the regular expression pattern. -// More complicated queries need to use Compile and the full Regexp interface. +// More complicated queries need to use [Compile] and the full [Regexp] interface. func MatchString(pattern string, s string) (matched bool, err error) { re, err := Compile(pattern) if err != nil { @@ -563,7 +561,7 @@ func MatchString(pattern string, s string) (matched bool, err error) { // Match reports whether the byte slice b // contains any match of the regular expression pattern. -// More complicated queries need to use Compile and the full Regexp interface. +// More complicated queries need to use [Compile] and the full [Regexp] interface. func Match(pattern string, b []byte) (matched bool, err error) { re, err := Compile(pattern) if err != nil { @@ -572,9 +570,9 @@ func Match(pattern string, b []byte) (matched bool, err error) { return re.Match(b), nil } -// ReplaceAllString returns a copy of src, replacing matches of the Regexp -// with the replacement string repl. Inside repl, $ signs are interpreted as -// in Expand, so for instance $1 represents the text of the first submatch. +// ReplaceAllString returns a copy of src, replacing matches of the [Regexp] +// with the replacement string repl. +// Inside repl, $ signs are interpreted as in [Regexp.Expand]. func (re *Regexp) ReplaceAllString(src, repl string) string { n := 2 if strings.Contains(repl, "$") { @@ -586,9 +584,9 @@ func (re *Regexp) ReplaceAllString(src, repl string) string { return string(b) } -// ReplaceAllLiteralString returns a copy of src, replacing matches of the Regexp +// ReplaceAllLiteralString returns a copy of src, replacing matches of the [Regexp] // with the replacement string repl. The replacement repl is substituted directly, -// without using Expand. +// without using [Regexp.Expand]. func (re *Regexp) ReplaceAllLiteralString(src, repl string) string { return string(re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte { return append(dst, repl...) @@ -596,9 +594,9 @@ func (re *Regexp) ReplaceAllLiteralString(src, repl string) string { } // ReplaceAllStringFunc returns a copy of src in which all matches of the -// Regexp have been replaced by the return value of function repl applied +// [Regexp] have been replaced by the return value of function repl applied // to the matched substring. The replacement returned by repl is substituted -// directly, without using Expand. +// directly, without using [Regexp.Expand]. func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { b := re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte { return append(dst, repl(src[match[0]:match[1]])...) @@ -671,9 +669,9 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst return buf } -// ReplaceAll returns a copy of src, replacing matches of the Regexp -// with the replacement text repl. Inside repl, $ signs are interpreted as -// in Expand, so for instance $1 represents the text of the first submatch. +// ReplaceAll returns a copy of src, replacing matches of the [Regexp] +// with the replacement text repl. +// Inside repl, $ signs are interpreted as in [Regexp.Expand]. func (re *Regexp) ReplaceAll(src, repl []byte) []byte { n := 2 if bytes.IndexByte(repl, '$') >= 0 { @@ -689,9 +687,9 @@ func (re *Regexp) ReplaceAll(src, repl []byte) []byte { return b } -// ReplaceAllLiteral returns a copy of src, replacing matches of the Regexp +// ReplaceAllLiteral returns a copy of src, replacing matches of the [Regexp] // with the replacement bytes repl. The replacement repl is substituted directly, -// without using Expand. +// without using [Regexp.Expand]. func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte { return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte { return append(dst, repl...) @@ -699,9 +697,9 @@ func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte { } // ReplaceAllFunc returns a copy of src in which all matches of the -// Regexp have been replaced by the return value of function repl applied +// [Regexp] have been replaced by the return value of function repl applied // to the matched byte slice. The replacement returned by repl is substituted -// directly, without using Expand. +// directly, without using [Regexp.Expand]. func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte { return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte { return append(dst, repl(src[match[0]:match[1]])...) @@ -845,7 +843,7 @@ func (re *Regexp) FindIndex(b []byte) (loc []int) { // FindString returns a string holding the text of the leftmost match in s of the regular // expression. If there is no match, the return value is an empty string, // but it will also be empty if the regular expression successfully matches -// an empty string. Use FindStringIndex or FindStringSubmatch if it is +// an empty string. Use [Regexp.FindStringIndex] or [Regexp.FindStringSubmatch] if it is // necessary to distinguish these cases. func (re *Regexp) FindString(s string) string { var dstCap [2]int @@ -870,7 +868,7 @@ func (re *Regexp) FindStringIndex(s string) (loc []int) { // FindReaderIndex returns a two-element slice of integers defining the // location of the leftmost match of the regular expression in text read from -// the RuneReader. The match text was found in the input stream at +// the [io.RuneReader]. The match text was found in the input stream at // byte offset loc[0] through loc[1]-1. // A return value of nil indicates no match. func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) { @@ -904,7 +902,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte { // Expand appends template to dst and returns the result; during the // append, Expand replaces variables in the template with corresponding // matches drawn from src. The match slice should have been returned by -// FindSubmatchIndex. +// [Regexp.FindSubmatchIndex]. // // In the template, a variable is denoted by a substring of the form // $name or ${name}, where name is a non-empty sequence of letters, @@ -922,7 +920,7 @@ func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) [ return re.expand(dst, string(template), src, "", match) } -// ExpandString is like Expand but the template and source are strings. +// ExpandString is like [Regexp.Expand] but the template and source are strings. // It appends to and returns a byte slice in order to give the calling // code control over allocation. func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte { @@ -1067,7 +1065,7 @@ func (re *Regexp) FindStringSubmatchIndex(s string) []int { // FindReaderSubmatchIndex returns a slice holding the index pairs // identifying the leftmost match of the regular expression of text read by -// the RuneReader, and the matches, if any, of its subexpressions, as defined +// the [io.RuneReader], and the matches, if any, of its subexpressions, as defined // by the 'Submatch' and 'Index' descriptions in the package comment. A // return value of nil indicates no match. func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int { @@ -1076,7 +1074,7 @@ func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int { const startSize = 10 // The size at which to start a slice in the 'All' routines. -// FindAll is the 'All' version of Find; it returns a slice of all successive +// FindAll is the 'All' version of [Regexp.Find]; it returns a slice of all successive // matches of the expression, as defined by the 'All' description in the // package comment. // A return value of nil indicates no match. @@ -1094,7 +1092,7 @@ func (re *Regexp) FindAll(b []byte, n int) [][]byte { return result } -// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all +// FindAllIndex is the 'All' version of [Regexp.FindIndex]; it returns a slice of all // successive matches of the expression, as defined by the 'All' description // in the package comment. // A return value of nil indicates no match. @@ -1112,7 +1110,7 @@ func (re *Regexp) FindAllIndex(b []byte, n int) [][]int { return result } -// FindAllString is the 'All' version of FindString; it returns a slice of all +// FindAllString is the 'All' version of [Regexp.FindString]; it returns a slice of all // successive matches of the expression, as defined by the 'All' description // in the package comment. // A return value of nil indicates no match. @@ -1130,7 +1128,7 @@ func (re *Regexp) FindAllString(s string, n int) []string { return result } -// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a +// FindAllStringIndex is the 'All' version of [Regexp.FindStringIndex]; it returns a // slice of all successive matches of the expression, as defined by the 'All' // description in the package comment. // A return value of nil indicates no match. @@ -1148,7 +1146,7 @@ func (re *Regexp) FindAllStringIndex(s string, n int) [][]int { return result } -// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice +// FindAllSubmatch is the 'All' version of [Regexp.FindSubmatch]; it returns a slice // of all successive matches of the expression, as defined by the 'All' // description in the package comment. // A return value of nil indicates no match. @@ -1172,7 +1170,7 @@ func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte { return result } -// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns +// FindAllSubmatchIndex is the 'All' version of [Regexp.FindSubmatchIndex]; it returns // a slice of all successive matches of the expression, as defined by the // 'All' description in the package comment. // A return value of nil indicates no match. @@ -1190,7 +1188,7 @@ func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int { return result } -// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it +// FindAllStringSubmatch is the 'All' version of [Regexp.FindStringSubmatch]; it // returns a slice of all successive matches of the expression, as defined by // the 'All' description in the package comment. // A return value of nil indicates no match. @@ -1215,7 +1213,7 @@ func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string { } // FindAllStringSubmatchIndex is the 'All' version of -// FindStringSubmatchIndex; it returns a slice of all successive matches of +// [Regexp.FindStringSubmatchIndex]; it returns a slice of all successive matches of // the expression, as defined by the 'All' description in the package // comment. // A return value of nil indicates no match. @@ -1237,8 +1235,8 @@ func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int { // the substrings between those expression matches. // // The slice returned by this method consists of all the substrings of s -// not contained in the slice returned by FindAllString. When called on an expression -// that contains no metacharacters, it is equivalent to strings.SplitN. +// not contained in the slice returned by [Regexp.FindAllString]. When called on an expression +// that contains no metacharacters, it is equivalent to [strings.SplitN]. // // Example: // @@ -1283,3 +1281,24 @@ func (re *Regexp) Split(s string, n int) []string { return strings } + +// MarshalText implements [encoding.TextMarshaler]. The output +// matches that of calling the [Regexp.String] method. +// +// Note that the output is lossy in some cases: This method does not indicate +// POSIX regular expressions (i.e. those compiled by calling [CompilePOSIX]), or +// those for which the [Regexp.Longest] method has been called. +func (re *Regexp) MarshalText() ([]byte, error) { + return []byte(re.String()), nil +} + +// UnmarshalText implements [encoding.TextUnmarshaler] by calling +// [Compile] on the encoded value. +func (re *Regexp) UnmarshalText(text []byte) error { + newRE, err := Compile(string(text)) + if err != nil { + return err + } + *re = *newRE + return nil +} diff --git a/vendor/github.com/grafana/regexp/syntax/doc.go b/vendor/github.com/grafana/regexp/syntax/doc.go index f6a4b43f7aeb..877f1043ddda 100644 --- a/vendor/github.com/grafana/regexp/syntax/doc.go +++ b/vendor/github.com/grafana/regexp/syntax/doc.go @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution. +// Code generated by mksyntaxgo from the RE2 distribution. DO NOT EDIT. /* Package syntax parses regular expressions into parse trees and compiles parse trees into programs. Most clients of regular expressions will use the -facilities of package regexp (such as Compile and Match) instead of this package. +facilities of package [regexp] (such as [regexp.Compile] and [regexp.Match]) instead of this package. # Syntax -The regular expression syntax understood by this package when parsing with the Perl flag is as follows. -Parts of the syntax can be disabled by passing alternate flags to Parse. +The regular expression syntax understood by this package when parsing with the [Perl] flag is as follows. +Parts of the syntax can be disabled by passing alternate flags to [Parse]. Single characters: @@ -56,6 +56,7 @@ Grouping: (re) numbered capturing group (submatch) (?Pre) named & numbered capturing group (submatch) + (?re) named & numbered capturing group (submatch) (?:re) non-capturing group (?flags) set flags within current group; non-capturing (?flags:re) set flags during re; non-capturing @@ -136,6 +137,6 @@ ASCII character classes: [[:word:]] word characters (== [0-9A-Za-z_]) [[:xdigit:]] hex digit (== [0-9A-Fa-f]) -Unicode character classes are those in unicode.Categories and unicode.Scripts. +Unicode character classes are those in [unicode.Categories] and [unicode.Scripts]. */ package syntax diff --git a/vendor/github.com/grafana/regexp/syntax/op_string.go b/vendor/github.com/grafana/regexp/syntax/op_string.go index 3952b2bdd5f5..1368f5b7ea46 100644 --- a/vendor/github.com/grafana/regexp/syntax/op_string.go +++ b/vendor/github.com/grafana/regexp/syntax/op_string.go @@ -4,6 +4,32 @@ package syntax import "strconv" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[OpNoMatch-1] + _ = x[OpEmptyMatch-2] + _ = x[OpLiteral-3] + _ = x[OpCharClass-4] + _ = x[OpAnyCharNotNL-5] + _ = x[OpAnyChar-6] + _ = x[OpBeginLine-7] + _ = x[OpEndLine-8] + _ = x[OpBeginText-9] + _ = x[OpEndText-10] + _ = x[OpWordBoundary-11] + _ = x[OpNoWordBoundary-12] + _ = x[OpCapture-13] + _ = x[OpStar-14] + _ = x[OpPlus-15] + _ = x[OpQuest-16] + _ = x[OpRepeat-17] + _ = x[OpConcat-18] + _ = x[OpAlternate-19] + _ = x[opPseudo-128] +} + const ( _Op_name_0 = "NoMatchEmptyMatchLiteralCharClassAnyCharNotNLAnyCharBeginLineEndLineBeginTextEndTextWordBoundaryNoWordBoundaryCaptureStarPlusQuestRepeatConcatAlternate" _Op_name_1 = "opPseudo" diff --git a/vendor/github.com/grafana/regexp/syntax/parse.go b/vendor/github.com/grafana/regexp/syntax/parse.go index b6d348d00cd8..6ed6491c807a 100644 --- a/vendor/github.com/grafana/regexp/syntax/parse.go +++ b/vendor/github.com/grafana/regexp/syntax/parse.go @@ -44,6 +44,7 @@ const ( ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression" ErrUnexpectedParen ErrorCode = "unexpected )" ErrNestingDepth ErrorCode = "expression nests too deeply" + ErrLarge ErrorCode = "expression too large" ) func (e ErrorCode) String() string { @@ -159,7 +160,7 @@ func (p *parser) reuse(re *Regexp) { func (p *parser) checkLimits(re *Regexp) { if p.numRunes > maxRunes { - panic(ErrInternalError) + panic(ErrLarge) } p.checkSize(re) p.checkHeight(re) @@ -203,7 +204,7 @@ func (p *parser) checkSize(re *Regexp) { } if p.calcSize(re, true) > maxSize { - panic(ErrInternalError) + panic(ErrLarge) } } @@ -248,9 +249,7 @@ func (p *parser) calcSize(re *Regexp, force bool) int64 { size = int64(re.Max)*sub + int64(re.Max-re.Min) } - if size < 1 { - size = 1 - } + size = max(1, size) p.size[re] = size return size } @@ -381,14 +380,12 @@ func minFoldRune(r rune) rune { if r < minFold || r > maxFold { return r } - min := r + m := r r0 := r for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) { - if min > r { - min = r - } + m = min(m, r) } - return min + return m } // op pushes a regexp with the given op onto the stack @@ -897,8 +894,8 @@ func parse(s string, flags Flags) (_ *Regexp, err error) { panic(r) case nil: // ok - case ErrInternalError: // too big - err = &Error{Code: ErrInternalError, Expr: s} + case ErrLarge: // too big + err = &Error{Code: ErrLarge, Expr: s} case ErrNestingDepth: err = &Error{Code: ErrNestingDepth, Expr: s} } @@ -1158,9 +1155,18 @@ func (p *parser) parsePerlFlags(s string) (rest string, err error) { // support all three as well. EcmaScript 4 uses only the Python form. // // In both the open source world (via Code Search) and the - // Google source tree, (?Pname) is the dominant form, - // so that's the one we implement. One is enough. - if len(t) > 4 && t[2] == 'P' && t[3] == '<' { + // Google source tree, (?Pname) and (?name) are the + // dominant forms of named captures and both are supported. + startsWithP := len(t) > 4 && t[2] == 'P' && t[3] == '<' + startsWithName := len(t) > 3 && t[2] == '<' + + if startsWithP || startsWithName { + // position of expr start + exprStartPos := 4 + if startsWithName { + exprStartPos = 3 + } + // Pull out name. end := strings.IndexRune(t, '>') if end < 0 { @@ -1170,8 +1176,8 @@ func (p *parser) parsePerlFlags(s string) (rest string, err error) { return "", &Error{ErrInvalidNamedCapture, s} } - capture := t[:end+1] // "(?P" - name := t[4:end] // "name" + capture := t[:end+1] // "(?P" or "(?" + name := t[exprStartPos:end] // "name" if err = checkUTF8(name); err != nil { return "", err } @@ -1853,6 +1859,22 @@ func cleanClass(rp *[]rune) []rune { return r[:w] } +// inCharClass reports whether r is in the class. +// It assumes the class has been cleaned by cleanClass. +func inCharClass(r rune, class []rune) bool { + _, ok := sort.Find(len(class)/2, func(i int) int { + lo, hi := class[2*i], class[2*i+1] + if r > hi { + return +1 + } + if r < lo { + return -1 + } + return 0 + }) + return ok +} + // appendLiteral returns the result of appending the literal x to the class r. func appendLiteral(r []rune, x rune, flags Flags) []rune { if flags&FoldCase != 0 { @@ -1937,7 +1959,7 @@ func appendClass(r []rune, x []rune) []rune { return r } -// appendFolded returns the result of appending the case folding of the class x to the class r. +// appendFoldedClass returns the result of appending the case folding of the class x to the class r. func appendFoldedClass(r []rune, x []rune) []rune { for i := 0; i < len(x); i += 2 { r = appendFoldedRange(r, x[i], x[i+1]) diff --git a/vendor/github.com/grafana/regexp/syntax/prog.go b/vendor/github.com/grafana/regexp/syntax/prog.go index 896cdc42c2a4..6a3705ec8f90 100644 --- a/vendor/github.com/grafana/regexp/syntax/prog.go +++ b/vendor/github.com/grafana/regexp/syntax/prog.go @@ -106,7 +106,9 @@ func EmptyOpContext(r1, r2 rune) EmptyOp { // during the evaluation of the \b and \B zero-width assertions. // These assertions are ASCII-only: the word characters are [A-Za-z0-9_]. func IsWordChar(r rune) bool { - return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_' + // Test for lowercase letters first, as these occur more + // frequently than uppercase letters in common cases. + return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' || r == '_' } // An Inst is a single instruction in a regular expression program. @@ -189,7 +191,7 @@ Loop: const noMatch = -1 // MatchRune reports whether the instruction matches (and consumes) r. -// It should only be called when i.Op == InstRune. +// It should only be called when i.Op == [InstRune]. func (i *Inst) MatchRune(r rune) bool { return i.MatchRunePos(r) != noMatch } @@ -198,7 +200,7 @@ func (i *Inst) MatchRune(r rune) bool { // If so, MatchRunePos returns the index of the matching rune pair // (or, when len(i.Rune) == 1, rune singleton). // If not, MatchRunePos returns -1. -// MatchRunePos should only be called when i.Op == InstRune. +// MatchRunePos should only be called when i.Op == [InstRune]. func (i *Inst) MatchRunePos(r rune) int { rune := i.Rune @@ -245,7 +247,7 @@ func (i *Inst) MatchRunePos(r rune) int { lo := 0 hi := len(rune) / 2 for lo < hi { - m := lo + (hi-lo)/2 + m := int(uint(lo+hi) >> 1) if c := rune[2*m]; c <= r { if r <= rune[2*m+1] { return m @@ -260,7 +262,7 @@ func (i *Inst) MatchRunePos(r rune) int { // MatchEmptyWidth reports whether the instruction matches // an empty string between the runes before and after. -// It should only be called when i.Op == InstEmptyWidth. +// It should only be called when i.Op == [InstEmptyWidth]. func (i *Inst) MatchEmptyWidth(before rune, after rune) bool { switch EmptyOp(i.Arg) { case EmptyBeginLine: diff --git a/vendor/github.com/grafana/regexp/syntax/regexp.go b/vendor/github.com/grafana/regexp/syntax/regexp.go index 3a4d2d201cd4..8ad3653abba3 100644 --- a/vendor/github.com/grafana/regexp/syntax/regexp.go +++ b/vendor/github.com/grafana/regexp/syntax/regexp.go @@ -8,6 +8,7 @@ package syntax // In this package, re is always a *Regexp and r is always a rune. import ( + "slices" "strconv" "strings" "unicode" @@ -75,24 +76,10 @@ func (x *Regexp) Equal(y *Regexp) bool { } case OpLiteral, OpCharClass: - if len(x.Rune) != len(y.Rune) { - return false - } - for i, r := range x.Rune { - if r != y.Rune[i] { - return false - } - } + return slices.Equal(x.Rune, y.Rune) case OpAlternate, OpConcat: - if len(x.Sub) != len(y.Sub) { - return false - } - for i, sub := range x.Sub { - if !sub.Equal(y.Sub[i]) { - return false - } - } + return slices.EqualFunc(x.Sub, y.Sub, func(a, b *Regexp) bool { return a.Equal(b) }) case OpStar, OpPlus, OpQuest: if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) { @@ -112,8 +99,165 @@ func (x *Regexp) Equal(y *Regexp) bool { return true } +// printFlags is a bit set indicating which flags (including non-capturing parens) to print around a regexp. +type printFlags uint8 + +const ( + flagI printFlags = 1 << iota // (?i: + flagM // (?m: + flagS // (?s: + flagOff // ) + flagPrec // (?: ) + negShift = 5 // flagI<") @@ -122,15 +266,9 @@ func writeRegexp(b *strings.Builder, re *Regexp) { case OpEmptyMatch: b.WriteString(`(?:)`) case OpLiteral: - if re.Flags&FoldCase != 0 { - b.WriteString(`(?i:`) - } for _, r := range re.Rune { escape(b, r, false) } - if re.Flags&FoldCase != 0 { - b.WriteString(`)`) - } case OpCharClass: if len(re.Rune)%2 != 0 { b.WriteString(`[invalid char class]`) @@ -147,7 +285,9 @@ func writeRegexp(b *strings.Builder, re *Regexp) { lo, hi := re.Rune[i]+1, re.Rune[i+1]-1 escape(b, lo, lo == '-') if lo != hi { - b.WriteRune('-') + if hi != lo+1 { + b.WriteRune('-') + } escape(b, hi, hi == '-') } } @@ -156,25 +296,25 @@ func writeRegexp(b *strings.Builder, re *Regexp) { lo, hi := re.Rune[i], re.Rune[i+1] escape(b, lo, lo == '-') if lo != hi { - b.WriteRune('-') + if hi != lo+1 { + b.WriteRune('-') + } escape(b, hi, hi == '-') } } } b.WriteRune(']') - case OpAnyCharNotNL: - b.WriteString(`(?-s:.)`) - case OpAnyChar: - b.WriteString(`(?s:.)`) + case OpAnyCharNotNL, OpAnyChar: + b.WriteString(`.`) case OpBeginLine: - b.WriteString(`(?m:^)`) + b.WriteString(`^`) case OpEndLine: - b.WriteString(`(?m:$)`) + b.WriteString(`$`) case OpBeginText: b.WriteString(`\A`) case OpEndText: if re.Flags&WasDollar != 0 { - b.WriteString(`(?-m:$)`) + b.WriteString(`$`) } else { b.WriteString(`\z`) } @@ -191,17 +331,17 @@ func writeRegexp(b *strings.Builder, re *Regexp) { b.WriteRune('(') } if re.Sub[0].Op != OpEmptyMatch { - writeRegexp(b, re.Sub[0]) + writeRegexp(b, re.Sub[0], flags[re.Sub[0]], flags) } b.WriteRune(')') case OpStar, OpPlus, OpQuest, OpRepeat: - if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 { - b.WriteString(`(?:`) - writeRegexp(b, sub) - b.WriteString(`)`) - } else { - writeRegexp(b, sub) + p := printFlags(0) + sub := re.Sub[0] + if sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 { + p = flagPrec } + writeRegexp(b, sub, p, flags) + switch re.Op { case OpStar: b.WriteRune('*') @@ -225,27 +365,31 @@ func writeRegexp(b *strings.Builder, re *Regexp) { } case OpConcat: for _, sub := range re.Sub { + p := printFlags(0) if sub.Op == OpAlternate { - b.WriteString(`(?:`) - writeRegexp(b, sub) - b.WriteString(`)`) - } else { - writeRegexp(b, sub) + p = flagPrec } + writeRegexp(b, sub, p, flags) } case OpAlternate: for i, sub := range re.Sub { if i > 0 { b.WriteRune('|') } - writeRegexp(b, sub) + writeRegexp(b, sub, 0, flags) } } } func (re *Regexp) String() string { var b strings.Builder - writeRegexp(&b, re) + var flags map[*Regexp]printFlags + must, cant := calcFlags(re, &flags) + must |= (cant &^ flagI) << negShift + if must != 0 { + must |= flagOff + } + writeRegexp(&b, re, must, flags) return b.String() } diff --git a/vendor/modules.txt b/vendor/modules.txt index 701241662ea9..66e15ee11f90 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1029,8 +1029,8 @@ github.com/grafana/loki/pkg/push github.com/grafana/pyroscope-go/godeltaprof github.com/grafana/pyroscope-go/godeltaprof/http/pprof github.com/grafana/pyroscope-go/godeltaprof/internal/pprof -# github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc => github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd -## explicit; go 1.17 +# github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc => github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc +## explicit; go 1.21 github.com/grafana/regexp github.com/grafana/regexp/syntax # github.com/grafana/tail v0.0.0-20230510142333-77b18831edf0 @@ -2402,6 +2402,6 @@ sigs.k8s.io/yaml # github.com/hashicorp/consul => github.com/hashicorp/consul v1.14.5 # github.com/gocql/gocql => github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85 # github.com/hashicorp/memberlist => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe -# github.com/grafana/regexp => github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd +# github.com/grafana/regexp => github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc # github.com/grafana/loki/pkg/push => ./pkg/push # github.com/influxdata/go-syslog/v3 => github.com/leodido/go-syslog/v4 v4.1.0