// Substitutes values, calculated by callback, on matching regex func (c *Config) computeVar(beforeValue *string, regx *regexp.Regexp, headsz, tailsz int, withVar func(*string) string) (*string, error) { var i int computedVal := beforeValue for i = 0; i < _DEPTH_VALUES; i++ { // keep a sane depth vr := regx.FindStringSubmatchIndex(*computedVal) if len(vr) == 0 { break } varname := (*computedVal)[vr[headsz]:vr[headsz+1]] varVal := withVar(&varname) if varVal == "" { return &varVal, errors.New(fmt.Sprintf("Option not found: %s", varname)) } // substitute by new value and take off leading '%(' and trailing ')s' // %(foo)s => headsz=2, tailsz=2 // ${foo} => headsz=2, tailsz=1 newVal := (*computedVal)[0:vr[headsz]-headsz] + varVal + (*computedVal)[vr[headsz+1]+tailsz:] computedVal = &newVal } if i == _DEPTH_VALUES { retVal := "" return &retVal, fmt.Errorf("Possible cycle while unfolding variables: max depth of %d reached", _DEPTH_VALUES) } return computedVal, nil }
// consume searches for r in the remaining text. If found, it consumes // up to the end of the match, fills m.groups with the matched groups, // and returns true. func (m *matcher) consume(r *regexp.Regexp) bool { idx := r.FindStringSubmatchIndex(m.str[m.pos:]) if idx == nil { m.groups = m.groups[:0] return false } if len(idx)/2 <= cap(m.groups) { m.groups = m.groups[:len(idx)/2] } else { m.groups = make([]string, len(idx)/2, len(idx)) } for i := range m.groups { if idx[i*2] >= 0 { m.groups[i] = m.str[m.pos+idx[i*2] : m.pos+idx[i*2+1]] } else { m.groups[i] = "" } } m.matchPos = m.pos + idx[0] m.pos += idx[1] return true }