aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/vespa/document/predicate/predicate_printer.cpp
blob: e0272e2ecc7bfd5d703399ad36d4037766ea81e2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "predicate.h"
#include "predicate_printer.h"
#include <vespa/document/util/stringutil.h>
#include <vespa/vespalib/data/slime/slime.h>
#include <vespa/vespalib/stllike/asciistream.h>

using vespalib::Slime;
using vespalib::slime::Inspector;

namespace document {

namespace {
void printEscapedString(vespalib::asciistream &out, const Inspector &in) {
    out << "'" << StringUtil::escape(in.asString().make_string(), '\'') << "'";
}
}  // namespace

vespalib::string
PredicatePrinter::str() const {
    return _out->str();
}

PredicatePrinter::PredicatePrinter() : _out(new vespalib::asciistream()), _negated(false) {}
PredicatePrinter::~PredicatePrinter() { }


void PredicatePrinter::visitFeatureSet(const Inspector &in) {
    printEscapedString(*_out, in[Predicate::KEY]);
    if (_negated) {
        *_out << " not";
    }
    *_out << " in [";
    for (size_t i = 0; i < in[Predicate::SET].entries(); ++i) {
        if (i) {
            *_out << ",";
        }
        printEscapedString(*_out, in[Predicate::SET][i]);
    }
    *_out << "]";
}

void PredicatePrinter::visitFeatureRange(const Inspector &in) {
    printEscapedString(*_out, in[Predicate::KEY]);
    if (_negated) {
        *_out << " not";
    }
    bool has_min = in[Predicate::RANGE_MIN].valid();
    bool has_max = in[Predicate::RANGE_MAX].valid();
    *_out << " in [";
    if (has_min) *_out << in[Predicate::RANGE_MIN].asLong();
    *_out << "..";
    if (has_max) *_out << in[Predicate::RANGE_MAX].asLong();
    *_out << "]";
}

void PredicatePrinter::visitNegation(const Inspector &in) {
    bool n = _negated;
    _negated = !_negated;
    visitChildren(in);
    _negated = n;
}

void PredicatePrinter::visitConjunction(const Inspector &in) {
    if (_negated)
        *_out << "not ";
    _negated = false;
    *_out << "(";
    for (size_t i = 0; i < in[Predicate::CHILDREN].children(); ++i) {
        if (i) {
            *_out << " and ";
        }
        visit(in[Predicate::CHILDREN][i]);
    }
    *_out << ")";
}

void PredicatePrinter::visitDisjunction(const Inspector &in) {
    if (_negated)
        *_out << "not ";
    _negated = false;
    *_out << "(";
    for (size_t i = 0; i < in[Predicate::CHILDREN].children(); ++i) {
        if (i) {
            *_out << " or ";
        }
        visit(in[Predicate::CHILDREN][i]);
    }
    *_out << ")";
}

void PredicatePrinter::visitTrue(const Inspector &) {
    *_out << "true";
}

void PredicatePrinter::visitFalse(const Inspector &) {
    *_out << "false";
}

vespalib::string PredicatePrinter::print(const Slime &slime) {
    PredicatePrinter printer;
    printer.visit(slime.get());
    return printer.str();
}

}  // namespace document