Skip to content

Commit

Permalink
Add extra options
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelmior committed Feb 13, 2025
1 parent fb987b2 commit 12555b9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 46 deletions.
8 changes: 6 additions & 2 deletions src/compiler/default_compiler_2019_09.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,18 @@ auto compiler_2019_09_applicator_unevaluatedproperties(
} else if (keyword == "patternProperties") {
if (subschema.is_object()) {
for (const auto &property : subschema.as_object()) {
const auto maybe_prefix{pattern_as_prefix(property.first)};
std::optional<std::basic_string<char>> maybe_prefix{std::nullopt};
if (options.simplify_regexes) {
maybe_prefix = pattern_as_prefix(property.first);
}
if (maybe_prefix.has_value()) {
filter_prefixes.push_back(maybe_prefix.value());
} else {
filter_regexes.push_back(
{parse_regex(property.first, schema_context.base,
schema_context.relative_pointer.initial().concat(
{"patternProperties"})),
{"patternProperties"}),
options.simplify_regexes),
property.first});
}
}
Expand Down
56 changes: 35 additions & 21 deletions src/compiler/default_compiler_draft4.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

static auto parse_regex(const std::string &pattern,
const sourcemeta::core::URI &base,
const sourcemeta::core::Pointer &schema_location)
const sourcemeta::core::Pointer &schema_location,
const bool simplify_regexes)
-> sourcemeta::core::Regex<sourcemeta::core::JSON::String> {
const auto result{sourcemeta::core::to_regex(pattern)};
const auto result{sourcemeta::core::to_regex(pattern, simplify_regexes)};
if (!result.has_value()) {
std::ostringstream message;
message << "Invalid regular expression: " << pattern;
Expand Down Expand Up @@ -252,7 +253,8 @@ auto compiler_draft4_core_ref(const Context &context,
.pointer)) ||
schema_context.references.contains(reference.destination)};

