コード例 #1
0
ファイル: filters.go プロジェクト: emccode/libstorage
func compileFilterSet(
	s string, pos int, parent *types.Filter) (int, error) {

	for pos < len(s) && s[pos] == '(' {
		child, newPos, err := compileFilter(s, pos+1)
		if err != nil {
			return pos, err
		}
		pos = newPos
		parent.Children = append(parent.Children, child)
	}

	if pos == len(s) {
		return pos, errUnexpectedEOF
	}

	return pos + 1, nil
}
コード例 #2
0
ファイル: filters.go プロジェクト: emccode/libstorage
func compileFilter(s string, pos int) (*types.Filter, int, error) {

	switch s[pos] {
	case '(':
		f, newPos, err := compileFilter(s, pos+1)
		newPos++
		return f, newPos, err

	case '&':
		f := &types.Filter{Op: filterAnd}
		newPos, err := compileFilterSet(s, pos+1, f)
		return f, newPos, err

	case '|':
		f := &types.Filter{Op: filterOr}
		newPos, err := compileFilterSet(s, pos+1, f)
		return f, newPos, err

	case '!':
		f := &types.Filter{Op: filterNot}
		child, newPos, err := compileFilter(s, pos+1)
		f.Children = append(f.Children, child)
		return f, newPos, err

	default:

		var (
			f          *types.Filter
			abuf, cbuf bytes.Buffer
			newPos     = pos
		)

		for newPos < len(s) && s[newPos] != ')' {
			switch {
			case f != nil:
				if err := cbuf.WriteByte(s[newPos]); err != nil {
					return nil, 0, err
				}

			case s[newPos] == '=':
				f = &types.Filter{Op: filterEqualityMatch}

			case s[newPos] == '>' && s[newPos+1] == '=':
				f = &types.Filter{Op: filterGreaterOrEqual}
				newPos++

			case s[newPos] == '<' && s[newPos+1] == '=':
				f = &types.Filter{Op: filterLessOrEqual}
				newPos++

			case s[newPos] == '~' && s[newPos+1] == '=':
				f = &types.Filter{Op: filterApproxMatch}
				newPos++

			case f == nil:
				if err := abuf.WriteByte(s[newPos]); err != nil {
					return nil, 0, err
				}
			}
			newPos++
		}

		if newPos == len(s) {
			return f, newPos, errUnexpectedEOF
		}

		if f == nil {
			return nil, 0, errParse
		}

		f.Left = abuf.String()

		var (
			cbyt = cbuf.Bytes()
			cstr = cbuf.String()
			clen = len(cbyt)
			cfch = cbyt[clen-1]
		)

		switch {
		case f.Op == filterEqualityMatch && cstr == "*":
			f.Op = filterPresent

		case f.Op == filterEqualityMatch &&
			cbyt[0] == '*' && cfch == '*' && clen > 2:
			f.Op = filterSubstrings
			f.Right = cstr[1 : clen-1]

		case f.Op == filterEqualityMatch && cbyt[0] == '*' && clen > 1:
			f.Op = filterSubstringsPrefix
			f.Right = cstr[1:]

		case f.Op == filterEqualityMatch && cfch == '*' && clen > 1:
			f.Op = filterSubstringsPostfix
			f.Right = cstr[:clen-1]

		default:
			f.Right = cstr

		}
		newPos++
		return f, newPos, nil
	}
}