Skip to content

Commit ed579f5

Browse files
authored
Try to use std::bitset for ValueTypes (#555)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent af2b977 commit ed579f5

11 files changed

Lines changed: 309 additions & 232 deletions

File tree

DEPENDENCIES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02
2-
core https://github.com/sourcemeta/core 10f0f36b678790354d3f67c73c686dfbd0e40231
2+
core https://github.com/sourcemeta/core 0e963f3e966143def590ebdb643ec6c07b7ebef7
33
jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite Test-JSON-Schema-Acceptance-1.033

src/compiler/default_compiler_draft4.h

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,14 @@ auto compiler_draft4_validation_type(const Context &context,
376376
return {};
377377
}
378378

379+
ValueTypes types{};
380+
types.set(static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
381+
types.set(
382+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
383+
types.set(
384+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
379385
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
380-
context, schema_context, dynamic_context,
381-
static_cast<ValueTypes>(
382-
(1U << static_cast<std::uint8_t>(
383-
sourcemeta::core::JSON::Type::Real)) |
384-
(1U << static_cast<std::uint8_t>(
385-
sourcemeta::core::JSON::Type::Integer)) |
386-
(1U << static_cast<std::uint8_t>(
387-
sourcemeta::core::JSON::Type::Decimal))))};
386+
context, schema_context, dynamic_context, types)};
388387
} else if (type == "integer") {
389388
if (context.mode == Mode::FastValidation &&
390389
schema_context.schema.defines("enum") &&
@@ -457,15 +456,14 @@ auto compiler_draft4_validation_type(const Context &context,
457456
context, schema_context, dynamic_context,
458457
sourcemeta::core::JSON::Type::Array)};
459458
} else if (type == "number") {
459+
ValueTypes types{};
460+
types.set(static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
461+
types.set(
462+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
463+
types.set(
464+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
460465
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
461-
context, schema_context, dynamic_context,
462-
static_cast<ValueTypes>(
463-
(1U << static_cast<std::uint8_t>(
464-
sourcemeta::core::JSON::Type::Real)) |
465-
(1U << static_cast<std::uint8_t>(
466-
sourcemeta::core::JSON::Type::Integer)) |
467-
(1U << static_cast<std::uint8_t>(
468-
sourcemeta::core::JSON::Type::Decimal))))};
466+
context, schema_context, dynamic_context, types)};
469467
} else if (type == "integer") {
470468
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrict,
471469
context, schema_context, dynamic_context,
@@ -478,40 +476,40 @@ auto compiler_draft4_validation_type(const Context &context,
478476
return {};
479477
}
480478
} else if (schema_context.schema.at(dynamic_context.keyword).is_array()) {
481-
ValueTypes types{0};
479+
ValueTypes types{};
482480
for (const auto &type :
483481
schema_context.schema.at(dynamic_context.keyword).as_array()) {
484482
assert(type.is_string());
485483
const auto &type_string{type.to_string()};
486484
if (type_string == "null") {
487-
types |= (1U << static_cast<std::uint8_t>(
488-
sourcemeta::core::JSON::Type::Null));
485+
types.set(
486+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Null));
489487
} else if (type_string == "boolean") {
490-
types |= (1U << static_cast<std::uint8_t>(
491-
sourcemeta::core::JSON::Type::Boolean));
488+
types.set(
489+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Boolean));
492490
} else if (type_string == "object") {
493-
types |= (1U << static_cast<std::uint8_t>(
494-
sourcemeta::core::JSON::Type::Object));
491+
types.set(
492+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Object));
495493
} else if (type_string == "array") {
496-
types |= (1U << static_cast<std::uint8_t>(
497-
sourcemeta::core::JSON::Type::Array));
494+
types.set(
495+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Array));
498496
} else if (type_string == "number") {
499-
types |= (1U << static_cast<std::uint8_t>(
500-
sourcemeta::core::JSON::Type::Integer));
501-
types |= (1U << static_cast<std::uint8_t>(
502-
sourcemeta::core::JSON::Type::Real));
503-
types |= (1U << static_cast<std::uint8_t>(
504-
sourcemeta::core::JSON::Type::Decimal));
497+
types.set(
498+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
499+
types.set(
500+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
501+
types.set(
502+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
505503
} else if (type_string == "integer") {
506-
types |= (1U << static_cast<std::uint8_t>(
507-
sourcemeta::core::JSON::Type::Integer));
504+
types.set(
505+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
508506
} else if (type_string == "string") {
509-
types |= (1U << static_cast<std::uint8_t>(
510-
sourcemeta::core::JSON::Type::String));
507+
types.set(
508+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::String));
511509
}
512510
}
513511

514-
assert(types != 0);
512+
assert(types.any());
515513
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
516514
context, schema_context, dynamic_context, types)};
517515
}
@@ -720,13 +718,13 @@ auto compiler_draft4_applicator_anyof(const Context &context,
720718
sourcemeta::blaze::InstructionIndex::
721719
AssertionTypeStrictAny);
722720
})) {
723-
ValueTypes types{0};
721+
ValueTypes types{};
724722
for (const auto &instruction : disjunctors) {
725723
if (instruction.children.front().type ==
726724
sourcemeta::blaze::InstructionIndex::AssertionTypeStrict) {
727725
const auto &value{
728726
*std::get_if<ValueType>(&instruction.children.front().value)};
729-
types |= (1U << static_cast<std::uint8_t>(value));
727+
types.set(static_cast<std::uint8_t>(value));
730728
}
731729

732730
if (instruction.children.front().type ==
@@ -737,18 +735,18 @@ auto compiler_draft4_applicator_anyof(const Context &context,
737735
}
738736
}
739737

740-
assert(types != 0);
741-
std::uint8_t popcount{0};
742-
for (std::uint8_t temp{types}; temp != 0; temp >>= 1) {
743-
popcount += (temp & 1);
744-
}
738+
assert(types.any());
739+
const auto popcount{types.count()};
745740
if (popcount > 1) {
746741
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
747742
context, schema_context, dynamic_context, types)};
748743
} else {
749744
std::uint8_t type_index{0};
750-
for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) {
751-
type_index++;
745+
for (std::uint8_t bit{0}; bit < 8; bit++) {
746+
if (types.test(bit)) {
747+
type_index = bit;
748+
break;
749+
}
752750
}
753751
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrict,
754752
context, schema_context, dynamic_context,

src/compiler/default_compiler_draft6.h

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,14 @@ auto compiler_draft6_validation_type(const Context &context,
165165
return {};
166166
}
167167

168+
ValueTypes types{};
169+
types.set(static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
170+
types.set(
171+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
172+
types.set(
173+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
168174
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
169-
context, schema_context, dynamic_context,
170-
static_cast<ValueTypes>(
171-
(1U << static_cast<std::uint8_t>(
172-
sourcemeta::core::JSON::Type::Real)) |
173-
(1U << static_cast<std::uint8_t>(
174-
sourcemeta::core::JSON::Type::Integer)) |
175-
(1U << static_cast<std::uint8_t>(
176-
sourcemeta::core::JSON::Type::Decimal))))};
175+
context, schema_context, dynamic_context, types)};
177176
} else if (type == "integer") {
178177
if (context.mode == Mode::FastValidation &&
179178
schema_context.schema.defines("enum") &&
@@ -262,15 +261,14 @@ auto compiler_draft6_validation_type(const Context &context,
262261
context, schema_context, dynamic_context,
263262
sourcemeta::core::JSON::Type::Array)};
264263
} else if (type == "number") {
264+
ValueTypes types{};
265+
types.set(static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
266+
types.set(
267+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
268+
types.set(
269+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
265270
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny,
266-
context, schema_context, dynamic_context,
267-
static_cast<ValueTypes>(
268-
(1U << static_cast<std::uint8_t>(
269-
sourcemeta::core::JSON::Type::Real)) |
270-
(1U << static_cast<std::uint8_t>(
271-
sourcemeta::core::JSON::Type::Integer)) |
272-
(1U << static_cast<std::uint8_t>(
273-
sourcemeta::core::JSON::Type::Decimal))))};
271+
context, schema_context, dynamic_context, types)};
274272
} else if (type == "integer") {
275273
return {make(sourcemeta::blaze::InstructionIndex::AssertionType, context,
276274
schema_context, dynamic_context,
@@ -287,44 +285,44 @@ auto compiler_draft6_validation_type(const Context &context,
287285
return {};
288286
}
289287
} else if (schema_context.schema.at(dynamic_context.keyword).is_array()) {
290-
ValueTypes types{0};
288+
ValueTypes types{};
291289
for (const auto &type :
292290
schema_context.schema.at(dynamic_context.keyword).as_array()) {
293291
assert(type.is_string());
294292
const auto &type_string{type.to_string()};
295293
if (type_string == "null") {
296-
types |= (1U << static_cast<std::uint8_t>(
297-
sourcemeta::core::JSON::Type::Null));
294+
types.set(
295+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Null));
298296
} else if (type_string == "boolean") {
299-
types |= (1U << static_cast<std::uint8_t>(
300-
sourcemeta::core::JSON::Type::Boolean));
297+
types.set(
298+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Boolean));
301299
} else if (type_string == "object") {
302-
types |= (1U << static_cast<std::uint8_t>(
303-
sourcemeta::core::JSON::Type::Object));
300+
types.set(
301+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Object));
304302
} else if (type_string == "array") {
305-
types |= (1U << static_cast<std::uint8_t>(
306-
sourcemeta::core::JSON::Type::Array));
303+
types.set(
304+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Array));
307305
} else if (type_string == "number") {
308-
types |= (1U << static_cast<std::uint8_t>(
309-
sourcemeta::core::JSON::Type::Integer));
310-
types |= (1U << static_cast<std::uint8_t>(
311-
sourcemeta::core::JSON::Type::Real));
312-
types |= (1U << static_cast<std::uint8_t>(
313-
sourcemeta::core::JSON::Type::Decimal));
306+
types.set(
307+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
308+
types.set(
309+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Real));
310+
types.set(
311+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Decimal));
314312
} else if (type_string == "integer") {
315-
types |= (1U << static_cast<std::uint8_t>(
316-
sourcemeta::core::JSON::Type::Integer));
313+
types.set(
314+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::Integer));
317315
} else if (type_string == "string") {
318316
if (dynamic_context.property_as_target) {
319317
continue;
320318
}
321319

322-
types |= (1U << static_cast<std::uint8_t>(
323-
sourcemeta::core::JSON::Type::String));
320+
types.set(
321+
static_cast<std::uint8_t>(sourcemeta::core::JSON::Type::String));
324322
}
325323
}
326324

