| 38 | { |
| 39 | |
| 40 | void Expression::build(LogicGate& gate, const NL::json& json) |
| 41 | { |
| 42 | if (json.is_array()) |
| 43 | { |
| 44 | for (auto& val : json) |
| 45 | build(gate, val); |
| 46 | return; |
| 47 | } |
| 48 | |
| 49 | if (!json.is_object()) |
| 50 | { |
| 51 | throw pdal_error("Unexpected expression: " + json.get<std::string>()); |
| 52 | } |
| 53 | |
| 54 | LogicGate* active(&gate); |
| 55 | |
| 56 | std::unique_ptr<LogicGate> outer; |
| 57 | |
| 58 | if (json.size() > 1) |
| 59 | { |
| 60 | outer = LogicGate::create(LogicalOperator::lAnd); |
| 61 | active = outer.get(); |
| 62 | } |
| 63 | |
| 64 | for (auto& it : json.items()) |
| 65 | { |
| 66 | const NL::json& val(it.value()); |
| 67 | const std::string& key(it.key()); |
| 68 | |
| 69 | if (isLogicalOperator(key)) |
| 70 | { |
| 71 | auto inner(LogicGate::create(key)); |
| 72 | if (inner->type() != LogicalOperator::lNot && !val.is_array()) |
| 73 | { |
| 74 | throw pdal_error("Logical operator expressions must be arrays"); |
| 75 | } |
| 76 | |
| 77 | build(*inner, val); |
| 78 | active->push(std::move(inner)); |
| 79 | } |
| 80 | else if (!val.is_object() || val.size() == 1) |
| 81 | { |
| 82 | // A comparison object. |
| 83 | active->push(Comparison::create(*m_layout, key, val)); |
| 84 | } |
| 85 | else |
| 86 | { |
| 87 | // key is the name of a dimension, val is an object of |
| 88 | // multiple comparison key/val pairs, for example: |
| 89 | // |
| 90 | // key: "Red" |
| 91 | // val: { "$gt": 100, "$lt": 200 } |
| 92 | // |
| 93 | // There cannot be any further nested logical operators |
| 94 | // within val, since we've already selected a dimension. |
| 95 | for (auto inner : val.items()) |
| 96 | { |
| 97 | NL::json nest; |
no test coverage detected