nit: move + rename _build_min_max_int
This commit is contained in:
parent
e93368076b
commit
a0f19047af
1 changed files with 183 additions and 183 deletions
|
@ -40,6 +40,188 @@ static std::string build_repetition(const std::string & item_rule, const int min
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _build_min_max_int(int min_value, int max_value, std::stringstream & out, int decimals_left = 16, bool top_level = true) {
|
||||||
|
auto has_min = min_value != std::numeric_limits<int>::min();
|
||||||
|
auto has_max = max_value != std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
auto digit_range = [&](char from, char to) {
|
||||||
|
out << "[";
|
||||||
|
if (from == to) {
|
||||||
|
out << from;
|
||||||
|
} else {
|
||||||
|
out << from << "-" << to;
|
||||||
|
}
|
||||||
|
out << "]";
|
||||||
|
};
|
||||||
|
auto more_digits = [&](int min_digits, int max_digits) {
|
||||||
|
out << "[0-9]";
|
||||||
|
if (min_digits == max_digits && min_digits == 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out << "{";
|
||||||
|
out << min_digits;
|
||||||
|
if (max_digits != min_digits) {
|
||||||
|
out << ",";
|
||||||
|
if (max_digits != std::numeric_limits<int>::max()) {
|
||||||
|
out << max_digits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "}";
|
||||||
|
};
|
||||||
|
std::function<void(const std::string_view &, const std::string_view &)> uniform_range = [&](const std::string_view & from, const std::string_view & to) {
|
||||||
|
size_t i = 0;
|
||||||
|
while (from[i] == to[i]) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
out << "\"" << from.substr(0, i) << "\"";
|
||||||
|
}
|
||||||
|
if (i < from.length()) {
|
||||||
|
if (i > 0) {
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
auto sub_len = from.length() - i - 1;
|
||||||
|
if (sub_len > 0) {
|
||||||
|
auto from_sub = from.substr(i + 1);
|
||||||
|
auto to_sub = to.substr(i + 1);
|
||||||
|
auto sub_zeros = repeat("0", sub_len);
|
||||||
|
auto sub_nines = repeat("9", sub_len);
|
||||||
|
|
||||||
|
auto to_reached = false;
|
||||||
|
out << "(";
|
||||||
|
if (from_sub == sub_zeros) {
|
||||||
|
digit_range(from[i], to[i] - 1);
|
||||||
|
out << " ";
|
||||||
|
more_digits(sub_len, sub_len);
|
||||||
|
} else {
|
||||||
|
out << "[" << from[i] << "] ";
|
||||||
|
out << "(";
|
||||||
|
uniform_range(from_sub, sub_nines);
|
||||||
|
out << ")";
|
||||||
|
if (from[i] < to[i] - 1) {
|
||||||
|
out << " | ";
|
||||||
|
if (to_sub == sub_nines) {
|
||||||
|
digit_range(from[i] + 1, to[i]);
|
||||||
|
to_reached = true;
|
||||||
|
} else {
|
||||||
|
digit_range(from[i] + 1, to[i] - 1);
|
||||||
|
}
|
||||||
|
out << " ";
|
||||||
|
more_digits(sub_len, sub_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!to_reached) {
|
||||||
|
out << " | ";
|
||||||
|
digit_range(to[i], to[i]);
|
||||||
|
out << " ";
|
||||||
|
uniform_range(sub_zeros, to_sub);
|
||||||
|
}
|
||||||
|
out << ")";
|
||||||
|
} else {
|
||||||
|
out << "[" << from[i] << "-" << to[i] << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (has_min && has_max) {
|
||||||
|
if (min_value < 0 && max_value < 0) {
|
||||||
|
out << "\"-\" (";
|
||||||
|
_build_min_max_int(-max_value, -min_value, out, decimals_left, /* top_level= */ true);
|
||||||
|
out << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min_value < 0) {
|
||||||
|
out << "\"-\" (";
|
||||||
|
_build_min_max_int(0, -min_value, out, decimals_left, /* top_level= */ true);
|
||||||
|
out << ") | ";
|
||||||
|
min_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto min_s = std::to_string(min_value);
|
||||||
|
auto max_s = std::to_string(max_value);
|
||||||
|
auto min_digits = min_s.length();
|
||||||
|
auto max_digits = max_s.length();
|
||||||
|
|
||||||
|
for (auto digits = min_digits; digits < max_digits; digits++) {
|
||||||
|
uniform_range(min_s, repeat("9", digits));
|
||||||
|
min_s = "1" + repeat("0", digits);
|
||||||
|
out << " | ";
|
||||||
|
}
|
||||||
|
uniform_range(min_s, max_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto less_decimals = std::max(decimals_left - 1, 1);
|
||||||
|
|
||||||
|
if (has_min) {
|
||||||
|
if (min_value < 0) {
|
||||||
|
out << "\"-\" (";
|
||||||
|
_build_min_max_int(std::numeric_limits<int>::min(), -min_value, out, decimals_left, /* top_level= */ false);
|
||||||
|
out << ") | [0] | [1-9] ";
|
||||||
|
more_digits(0, decimals_left - 1);
|
||||||
|
} else if (min_value == 0) {
|
||||||
|
if (top_level) {
|
||||||
|
out << "[0] | [1-9] ";
|
||||||
|
more_digits(0, less_decimals);
|
||||||
|
} else {
|
||||||
|
more_digits(1, decimals_left);
|
||||||
|
}
|
||||||
|
} else if (min_value <= 9) {
|
||||||
|
char c = '0' + min_value;
|
||||||
|
if (min_value > (top_level ? 1 : 0)) {
|
||||||
|
digit_range('0', c - 1);
|
||||||
|
out << " ";
|
||||||
|
more_digits(1, less_decimals);
|
||||||
|
out << " | ";
|
||||||
|
}
|
||||||
|
digit_range(c, '9');
|
||||||
|
out << " ";
|
||||||
|
more_digits(0, less_decimals);
|
||||||
|
} else {
|
||||||
|
auto min_s = std::to_string(min_value);
|
||||||
|
auto len = min_s.length();
|
||||||
|
auto c = min_s[0];
|
||||||
|
|
||||||
|
if (c > '1') {
|
||||||
|
digit_range(top_level ? '1' : '0', c - 1);
|
||||||
|
out << " ";
|
||||||
|
more_digits(len, less_decimals);
|
||||||
|
out << " | ";
|
||||||
|
}
|
||||||
|
digit_range(c, c);
|
||||||
|
out << " (";
|
||||||
|
_build_min_max_int(std::stoi(min_s.substr(1)), std::numeric_limits<int>::max(), out, less_decimals, /* top_level= */ false);
|
||||||
|
out << ")";
|
||||||
|
if (c < '9') {
|
||||||
|
out << " | ";
|
||||||
|
digit_range(c + 1, '9');
|
||||||
|
out << " ";
|
||||||
|
more_digits(len - 1, less_decimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_max) {
|
||||||
|
if (max_value >= 0) {
|
||||||
|
if (top_level) {
|
||||||
|
out << "\"-\" [1-9] ";
|
||||||
|
more_digits(0, less_decimals);
|
||||||
|
out << " | ";
|
||||||
|
}
|
||||||
|
_build_min_max_int(0, max_value, out, decimals_left, /* top_level= */ true);
|
||||||
|
} else {
|
||||||
|
out << "\"-\" (";
|
||||||
|
_build_min_max_int(-max_value, std::numeric_limits<int>::max(), out, decimals_left, /* top_level= */ false);
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("At least one of min_value or max_value must be set");
|
||||||
|
}
|
||||||
|
|
||||||
const std::string SPACE_RULE = "\" \"?";
|
const std::string SPACE_RULE = "\" \"?";
|
||||||
|
|
||||||
struct BuiltinRule {
|
struct BuiltinRule {
|
||||||
|
@ -160,188 +342,6 @@ static std::string format_literal(const std::string & literal) {
|
||||||
return "\"" + escaped + "\"";
|
return "\"" + escaped + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _generate_min_max_int(int min_value, int max_value, std::stringstream & out, int decimals_left = 16, bool top_level = true) {
|
|
||||||
auto has_min = min_value != std::numeric_limits<int>::min();
|
|
||||||
auto has_max = max_value != std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
auto digit_range = [&](char from, char to) {
|
|
||||||
out << "[";
|
|
||||||
if (from == to) {
|
|
||||||
out << from;
|
|
||||||
} else {
|
|
||||||
out << from << "-" << to;
|
|
||||||
}
|
|
||||||
out << "]";
|
|
||||||
};
|
|
||||||
auto more_digits = [&](int min_digits, int max_digits) {
|
|
||||||
out << "[0-9]";
|
|
||||||
if (min_digits == max_digits && min_digits == 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out << "{";
|
|
||||||
out << min_digits;
|
|
||||||
if (max_digits != min_digits) {
|
|
||||||
out << ",";
|
|
||||||
if (max_digits != std::numeric_limits<int>::max()) {
|
|
||||||
out << max_digits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << "}";
|
|
||||||
};
|
|
||||||
std::function<void(const std::string_view &, const std::string_view &)> uniform_range = [&](const std::string_view & from, const std::string_view & to) {
|
|
||||||
size_t i = 0;
|
|
||||||
while (from[i] == to[i]) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i > 0) {
|
|
||||||
out << "\"" << from.substr(0, i) << "\"";
|
|
||||||
}
|
|
||||||
if (i < from.length()) {
|
|
||||||
if (i > 0) {
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
auto sub_len = from.length() - i - 1;
|
|
||||||
if (sub_len > 0) {
|
|
||||||
auto from_sub = from.substr(i + 1);
|
|
||||||
auto to_sub = to.substr(i + 1);
|
|
||||||
auto sub_zeros = repeat("0", sub_len);
|
|
||||||
auto sub_nines = repeat("9", sub_len);
|
|
||||||
|
|
||||||
auto to_reached = false;
|
|
||||||
out << "(";
|
|
||||||
if (from_sub == sub_zeros) {
|
|
||||||
digit_range(from[i], to[i] - 1);
|
|
||||||
out << " ";
|
|
||||||
more_digits(sub_len, sub_len);
|
|
||||||
} else {
|
|
||||||
out << "[" << from[i] << "] ";
|
|
||||||
out << "(";
|
|
||||||
uniform_range(from_sub, sub_nines);
|
|
||||||
out << ")";
|
|
||||||
if (from[i] < to[i] - 1) {
|
|
||||||
out << " | ";
|
|
||||||
if (to_sub == sub_nines) {
|
|
||||||
digit_range(from[i] + 1, to[i]);
|
|
||||||
to_reached = true;
|
|
||||||
} else {
|
|
||||||
digit_range(from[i] + 1, to[i] - 1);
|
|
||||||
}
|
|
||||||
out << " ";
|
|
||||||
more_digits(sub_len, sub_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!to_reached) {
|
|
||||||
out << " | ";
|
|
||||||
digit_range(to[i], to[i]);
|
|
||||||
out << " ";
|
|
||||||
uniform_range(sub_zeros, to_sub);
|
|
||||||
}
|
|
||||||
out << ")";
|
|
||||||
} else {
|
|
||||||
out << "[" << from[i] << "-" << to[i] << "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (has_min && has_max) {
|
|
||||||
if (min_value < 0 && max_value < 0) {
|
|
||||||
out << "\"-\" (";
|
|
||||||
_generate_min_max_int(-max_value, -min_value, out, decimals_left, /* top_level= */ true);
|
|
||||||
out << ")";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min_value < 0) {
|
|
||||||
out << "\"-\" (";
|
|
||||||
_generate_min_max_int(0, -min_value, out, decimals_left, /* top_level= */ true);
|
|
||||||
out << ") | ";
|
|
||||||
min_value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto min_s = std::to_string(min_value);
|
|
||||||
auto max_s = std::to_string(max_value);
|
|
||||||
auto min_digits = min_s.length();
|
|
||||||
auto max_digits = max_s.length();
|
|
||||||
|
|
||||||
for (auto digits = min_digits; digits < max_digits; digits++) {
|
|
||||||
uniform_range(min_s, repeat("9", digits));
|
|
||||||
min_s = "1" + repeat("0", digits);
|
|
||||||
out << " | ";
|
|
||||||
}
|
|
||||||
uniform_range(min_s, max_s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto less_decimals = std::max(decimals_left - 1, 1);
|
|
||||||
|
|
||||||
if (has_min) {
|
|
||||||
if (min_value < 0) {
|
|
||||||
out << "\"-\" (";
|
|
||||||
_generate_min_max_int(std::numeric_limits<int>::min(), -min_value, out, decimals_left, /* top_level= */ false);
|
|
||||||
out << ") | [0] | [1-9] ";
|
|
||||||
more_digits(0, decimals_left - 1);
|
|
||||||
} else if (min_value == 0) {
|
|
||||||
if (top_level) {
|
|
||||||
out << "[0] | [1-9] ";
|
|
||||||
more_digits(0, less_decimals);
|
|
||||||
} else {
|
|
||||||
more_digits(1, decimals_left);
|
|
||||||
}
|
|
||||||
} else if (min_value <= 9) {
|
|
||||||
char c = '0' + min_value;
|
|
||||||
if (min_value > (top_level ? 1 : 0)) {
|
|
||||||
digit_range('0', c - 1);
|
|
||||||
out << " ";
|
|
||||||
more_digits(1, less_decimals);
|
|
||||||
out << " | ";
|
|
||||||
}
|
|
||||||
digit_range(c, '9');
|
|
||||||
out << " ";
|
|
||||||
more_digits(0, less_decimals);
|
|
||||||
} else {
|
|
||||||
auto min_s = std::to_string(min_value);
|
|
||||||
auto len = min_s.length();
|
|
||||||
auto c = min_s[0];
|
|
||||||
|
|
||||||
if (c > '1') {
|
|
||||||
digit_range(top_level ? '1' : '0', c - 1);
|
|
||||||
out << " ";
|
|
||||||
more_digits(len, less_decimals);
|
|
||||||
out << " | ";
|
|
||||||
}
|
|
||||||
digit_range(c, c);
|
|
||||||
out << " (";
|
|
||||||
_generate_min_max_int(std::stoi(min_s.substr(1)), std::numeric_limits<int>::max(), out, less_decimals, /* top_level= */ false);
|
|
||||||
out << ")";
|
|
||||||
if (c < '9') {
|
|
||||||
out << " | ";
|
|
||||||
digit_range(c + 1, '9');
|
|
||||||
out << " ";
|
|
||||||
more_digits(len - 1, less_decimals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_max) {
|
|
||||||
if (max_value >= 0) {
|
|
||||||
if (top_level) {
|
|
||||||
out << "\"-\" [1-9] ";
|
|
||||||
more_digits(0, less_decimals);
|
|
||||||
out << " | ";
|
|
||||||
}
|
|
||||||
_generate_min_max_int(0, max_value, out, decimals_left, /* top_level= */ true);
|
|
||||||
} else {
|
|
||||||
out << "\"-\" (";
|
|
||||||
_generate_min_max_int(-max_value, std::numeric_limits<int>::max(), out, decimals_left, /* top_level= */ false);
|
|
||||||
out << ")";
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("At least one of min_value or max_value must be set");
|
|
||||||
}
|
|
||||||
|
|
||||||
class SchemaConverter {
|
class SchemaConverter {
|
||||||
private:
|
private:
|
||||||
std::function<json(const std::string &)> _fetch_json;
|
std::function<json(const std::string &)> _fetch_json;
|
||||||
|
@ -882,7 +882,7 @@ public:
|
||||||
}
|
}
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
out << "(";
|
out << "(";
|
||||||
_generate_min_max_int(min_value, max_value, out);
|
_build_min_max_int(min_value, max_value, out);
|
||||||
out << ") space";
|
out << ") space";
|
||||||
return _add_rule(rule_name, out.str());
|
return _add_rule(rule_name, out.str());
|
||||||
} else if (schema.empty() || schema_type == "object") {
|
} else if (schema.empty() || schema_type == "object") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue