Skip to content

Commit d6685df

Browse files
mcb5637liss-h
authored andcommitted
container mapping
1 parent 46c25ae commit d6685df

3 files changed

Lines changed: 99 additions & 56 deletions

File tree

private/rdf4cpp/parser/JsonLdContextParser.cpp

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ namespace rdf4cpp::parser::json_ld {
322322
if (t.value().get(v) != simdjson::SUCCESS || v != keyword_set) {
323323
return make_error(ParsingError::Type::BadSyntax, "keyword redefinition (@type invalid @container)");
324324
}
325-
p.term.container_mapping.emplace_back(keyword_set);
325+
p.term.container_mapping |= ContainerMapping::Set;
326326
any = true;
327327
} else if (k == keyword_protected) {
328328
bool v;
@@ -504,7 +504,7 @@ namespace rdf4cpp::parser::json_ld {
504504
return make_error(ParsingError::Type::BadSyntax, "invalid reverse property");
505505
}
506506
if (v_cont.is_null()) {
507-
p.term.container_mapping.clear();
507+
p.term.container_mapping = ContainerMapping::None;
508508
} else {
509509
std::string_view cont;
510510
if (v_cont.get(cont) != simdjson::SUCCESS) {
@@ -513,8 +513,7 @@ namespace rdf4cpp::parser::json_ld {
513513
if (cont != keyword_set && cont != keyword_index) {
514514
return make_error(ParsingError::Type::BadSyntax, "invalid reverse property");
515515
}
516-
p.term.container_mapping.clear();
517-
p.term.container_mapping.emplace_back(cont);
516+
p.term.container_mapping = keyword_to_container_mapping(cont);
518517
}
519518
}
520519

@@ -592,72 +591,63 @@ namespace rdf4cpp::parser::json_ld {
592591
}
593592
}
594593
}
595-
auto container_contains = [&](std::string_view x) {
596-
return std::ranges::find(p.term.container_mapping, x) != p.term.container_mapping.end();
597-
};
598594
{ // 19
599595
auto [c, v] = try_get_field<simdjson::ondemand::value>(ob, keyword_container);
600596
if (c != simdjson::NO_SUCH_FIELD) {
601-
auto is_valid_keyword = [](std::string_view v) {
602-
static constexpr std::array valid = {keyword_graph, keyword_id, keyword_index, keyword_language, keyword_list, keyword_set, keyword_type};
603-
return std::ranges::any_of(valid, [v](std::string_view a) {
604-
return a == v;
605-
});
606-
};
607597
if (v.is_string()) {
608-
auto d = static_cast<std::string_view>(v);
609-
if (!is_valid_keyword(d)) {
598+
auto d = keyword_to_container_mapping(static_cast<std::string_view>(v));
599+
if (d == ContainerMapping::None) {
610600
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
611601
}
612-
p.term.container_mapping.clear();
613-
p.term.container_mapping.emplace_back(d);
602+
p.term.container_mapping = d;
614603
} else {
615604
simdjson::ondemand::array a;
616605
if (v.get(a) != simdjson::SUCCESS) {
617606
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
618607
}
619-
p.term.container_mapping.clear();
608+
p.term.container_mapping = ContainerMapping::None;
620609
for (auto w : a) {
621610
std::string_view x;
622611
if (w.get(x) != simdjson::SUCCESS) {
623612
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
624613
}
625-
if (!is_valid_keyword(x)) {
614+
auto container_mapping = keyword_to_container_mapping(x);
615+
if (container_mapping == ContainerMapping::None) {
626616
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
627617
}
628-
p.term.container_mapping.emplace_back(x);
618+
p.term.container_mapping |= container_mapping;
629619
}
630620
}
631-
if (p.term.container_mapping.empty()) {
621+
if (p.term.container_mapping == ContainerMapping::None) {
632622
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
633623
}
634-
if (p.term.container_mapping.size() > 1) {
635-
auto only = [&](std::initializer_list<std::string_view> x) {
636-
return std::ranges::all_of(p.term.container_mapping, [&](std::string_view d) {
637-
return std::ranges::any_of(x, [&](std::string_view a) {
638-
return a == d;
639-
});
640-
});
624+
if (p.term.container_mapping_size() > 1) {
625+
auto only = [&](std::initializer_list<ContainerMapping> x) {
626+
ContainerMapping check = ContainerMapping::None;
627+
for (auto e : x) {
628+
check |= e;
629+
}
630+
return (p.term.container_mapping & ~check) == ContainerMapping::None;
641631
};
642-
bool graph = container_contains(keyword_graph);
632+
bool graph = p.term.has_container_mapping(ContainerMapping::Graph);
643633
if (graph) {
644-
auto id = container_contains(keyword_id);
645-
auto index = container_contains(keyword_index);
634+
auto id = p.term.has_container_mapping(ContainerMapping::Id);
635+
auto index = p.term.has_container_mapping(ContainerMapping::Index);
646636
if (index == id) { // xor
647637
graph = false;
648638
} else {
649-
graph = only({keyword_graph, keyword_id, keyword_index, keyword_set});
639+
graph = only({ContainerMapping::Graph, ContainerMapping::Id, ContainerMapping::Index, ContainerMapping::Set});
650640
}
651641
}
652-
bool set = container_contains(keyword_set);
642+
bool set = p.term.has_container_mapping(ContainerMapping::Set);
653643
if (set) {
654-
set = only({keyword_set, keyword_index, keyword_graph, keyword_id, keyword_type, keyword_language});
644+
set = only({ContainerMapping::Set, ContainerMapping::Index, ContainerMapping::Graph, ContainerMapping::Id, ContainerMapping::Type, ContainerMapping::Language});
655645
}
656646
if (!set && !graph) {
657647
return make_error(ParsingError::Type::BadSyntax, "invalid container mapping");
658648
}
659649
}
660-
if (container_contains(keyword_type)) {
650+
if (p.term.has_container_mapping(ContainerMapping::Type)) {
661651
if (!p.term.type_mapping.has_value()) {
662652
p.term.type_mapping = keyword_id;
663653
}
@@ -673,7 +663,7 @@ namespace rdf4cpp::parser::json_ld {
673663
if (c != simdjson::SUCCESS) {
674664
return make_error(ParsingError::Type::BadSyntax, "invalid term definition");
675665
}
676-
if (!container_contains(keyword_index)) {
666+
if (!p.term.has_container_mapping(ContainerMapping::Index)) {
677667
return make_error(ParsingError::Type::BadSyntax, "invalid term definition");
678668
}
679669
params::ParseContextIRIExpansionParams p_ctx{

private/rdf4cpp/parser/JsonLdExpandParser.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ namespace rdf4cpp::parser::json_ld {
659659
expanded_value.is_json_literal = true;
660660
}
661661
// 13.7
662-
else if (term_definition != nullptr && term_definition->has_container_mapping(keyword_language) && v.type() == simdjson::ondemand::json_type::object) {
662+
else if (term_definition != nullptr && term_definition->has_container_mapping(ContainerMapping::Language) && v.type() == simdjson::ondemand::json_type::object) {
663663
expanded_value.path = p.active_path;
664664
expanded_value.path.keys.emplace_back(std::in_place_type<std::string>, k);
665665
expanded_value.language_map = p.active_ctx.base_direction;
@@ -668,7 +668,7 @@ namespace rdf4cpp::parser::json_ld {
668668
}
669669
}
670670
// 13.8
671-
else if (term_definition != nullptr && (term_definition->has_container_mapping(keyword_index) || term_definition->has_container_mapping(keyword_type) || term_definition->has_container_mapping(keyword_id))
671+
else if (term_definition != nullptr && (term_definition->has_container_mapping(ContainerMapping::Index) || term_definition->has_container_mapping(ContainerMapping::Type) || term_definition->has_container_mapping(ContainerMapping::Id))
672672
&& v.type() == simdjson::ondemand::json_type::object) {
673673

674674
// 13.8.2
@@ -687,7 +687,7 @@ namespace rdf4cpp::parser::json_ld {
687687

688688
Context const *map_context = nullptr;
689689
// 13.8.3.1
690-
if (term_definition->has_container_mapping(keyword_id) || term_definition->has_container_mapping(keyword_type)) {
690+
if (term_definition->has_container_mapping(ContainerMapping::Id) || term_definition->has_container_mapping(ContainerMapping::Type)) {
691691
map_context = p.active_ctx.previous_context;
692692
}
693693
// 13.8.3.1&3
@@ -696,7 +696,7 @@ namespace rdf4cpp::parser::json_ld {
696696
}
697697

698698
// 13.8.3.2
699-
if (term_definition->has_container_mapping(keyword_type)) {
699+
if (term_definition->has_container_mapping(ContainerMapping::Type)) {
700700
auto *index_term = map_context->try_find_term(index);
701701
if (index_term != nullptr && index_term->context.has_value()) {
702702
auto r = context_parser.parse_local_context(simdjson::padded_string_view{*index_term->context}, {
@@ -725,7 +725,7 @@ namespace rdf4cpp::parser::json_ld {
725725
ExpandedMap *next_lvl = nullptr;
726726
std::optional<simdjson::ondemand::object> index_value_obj = std::nullopt;
727727
// 13.8.3.7.1
728-
if (term_definition->has_container_mapping(keyword_graph) && !is_graph_object(index_value, p.active_ctx, index_value_obj)) {
728+
if (term_definition->has_container_mapping(ContainerMapping::Graph) && !is_graph_object(index_value, p.active_ctx, index_value_obj)) {
729729
ex.next_level_pre_expanded = ExpandedMap{};
730730
next_lvl = &std::get<ExpandedMap>(*ex.next_level_pre_expanded);
731731
auto &ge = next_lvl->entries.emplace_back(IRIMapping{std::string{keyword_graph}, IRIMappingType::Keyword});
@@ -761,7 +761,7 @@ namespace rdf4cpp::parser::json_ld {
761761
return next_lvl != nullptr && next_lvl->try_find_keyword(kwo) != nullptr;
762762
};
763763
// 13.8.3.7.2
764-
if (term_definition->has_container_mapping(keyword_index) && !index_key.is_keyword(keyword_index) && !expanded_index->is_keyword(keyword_none)) {
764+
if (term_definition->has_container_mapping(ContainerMapping::Index) && !index_key.is_keyword(keyword_index) && !expanded_index->is_keyword(keyword_none)) {
765765
auto reexpanded_index = value_expansion(p.active_ctx, index_key, index);
766766
if (!reexpanded_index.has_value()) {
767767
return reexpanded_index.error();
@@ -777,12 +777,12 @@ namespace rdf4cpp::parser::json_ld {
777777
e.pre_expanded_value = std::move(*reexpanded_index);
778778
}
779779
// 13.8.3.7.3
780-
else if (term_definition->has_container_mapping(keyword_index) && !has_keyword(keyword_index)
780+
else if (term_definition->has_container_mapping(ContainerMapping::Index) && !has_keyword(keyword_index)
781781
&& !expanded_index->is_keyword(keyword_none)) {
782782
// skipped, @index is ignored
783783
}
784784
// 13.8.3.7.4
785-
else if (term_definition->has_container_mapping(keyword_id) && !has_keyword(keyword_id)
785+
else if (term_definition->has_container_mapping(ContainerMapping::Id) && !has_keyword(keyword_id)
786786
&& !expanded_index->is_keyword(keyword_none)) {
787787
auto id = context_parser.iri_expansion(p.active_ctx, index, true, false);
788788
if (!id.has_value()) {
@@ -795,7 +795,7 @@ namespace rdf4cpp::parser::json_ld {
795795
e.keyword_values.emplace_back(std::move(*id));
796796
}
797797
// 13.8.3.7.5
798-
else if (term_definition->has_container_mapping(keyword_type) && !expanded_index->is_keyword(keyword_none)) {
798+
else if (term_definition->has_container_mapping(ContainerMapping::Type) && !expanded_index->is_keyword(keyword_none)) {
799799
if (next_lvl == nullptr) {
800800
return make_error(ParsingError::Type::BadSyntax, "invalid value object (attempting to add invalid type)");
801801
}
@@ -829,12 +829,12 @@ namespace rdf4cpp::parser::json_ld {
829829
continue;
830830
}
831831
// 13.11
832-
if (term_definition != nullptr && term_definition->has_container_mapping(keyword_list) && !is_list_object(v, p.active_ctx)) {
832+
if (term_definition != nullptr && term_definition->has_container_mapping(ContainerMapping::List) && !is_list_object(v, p.active_ctx)) {
833833
expanded_value.as_list = true;
834834
}
835835
// 13.12
836-
if (term_definition != nullptr && term_definition->has_container_mapping(keyword_graph)
837-
&& !term_definition->has_container_mapping(keyword_id) && !term_definition->has_container_mapping(keyword_index)) {
836+
if (term_definition != nullptr && term_definition->has_container_mapping(ContainerMapping::Graph)
837+
&& !term_definition->has_container_mapping(ContainerMapping::Id) && !term_definition->has_container_mapping(ContainerMapping::Index)) {
838838
if (v.type() == simdjson::ondemand::json_type::array) {
839839
expanded_value.as_multiple_graphs = true;
840840
} else {

private/rdf4cpp/parser/JsonLdParserTypes.hpp

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ namespace rdf4cpp::parser {
8484
constexpr auto operator<=>(NotSet const &) const = default;
8585
};
8686

87-
enum class BaseDirection : uint8_t {
87+
enum struct BaseDirection : uint8_t {
8888
None,
8989
Ltr,
9090
Rtl,
9191
};
9292
std::optional<BaseDirection> try_parse_base_direction(std::string_view d);
9393

9494
// corresponds to the defined map from the context parsing algorithms.
95-
enum class ParseState : uint8_t {
95+
enum struct ParseState : uint8_t {
9696
// not in the map
9797
NotStarted,
9898
// false
@@ -101,7 +101,7 @@ namespace rdf4cpp::parser {
101101
Done,
102102
};
103103

104-
enum class IRIMappingType : uint8_t {
104+
enum struct IRIMappingType : uint8_t {
105105
None,
106106
IRI,
107107
BlankNode,
@@ -176,18 +176,70 @@ namespace rdf4cpp::parser {
176176
}
177177
};
178178

179+
enum struct ContainerMapping : uint8_t {
180+
None = 0,
181+
Graph = 1 << 0,
182+
Id = 1 << 1,
183+
Index = 1 << 2,
184+
Language = 1 << 3,
185+
List = 1 << 4,
186+
Set = 1 << 5,
187+
Type = 1 << 6,
188+
};
189+
// ReSharper disable once CppDFAUnreachableFunctionCall
190+
constexpr ContainerMapping operator|(ContainerMapping a, ContainerMapping b) {
191+
return static_cast<ContainerMapping>(static_cast<std::underlying_type_t<ContainerMapping>>(a) | static_cast<std::underlying_type_t<ContainerMapping>>(b));
192+
}
193+
constexpr ContainerMapping& operator|=(ContainerMapping& a, ContainerMapping b) {
194+
a = a | b;
195+
return a;
196+
}
197+
constexpr ContainerMapping operator&(ContainerMapping a, ContainerMapping b) {
198+
return static_cast<ContainerMapping>(static_cast<std::underlying_type_t<ContainerMapping>>(a) & static_cast<std::underlying_type_t<ContainerMapping>>(b));
199+
}
200+
constexpr ContainerMapping operator^(ContainerMapping a, ContainerMapping b) {
201+
return static_cast<ContainerMapping>(static_cast<std::underlying_type_t<ContainerMapping>>(a) | static_cast<std::underlying_type_t<ContainerMapping>>(b));
202+
}
203+
constexpr ContainerMapping operator~(ContainerMapping a) {
204+
return static_cast<ContainerMapping>(~static_cast<std::underlying_type_t<ContainerMapping>>(a));
205+
}
206+
constexpr ContainerMapping keyword_to_container_mapping(std::string_view k) {
207+
if (k == keyword_graph) {
208+
return ContainerMapping::Graph;
209+
}
210+
else if (k == keyword_id) {
211+
return ContainerMapping::Id;
212+
}
213+
else if (k == keyword_index) {
214+
return ContainerMapping::Index;
215+
}
216+
else if (k == keyword_language) {
217+
return ContainerMapping::Language;
218+
}
219+
else if (k == keyword_list) {
220+
return ContainerMapping::List;
221+
}
222+
else if (k == keyword_set) {
223+
return ContainerMapping::Set;
224+
}
225+
else if (k == keyword_type) {
226+
return ContainerMapping::Type;
227+
}
228+
return ContainerMapping::None;
229+
}
230+
179231
// part of the term definition that needs to be compared for protection checks
180232
struct TermDefinitionBase {
181233
std::string key;
182234
IRIMapping iri_mapping;
183235
std::optional<std::string> base_iri;
184236
// needs to be padded during parent context parse
185237
std::optional<std::string> context;
186-
std::vector<std::string> container_mapping;
187238
IRIMapping index_mapping;
188239
LanguageMapping language_mapping = NotSet{};
189240
std::optional<std::string> nest_value;
190241
std::optional<std::string> type_mapping;
242+
ContainerMapping container_mapping = ContainerMapping::None;
191243
BaseDirection direction_mapping = BaseDirection::None;
192244
bool is_prefix = false;
193245
bool is_reverse_property = false;
@@ -199,10 +251,11 @@ namespace rdf4cpp::parser {
199251
: key{k} {
200252
}
201253

202-
[[nodiscard]] constexpr bool has_container_mapping(std::string_view m) const {
203-
return std::ranges::any_of(container_mapping, [&](auto const &e) {
204-
return e == m;
205-
});
254+
[[nodiscard]] constexpr bool has_container_mapping(ContainerMapping m) const {
255+
return (m & container_mapping) != ContainerMapping::None;
256+
}
257+
[[nodiscard]] constexpr int container_mapping_size() const {
258+
return std::popcount(static_cast<std::underlying_type_t<ContainerMapping>>(container_mapping));
206259
}
207260
};
208261
struct TermDefinition : TermDefinitionBase {

0 commit comments

Comments
 (0)