| 235 | } |
| 236 | |
| 237 | IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t> name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index, bool coerce_attribute_count) { |
| 238 | std::vector<const IfcParse::parameter_type*> parameter_types; |
| 239 | std::unique_ptr<IfcParse::named_type> transient_named_type; |
| 240 | |
| 241 | if ((decl != nullptr) && (decl->as_type_declaration() != nullptr)) { |
| 242 | parameter_types = { decl->as_type_declaration()->declared_type() }; |
| 243 | } else if ((decl != nullptr) && (decl->as_enumeration_type() != nullptr)) { |
| 244 | transient_named_type.reset(new IfcParse::named_type(const_cast<IfcParse::declaration*>(decl))); |
| 245 | parameter_types = { &*transient_named_type }; |
| 246 | } else if ((decl != nullptr) && (decl->as_entity() != nullptr)) { |
| 247 | auto entity_attrs = decl->as_entity()->all_attributes(); |
| 248 | std::transform( |
| 249 | entity_attrs.begin(), |
| 250 | entity_attrs.end(), |
| 251 | std::back_inserter(parameter_types), |
| 252 | [](auto* attr) { |
| 253 | return attr->type_of_attribute(); |
| 254 | } |
| 255 | ); |
| 256 | } |
| 257 | |
| 258 | if (((decl != nullptr) && (tokens_.size() != parameter_types.size())) || |
| 259 | expected_size && *expected_size != tokens_.size()) |
| 260 | { |
| 261 | size_t expected = expected_size ? *expected_size : parameter_types.size(); |
| 262 | if (decl != nullptr && decl->schema() == &Header_section_schema::get_schema()) { |
| 263 | Logger::Warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for header entity " + decl->name()); |
| 264 | } else { |
| 265 | Logger::Warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + (name ? std::string(" for instance #" + std::to_string(*name)) : std::string(""))); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | if (tokens_.empty()) { |
| 270 | return IfcEntityInstanceData(in_memory_attribute_storage(0)); |
| 271 | } |
| 272 | |
| 273 | in_memory_attribute_storage storage(coerce_attribute_count |
| 274 | ? (decl != nullptr |
| 275 | ? (std::min)(parameter_types.size(), tokens_.size()) |
| 276 | : tokens_.size()) |
| 277 | : tokens_.size() |
| 278 | ); |
| 279 | |
| 280 | auto it = tokens_.begin(); |
| 281 | auto kt = parameter_types.begin(); |
| 282 | for (; it != tokens_.end() && ((decl == nullptr) || kt != parameter_types.end()); ++it) { |
| 283 | auto& token = *it; |
| 284 | // @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical |
| 285 | const IfcParse::parameter_type* param_type = nullptr; |
| 286 | if (decl != nullptr) { |
| 287 | param_type = *kt; |
| 288 | } |
| 289 | |
| 290 | auto index = (uint8_t) std::distance(tokens_.begin(), it); |
| 291 | |
| 292 | std::visit([this, &storage, name, &references_to_resolve, index, param_type, resolve_reference_index](const auto& v) { |
| 293 | if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) { |
| 294 | dispatch_token(name, index, v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](auto v) { |
no test coverage detected