327-
assert(types != 0);
325+
assert(types.any());
328326
return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeAny, context,
329327
schema_context, dynamic_context, types)};
330328
}

src/evaluator/dispatch.inc.h

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -268,16 +268,14 @@ INSTRUCTION_HANDLER(AssertionTypeAny) {
268268
SOURCEMETA_MAYBE_UNUSED(evaluator);
269269
EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeAny);
270270
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
271-
assert(value != 0);
271+
assert(value.any());
272272
const auto &target{get(instance, instruction.relative_instance_location)};
273273
// In non-strict mode, we consider a real number that represents an
274274
// integer to be an integer
275-
const auto type_bit{static_cast<std::uint8_t>(
276-
1U << static_cast<std::uint8_t>(target.type()))};
277-
if ((value & type_bit) != 0) {
275+
const auto type_index{static_cast<std::uint8_t>(target.type())};
276+
if (value.test(type_index)) {
278277
result = true;
279-
} else if ((value & (1U << static_cast<std::uint8_t>(JSON::Type::Integer))) !=
280-
0 &&
278+
} else if (value.test(static_cast<std::uint8_t>(JSON::Type::Integer)) &&
281279
target.is_integral()) {
282280
result = true;
283281
}
@@ -308,11 +306,11 @@ INSTRUCTION_HANDLER(AssertionTypeStrictAny) {
308306
SOURCEMETA_MAYBE_UNUSED(evaluator);
309307
EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStrictAny);
310308
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
311-
assert(value != 0);
309+
assert(value.any());
312310
const auto &target{get(instance, instruction.relative_instance_location)};
313-
const auto type_bit{static_cast<std::uint8_t>(
314-
1U << static_cast<std::uint8_t>(effective_type_strict_real(target)))};
315-
result = ((value & type_bit) != 0);
311+
const auto type_index{
312+
static_cast<std::uint8_t>(effective_type_strict_real(target))};
313+
result = value.test(type_index);
316314
EVALUATE_END(AssertionTypeStrictAny);
317315
}
318316

