// SPDX-License-Identifier: GPL-3.0-or-later package plan import ( "fmt" "strconv" "strings" ) // MaxIndex returns the highest {N} used in s, 0 when none. It reports the // same errors Expand does for a malformed placeholder: an unclosed // placeholder, or {0} (capture groups are numbered from 1). It shares // Expand's scanner shape: "{{" and "}}" each emit one literal brace, and any // other "{" opens a placeholder that runs to the next "}". func MaxIndex(s string) (int, error) { max := 0 for i := 0; i < len(s); { switch { case s[i] == '{' && i+1 < len(s) && s[i+1] == '{': i += 2 case s[i] == '}' && i+1 < len(s) && s[i+1] == '}': i += 2 case s[i] == '{': end := strings.IndexByte(s[i+1:], '}') if end < 0 { return 0, fmt.Errorf("unclosed placeholder") } body := s[i+1 : i+1+end] if n, err := strconv.Atoi(body); err == nil { if n == 0 { return 0, fmt.Errorf("capture groups are numbered from 1") } if n >= 1 && n <= 9 && n > max { max = n } } i += end + 2 default: i++ } } return max, nil }