1#ifndef SOURCEMETA_BLAZE_EVALUATOR_H_
2#define SOURCEMETA_BLAZE_EVALUATOR_H_
4#ifndef SOURCEMETA_BLAZE_EVALUATOR_EXPORT
5#include <sourcemeta/blaze/evaluator_export.h>
8#include <sourcemeta/blaze/evaluator_error.h>
9#include <sourcemeta/blaze/evaluator_instruction.h>
11#include <sourcemeta/core/json.h>
12#include <sourcemeta/core/jsonpointer.h>
13#include <sourcemeta/core/regex.h>
34namespace sourcemeta::blaze {
41 std::vector<Instructions> targets;
42 std::vector<std::pair<std::size_t, std::size_t>> labels;
43 std::vector<InstructionExtra> extra;
51constexpr std::size_t JSON_VERSION{15};
55auto SOURCEMETA_BLAZE_EVALUATOR_EXPORT
56from_json(
const sourcemeta::core::JSON &json) -> std::optional<Template>;
79 const sourcemeta::core::WeakPointer &,
80 const sourcemeta::core::WeakPointer &,
const sourcemeta::core::JSON &)>;
115 assert(this->evaluate_path.empty());
116 assert(this->instance_location.empty());
117 assert(this->resources.empty());
119 if (schema.track && schema.dynamic) [[unlikely]] {
120 this->evaluated.clear();
121 return this->evaluate_impl<true, true, false>(schema, instance,
nullptr);
122 }
else if (schema.track) [[unlikely]] {
123 this->evaluated.clear();
124 return this->evaluate_impl<true, false, false>(schema, instance,
nullptr);
125 }
else if (schema.dynamic) [[unlikely]] {
126 return this->evaluate_impl<false, true, false>(schema, instance,
nullptr);
128 return this->evaluate_impl<false, false, false>(schema, instance,
195 assert(this->evaluate_path.empty());
196 assert(this->instance_location.empty());
197 assert(this->resources.empty());
198 this->evaluated.clear();
199 if (schema.dynamic) [[unlikely]] {
200 return this->evaluate_impl<true, true, true>(schema, instance, &callback);
203 return this->evaluate_impl<true, false, true>(schema, instance, &callback);
207 template <
bool Track,
bool Dynamic,
bool HasCallback>
208 auto evaluate_impl(
const Template &schema,
209 const sourcemeta::core::JSON &instance,
213 static inline const sourcemeta::core::JSON NULL_VALUE{
nullptr};
214 static inline const sourcemeta::core::JSON EMPTY_STRING{
""};
220 [[nodiscard]]
static auto hash(
const std::size_t resource,
221 const std::string_view fragment)
noexcept
223 constexpr std::size_t MASK{(1ULL << 53) - 1};
224 std::size_t result{14695981039346656037ULL & MASK};
225 for (
const auto byte : fragment) {
226 result ^=
static_cast<std::size_t
>(
static_cast<unsigned char>(byte));
227 result = (result * 1099511628211ULL) & MASK;
230 return (resource + result) & MASK;
233 auto evaluate(
const sourcemeta::core::JSON *target) ->
void {
234 Evaluation mark{.instance = target,
235 .evaluate_path = this->evaluate_path,
237 this->evaluated.push_back(std::move(mark));
240 [[nodiscard]]
auto is_evaluated(
const sourcemeta::core::JSON *target)
const
243 for (
auto iterator = this->evaluated.rbegin();
244 iterator != this->evaluated.rend(); ++iterator) {
245 if (target == iterator->instance && !iterator->skip &&
246 iterator->evaluate_path.starts_with_initial(this->evaluate_path)) {
254 auto unevaluate() ->
void {
255 for (
auto &entry : this->evaluated) {
256 if (!entry.skip && entry.evaluate_path.starts_with(this->evaluate_path)) {
267 [[nodiscard]]
auto checkpoint() const -> std::
size_t {
268 return this->evaluated.size();
271 auto rewind(
const std::size_t checkpoint) ->
void {
272 assert(checkpoint <= this->evaluated.size());
273 this->evaluated.resize(checkpoint);
277#pragma warning(disable : 4251 4275)
279 sourcemeta::core::WeakPointer evaluate_path;
280 sourcemeta::core::WeakPointer instance_location;
281 std::vector<std::size_t> resources;
284 const sourcemeta::core::JSON *instance;
285 sourcemeta::core::WeakPointer evaluate_path;
289 std::vector<Evaluation> evaluated;
291#pragma warning(default : 4251 4275)
300#include <sourcemeta/blaze/evaluator_dispatch.h>
302template <
bool Track,
bool Dynamic,
bool HasCallback>
303auto sourcemeta::blaze::Evaluator::evaluate_impl(
304 const Template &schema,
const sourcemeta::core::JSON &instance,
305 const Callback *callback) ->
bool {
306 assert(!schema.targets.empty());
307 dispatch::DispatchContext<Track, Dynamic, HasCallback> context{
309 .callback = callback,
311 .property_target =
nullptr};
313 for (
const auto &instruction : schema.targets[0]) {
314 if (!dispatch::evaluate_instruction(instruction, instance, 0, context))
321 if constexpr (Track || HasCallback) {
322 assert(this->evaluate_path.empty());
324 if constexpr (HasCallback) {
325 assert(this->instance_location.empty());
327 if constexpr (Dynamic) {
328 assert(this->resources.empty());
auto validate(const Template &schema, const sourcemeta::core::JSON &instance) -> bool
Definition evaluator.h:113
auto validate(const Template &schema, const sourcemeta::core::JSON &instance, const Callback &callback) -> bool
Definition evaluator.h:193
std::vector< std::string > messages
The message templates that instructions refer to, without duplicates.
Definition evaluator.h:47
std::vector< std::string > vocabularies
The vocabulary URIs that instructions refer to, without duplicates.
Definition evaluator.h:45
EvaluationType
Definition evaluator.h:60
std::function< void( const EvaluationType, bool, const Instruction &, const InstructionExtra &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::WeakPointer &, const sourcemeta::core::JSON &)> Callback
Definition evaluator.h:77
auto from_json(const sourcemeta::core::JSON &json) -> std::optional< Template >