@@ -782,14 +780,12 @@ INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAny) {
782780
SOURCEMETA_MAYBE_UNUSED(evaluator);
783781
EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAny);
784782
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
785-
assert(value != 0);
783+
assert(value.any());
786784
// Now here we refer to the actual property
787-
const auto type_bit{static_cast<std::uint8_t>(
788-
1U << static_cast<std::uint8_t>(target_check->type()))};
785+
const auto type_index{static_cast<std::uint8_t>(target_check->type())};
789786
result =
790-
((value & type_bit) != 0) ||
791-
(((value & (1U << static_cast<std::uint8_t>(JSON::Type::Integer))) !=
792-
0) &&
787+
value.test(type_index) ||
788+
(value.test(static_cast<std::uint8_t>(JSON::Type::Integer)) &&
793789
target_check->is_decimal() && target_check->to_decimal().is_integer());
794790
EVALUATE_END(AssertionPropertyTypeStrictAny);
795791
}
@@ -803,11 +799,10 @@ INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAnyEvaluate) {
803799
SOURCEMETA_MAYBE_UNUSED(evaluator);
804800
EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAnyEvaluate);
805801
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
806-
assert(value != 0);
802+
assert(value.any());
807803
// Now here we refer to the actual property
808-
const auto type_bit{static_cast<std::uint8_t>(
809-
1U << static_cast<std::uint8_t>(target_check->type()))};
810-
result = ((value & type_bit) != 0);
804+
const auto type_index{static_cast<std::uint8_t>(target_check->type())};
805+
result = value.test(type_index);
811806

