in watchman/query/since.cpp [101:163]
static std::unique_ptr<QueryExpr> parse(Query*, const json_ref& term) {
auto selected_field = since_what::SINCE_OCLOCK;
const char* fieldname = "oclock";
if (!term.isArray()) {
throw QueryParseError("\"since\" term must be an array");
}
if (json_array_size(term) < 2 || json_array_size(term) > 3) {
throw QueryParseError("\"since\" term has invalid number of parameters");
}
const auto& jval = term.at(1);
auto spec = ClockSpec::parseOptionalClockSpec(jval);
if (!spec) {
throw QueryParseError("invalid clockspec for \"since\" term");
}
if (std::holds_alternative<ClockSpec::NamedCursor>(spec->spec)) {
throw QueryParseError("named cursors are not allowed in \"since\" terms");
}
if (term.array().size() == 3) {
const auto& field = term.at(2);
size_t i;
bool valid = false;
fieldname = json_string_value(field);
if (!fieldname) {
throw QueryParseError("field name for \"since\" term must be a string");
}
for (i = 0; i < sizeof(allowed_fields) / sizeof(allowed_fields[0]); ++i) {
if (!strcmp(allowed_fields[i].label, fieldname)) {
selected_field = allowed_fields[i].value;
valid = true;
break;
}
}
if (!valid) {
throw QueryParseError(
"invalid field name \"", fieldname, "\" for \"since\" term");
}
}
switch (selected_field) {
case since_what::SINCE_CTIME:
case since_what::SINCE_MTIME:
if (!std::holds_alternative<ClockSpec::Timestamp>(spec->spec)) {
throw QueryParseError(
"field \"",
fieldname,
"\" requires a timestamp value for comparison in \"since\" term");
}
break;
case since_what::SINCE_OCLOCK:
case since_what::SINCE_CCLOCK:
/* we'll work with clocks or timestamps */
break;
}
return std::make_unique<SinceExpr>(std::move(spec), selected_field);
}