if (!is_recursive && direct_children_references <= 5) {
if (!is_recursive &&
direct_children_references <= options.expand_ref_threshold) {
if (context.mode == Mode::FastValidation &&
// Expanding references inline when dynamic scoping is required
// may not work, as we might omit the instruction that introduces
Expand Down Expand Up @@ -610,8 +612,9 @@ auto compiler_draft4_validation_required(const Context &context,
if (context.mode == Mode::FastValidation &&
properties_set.size() == 3 &&
std::all_of(properties_set.begin(), properties_set.end(),
[&hasher](const auto &property) {
return hasher.is_perfect(property.second);
[&hasher, &options](const auto &property) {
return options.perfect_hash &&
hasher.is_perfect(property.second);
})) {
std::vector<std::pair<ValueString, ValueStringSet::hash_type>> hashes;
for (const auto &property : properties_set) {
Expand Down Expand Up @@ -1018,7 +1021,7 @@ auto compiler_draft4_applicator_properties_with_options(
perfect_hashes;
for (const auto &entry : required) {
assert(required.contains(entry.first, entry.second));
if (hasher.is_perfect(entry.second)) {
if (options.perfect_hash && hasher.is_perfect(entry.second)) {
perfect_hashes.emplace_back(entry.first, entry.second);
}
}
Expand Down Expand Up @@ -1249,14 +1252,18 @@ auto compiler_draft4_applicator_patternproperties_with_options(
make(sourcemeta::blaze::InstructionIndex::LoopPropertiesRegexClosed,
context, schema_context, dynamic_context,
ValueRegex{parse_regex(pattern, schema_context.base,
schema_context.relative_pointer),
schema_context.relative_pointer,
options.simplify_regexes),
pattern},
std::move(substeps)));

// If the `patternProperties` subschema for the given pattern does
// nothing, then we can avoid generating an entire loop for it
} else if (!substeps.empty()) {
const auto maybe_prefix{pattern_as_prefix(pattern)};
std::optional<std::basic_string<char>> maybe_prefix{std::nullopt};
if (options.simplify_regexes) {
maybe_prefix = pattern_as_prefix(pattern);
}
if (maybe_prefix.has_value()) {
children.push_back(
make(sourcemeta::blaze::InstructionIndex::LoopPropertiesStartsWith,
Expand All @@ -1267,7 +1274,8 @@ auto compiler_draft4_applicator_patternproperties_with_options(
make(sourcemeta::blaze::InstructionIndex::LoopPropertiesRegex,
context, schema_context, dynamic_context,
ValueRegex{parse_regex(pattern, schema_context.base,
schema_context.relative_pointer),
schema_context.relative_pointer,
options.simplify_regexes),
pattern},
std::move(substeps)));
}
Expand Down Expand Up @@ -1323,14 +1331,18 @@ auto compiler_draft4_applicator_additionalproperties_with_options(
schema_context.schema.at("patternProperties").is_object()) {
for (const auto &entry :
schema_context.schema.at("patternProperties").as_object()) {
const auto maybe_prefix{pattern_as_prefix(entry.first)};
std::optional<std::basic_string<char>> maybe_prefix{std::nullopt};
if (options.simplify_regexes) {
maybe_prefix = pattern_as_prefix(entry.first);
}
if (maybe_prefix.has_value()) {
filter_prefixes.push_back(maybe_prefix.value());
} else {
filter_regexes.push_back(
{parse_regex(entry.first, schema_context.base,
schema_context.relative_pointer.initial().concat(
{"patternProperties"})),
{"patternProperties"}),
options.simplify_regexes),
entry.first});
}
}
Expand Down Expand Up @@ -1450,7 +1462,7 @@ auto compiler_draft4_applicator_additionalproperties(

auto compiler_draft4_validation_pattern(const Context &context,
const SchemaContext &schema_context,
const CompileOptions &,
const CompileOptions &options,
const DynamicContext &dynamic_context,
const Instructions &) -> Instructions {
assert(schema_context.schema.at(dynamic_context.keyword).is_string());
Expand All @@ -1466,13 +1478,14 @@ auto compiler_draft4_validation_pattern(const Context &context,
return {make(sourcemeta::blaze::InstructionIndex::AssertionRegex, context,
schema_context, dynamic_context,
ValueRegex{parse_regex(regex_string, schema_context.base,
schema_context.relative_pointer),
schema_context.relative_pointer,
options.simplify_regexes),
regex_string})};
}

auto compiler_draft4_validation_format(const Context &context,
const SchemaContext &schema_context,
const CompileOptions &,
const CompileOptions &options,
const DynamicContext &dynamic_context,
const Instructions &) -> Instructions {
if (!schema_context.schema.at(dynamic_context.keyword).is_string()) {
Expand Down Expand Up @@ -1507,7 +1520,8 @@ auto compiler_draft4_validation_format(const Context &context,
make(sourcemeta::blaze::InstructionIndex::AssertionRegex, context, \
schema_context, dynamic_context, \
ValueRegex{parse_regex(regular_expression, schema_context.base, \
schema_context.relative_pointer), \
schema_context.relative_pointer, \
options.simplify_regexes), \
(regular_expression)})}; \
}

Expand Down Expand Up @@ -1916,7 +1930,7 @@ auto compiler_draft4_applicator_dependencies(

auto compiler_draft4_validation_enum(const Context &context,
const SchemaContext &schema_context,
const CompileOptions &,
const CompileOptions &options,
const DynamicContext &dynamic_context,
const Instructions &) -> Instructions {
assert(schema_context.schema.at(dynamic_context.keyword).is_array());
Expand All @@ -1932,32 +1946,32 @@ auto compiler_draft4_validation_enum(const Context &context,
std::vector<std::pair<sourcemeta::blaze::ValueString,
sourcemeta::blaze::ValueStringSet::hash_type>>
perfect_string_hashes;
ValueSet options;
ValueSet enums;
sourcemeta::core::PropertyHashJSON<ValueString> hasher;
for (const auto &option :
schema_context.schema.at(dynamic_context.keyword).as_array()) {
if (option.is_string()) {
const auto hash{hasher(option.to_string())};
if (hasher.is_perfect(hash)) {
if (options.perfect_hash && hasher.is_perfect(hash)) {
perfect_string_hashes.emplace_back(option.to_string(), hash);
}
}

options.insert(option);
enums.insert(option);
}

// Only apply this optimisation on fast validation, as it
// can affect error messages
if (context.mode == Mode::FastValidation &&
perfect_string_hashes.size() == options.size()) {
perfect_string_hashes.size() == enums.size()) {
return {
make(sourcemeta::blaze::InstructionIndex::AssertionEqualsAnyStringHash,
context, schema_context, dynamic_context,
to_string_hashes(perfect_string_hashes))};
}

return {make(sourcemeta::blaze::InstructionIndex::AssertionEqualsAny, context,
schema_context, dynamic_context, std::move(options))};
schema_context, dynamic_context, std::move(enums))};
}

auto compiler_draft4_validation_uniqueitems(
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/include/sourcemeta/blaze/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,13 @@ struct DynamicContext {
};

struct CompileOptions {
const bool perfect_hash;
const size_t expand_ref_threshold;
const bool unroll;
const bool simplify_regexes;
};

const CompileOptions default_compile_options{true};
const CompileOptions default_compile_options{true, 5, true, true};

/* auto default_compile_options = CompileOptions{true}; */

Expand Down
46 changes: 24 additions & 22 deletions vendor/core/src/core/regex/include/sourcemeta/core/regex.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 12555b9

Please sign in to comment.