812807
if (result) {
813808
evaluator.evaluate(target_check);
@@ -2069,12 +2064,11 @@ INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAny) {
20692064
EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrictAny, target.is_object());
20702065
result = true;
20712066
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
2072-
assert(value != 0);
2067+
assert(value.any());
20732068
for (const auto &entry : target.as_object()) {
2074-
const auto type_bit{static_cast<std::uint8_t>(
2075-
1U << static_cast<std::uint8_t>(
2076-
effective_type_strict_real(entry.second)))};
2077-
if ((value & type_bit) == 0) {
2069+
const auto type_index{
2070+
static_cast<std::uint8_t>(effective_type_strict_real(entry.second))};
2071+
if (!value.test(type_index)) {
20782072
result = false;
20792073
break;
20802074
}
@@ -2094,12 +2088,11 @@ INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAnyEvaluate) {
20942088
target.is_object());
20952089
result = true;
20962090
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
2097-
assert(value != 0);
2091+
assert(value.any());
20982092
for (const auto &entry : target.as_object()) {
2099-
const auto type_bit{static_cast<std::uint8_t>(
2100-
1U << static_cast<std::uint8_t>(
2101-
effective_type_strict_real(entry.second)))};
2102-
if ((value & type_bit) == 0) {
2093+
const auto type_index{
2094+
static_cast<std::uint8_t>(effective_type_strict_real(entry.second))};
2095+
if (!value.test(type_index)) {
21032096
result = false;
21042097
EVALUATE_END(LoopPropertiesTypeStrictAnyEvaluate);
21052098
}
@@ -2344,13 +2337,13 @@ INSTRUCTION_HANDLER(LoopItemsTypeStrictAny) {
23442337
SOURCEMETA_MAYBE_UNUSED(evaluator);
23452338
EVALUATE_BEGIN_NON_STRING(LoopItemsTypeStrictAny, target.is_array());
23462339
const auto value{*std::get_if<ValueTypes>(&instruction.value)};
2347-
assert(value != 0);
2340+
assert(value.any());
23482341

23492342
result = true;
23502343
for (const auto &entry : target.as_array()) {
2351-
const auto type_bit{static_cast<std::uint8_t>(
2352-
1U << static_cast<std::uint8_t>(effective_type_strict_real(entry)))};
2353-
if ((value & type_bit) == 0) {
2344+
const auto type_index{
2345+
static_cast<std::uint8_t>(effective_type_strict_real(entry))};
2346+
if (!value.test(type_index)) {
23542347
result = false;
23552348
break;
23562349
}

0 commit comments

Comments
 (0)