An opinionated and permissive ECMA 262 + RFC 9485 (best effort) regex implementation for JSON Schema. More...
Classes | |
| struct | sourcemeta::core::RegexTypeNonEmpty |
| struct | sourcemeta::core::RegexTypePCRE2 |
| struct | sourcemeta::core::RegexTypeNoop |
Typedefs | |
| using | sourcemeta::core::RegexTypePrefix = std::string |
| using | sourcemeta::core::RegexTypeRange = std::pair<std::size_t, std::size_t> |
| using | sourcemeta::core::Regex |
Enumerations | |
| enum class | sourcemeta::core::RegexDialect : std::uint8_t { RegexDialect::Permissive , RegexDialect::IRegexp , RegexDialect::IRegexpSearch } |
Functions | |
| SOURCEMETA_CORE_REGEX_EXPORT auto | sourcemeta::core::to_regex (const std::string_view pattern, const RegexDialect dialect=RegexDialect::Permissive, const bool optimise_for_match=true) -> std::optional< Regex > |
| SOURCEMETA_CORE_REGEX_EXPORT auto | sourcemeta::core::matches (const Regex ®ex, const std::string_view value) -> bool |
| SOURCEMETA_CORE_REGEX_EXPORT auto | sourcemeta::core::matches_if_valid (const std::string_view pattern, const std::string_view value, const RegexDialect dialect=RegexDialect::Permissive) -> bool |
| SOURCEMETA_CORE_REGEX_EXPORT auto | sourcemeta::core::replace_all (const Regex ®ex, const std::string_view subject, const std::string_view replacement) -> std::string |
| SOURCEMETA_CORE_REGEX_EXPORT auto | sourcemeta::core::is_regex_ecma (const std::string_view pattern) -> bool |
An opinionated and permissive ECMA 262 + RFC 9485 (best effort) regex implementation for JSON Schema.
This functionality is included as follows:
| struct sourcemeta::core::RegexTypeNonEmpty |
| struct sourcemeta::core::RegexTypePCRE2 |
| struct sourcemeta::core::RegexTypeNoop |
| using sourcemeta::core::Regex |
A compiled regular expression in one of its supported representations.
| using sourcemeta::core::RegexTypePrefix = std::string |
Matches any string that begins with a fixed prefix.
| using sourcemeta::core::RegexTypeRange = std::pair<std::size_t, std::size_t> |
Matches any string whose length falls within an inclusive range.
|
strong |
The dialects that a regular expression pattern can be interpreted with.
| SOURCEMETA_CORE_REGEX_EXPORT auto sourcemeta::core::is_regex_ecma | ( | const std::string_view | pattern | ) | -> bool |
Check whether the given string is a valid ECMA-262 regular expression.
The pattern is read against the grammar of ECMA-262, including its early errors, rather than handed to the underlying engine, so the answer follows the standard instead of whatever a particular engine happens to accept. A pattern is accepted when it parses under either of the two Unicode-aware readings of the standard, meaning the one that JavaScript selects with the u flag or the one it selects with the v flag. The latter is what makes set notation, such as nested classes, set operations and string disjunctions, come out valid. JSON Schema recommends the former for the sake of Unicode support.
The reading that JavaScript selects when neither flag is given is deliberately not accepted. That is the reading on which Annex B of the standard applies, and the standard is explicit about who that annex is for: "The ECMAScript language syntax and semantics defined in this annex are required when the ECMAScript host is a web browser. The content of this annex is normative but optional if the ECMAScript host is not a web browser." It is equally explicit about who should stay away from it: "ECMAScript implementations are discouraged from implementing these features unless the implementation is part of a web browser or is required to run the same legacy ECMAScript code that web browsers encounter", and of the features themselves it says that they "are not considered part of the core ECMAScript language". Neither condition holds for reading a schema. Both Unicode-aware readings turn the annex off in any case, as "none of these extensions change the syntax of Unicode patterns recognized when parsing with the [UnicodeMode] parameter present on the goal symbol". See https://tc39.es/ecma262/#sec-additional-ecmascript-features-for-web-browsers and https://tc39.es/ecma262/#sec-regular-expressions-patterns
The practical effect of that annex is to turn a great deal of otherwise malformed input into literal text, so a pattern written for another flavour would pass without meaning what its author intended. Leaving it aside, a syntax character standing on its own, such as an unescaped brace or closing bracket, makes a pattern invalid, an escape of a letter that the standard leaves undefined makes a pattern invalid, and property escapes only resolve against the property names and values that the standard permits. The discarded reading is also the only one that allows escaping a character that cannot continue an identifier, so escaped punctuation outside a character class is turned down as well. A web browser accepts all of these, and this is where the two answers part company. For example:
Note that a pattern being valid does not mean this project can compile it, as the standard places no bound on how much a quantifier may repeat nor on how deeply groups and classes may nest, while this reader stops at 255 levels and the underlying engine has limits of its own. Use to_regex to find out whether a pattern can also be matched with, bearing in mind that the dialects it offers are not the reading described here.
| SOURCEMETA_CORE_REGEX_EXPORT auto sourcemeta::core::matches | ( | const Regex & | regex, |
| const std::string_view | value ) -> bool |
Validate a string against a regular expression. For example:
| SOURCEMETA_CORE_REGEX_EXPORT auto sourcemeta::core::matches_if_valid | ( | const std::string_view | pattern, |
| const std::string_view | value, | ||
| const RegexDialect | dialect = RegexDialect::Permissive ) -> bool |
Validate a string against a regular expression pattern if the pattern represents a valid regular expression, compiling it along the way. For example:
| SOURCEMETA_CORE_REGEX_EXPORT auto sourcemeta::core::replace_all | ( | const Regex & | regex, |
| const std::string_view | subject, | ||
| const std::string_view | replacement ) -> std::string |
Replace every match of a regular expression with the given text, which is inserted literally. The regular expression must have been compiled without optimising for matching, and the behaviour is undefined otherwise. A subject that exhausts a matching resource is left alone, just as it would count as a failure to match. For example:
| SOURCEMETA_CORE_REGEX_EXPORT auto sourcemeta::core::to_regex | ( | const std::string_view | pattern, |
| const RegexDialect | dialect = RegexDialect::Permissive, | ||
| const bool | optimise_for_match = true ) -> std::optional< Regex > |
Compile a regular expression from a string. If the regular expression is invalid, no value is returned. In this function:
For example: