mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 23:40:59 +00:00
ifcparse: map argument_type to its stored type, size() as size_t
Review: argument_type enumerates the members of type_variant_parameter_pack
in order, so express that once as argument_storage_type_t<A> (pinned by
static_asserts) and let attribute_value::size() on RocksDB go through a
single aggregate_size_<A>() helper instead of spelling each vector type
out in the switch. size() now returns size_t; its only caller already
took size_t.
Also build the RocksDB DeleteRange upper bounds as prefix + ('|' + 1)
rather than a literal '}', which read as the {id} placeholder notation.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HNrXDmR88wKPCYwGE21SyH
This commit is contained in:
@@ -135,6 +135,12 @@ namespace {
|
|||||||
#endif
|
#endif
|
||||||
throw std::logic_error("RocksDB storage is unavailable");
|
throw std::logic_error("RocksDB storage is unavailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<argument_type A>
|
||||||
|
inline size_t aggregate_size_(attribute_value::pointer_type array_, uint8_t storage_model_, size_t instance_name_, const ifcopenshell::declaration* entity_or_type, uint8_t index_)
|
||||||
|
{
|
||||||
|
return dispatch_get_<argument_storage_type_t<A>>(array_, storage_model_, instance_name_, entity_or_type, index_).size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute_value::operator int64_t() const
|
attribute_value::operator int64_t() const
|
||||||
@@ -289,10 +295,10 @@ bool attribute_value::isNull() const
|
|||||||
return dispatch_has_<blank>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
return dispatch_has_<blank>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int attribute_value::size() const
|
size_t attribute_value::size() const
|
||||||
{
|
{
|
||||||
if (storage_model_ == 0) {
|
if (storage_model_ == 0) {
|
||||||
return array_.storage_ptr->apply_visitor(size_visitor{}, index_);
|
return (size_t)array_.storage_ptr->apply_visitor(size_visitor{}, index_);
|
||||||
}
|
}
|
||||||
#ifdef IFOPSH_WITH_ROCKSDB
|
#ifdef IFOPSH_WITH_ROCKSDB
|
||||||
else {
|
else {
|
||||||
@@ -302,23 +308,23 @@ unsigned int attribute_value::size() const
|
|||||||
case Argument_AGGREGATE_OF_EMPTY_AGGREGATE:
|
case Argument_AGGREGATE_OF_EMPTY_AGGREGATE:
|
||||||
return 0;
|
return 0;
|
||||||
case Argument_AGGREGATE_OF_INT:
|
case Argument_AGGREGATE_OF_INT:
|
||||||
return (unsigned int)dispatch_get_<std::vector<int64_t>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_INT>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_DOUBLE:
|
case Argument_AGGREGATE_OF_DOUBLE:
|
||||||
return (unsigned int)dispatch_get_<std::vector<double>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_DOUBLE>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_STRING:
|
case Argument_AGGREGATE_OF_STRING:
|
||||||
return (unsigned int)dispatch_get_<std::vector<std::string>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_STRING>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_BINARY:
|
case Argument_AGGREGATE_OF_BINARY:
|
||||||
return (unsigned int)dispatch_get_<std::vector<boost::dynamic_bitset<>>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_BINARY>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_ENTITY_INSTANCE:
|
case Argument_AGGREGATE_OF_ENTITY_INSTANCE:
|
||||||
return (unsigned int)((std::vector<express::base>)*this).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_ENTITY_INSTANCE>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_AGGREGATE_OF_INT:
|
case Argument_AGGREGATE_OF_AGGREGATE_OF_INT:
|
||||||
return (unsigned int)dispatch_get_<std::vector<std::vector<int64_t>>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_AGGREGATE_OF_INT>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE:
|
case Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE:
|
||||||
return (unsigned int)dispatch_get_<std::vector<std::vector<double>>>(array_, storage_model_, instance_name_, entity_or_type_, index_).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
case Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE:
|
case Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE:
|
||||||
return (unsigned int)((std::vector<std::vector<express::base>>)*this).size();
|
return aggregate_size_<Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE>(array_, storage_model_, instance_name_, entity_or_type_, index_);
|
||||||
default:
|
default:
|
||||||
return (unsigned int)-1;
|
return (size_t)-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -215,12 +215,11 @@ void ifcopenshell::impl::rocks_db_file_storage::process_deletion_inverse(const e
|
|||||||
auto id = inst.id();
|
auto id = inst.id();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Delete every record referencing inst: all keys under v|{id}|. The
|
// Delete every record referencing inst: all keys under v|<id>|. The
|
||||||
// prefix with its last byte incremented is the exclusive upper bound
|
// exclusive upper bound is the same prefix with its separator
|
||||||
// ('}' follows '|'), so no iterator is needed to find the range end.
|
// incremented, so no iterator is needed to find the range end.
|
||||||
auto prefix = "v|" + std::to_string(id) + "|";
|
auto prefix = "v|" + std::to_string(id) + "|";
|
||||||
auto upper_bound = prefix;
|
auto upper_bound = "v|" + std::to_string(id) + std::string(1, '|' + 1);
|
||||||
upper_bound.back() = '}';
|
|
||||||
|
|
||||||
rocksdb::WriteBatch batch;
|
rocksdb::WriteBatch batch;
|
||||||
batch.DeleteRange(prefix, upper_bound);
|
batch.DeleteRange(prefix, upper_bound);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#undef Handle
|
#undef Handle
|
||||||
|
|
||||||
#include <rocksdb/db.h>
|
#include <rocksdb/db.h>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#pragma pop_macro("Handle")
|
#pragma pop_macro("Handle")
|
||||||
|
|
||||||
@@ -226,6 +227,24 @@ struct pack_to_variant_array<parameter_pack<Args...>> {
|
|||||||
|
|
||||||
using in_memory_attribute_storage = pack_to_variant_array<type_variant_parameter_pack>::type;
|
using in_memory_attribute_storage = pack_to_variant_array<type_variant_parameter_pack>::type;
|
||||||
|
|
||||||
|
// argument_type enumerates the members of type_variant_parameter_pack in
|
||||||
|
// order, so a member maps back to the type stored for it.
|
||||||
|
template <typename Pack>
|
||||||
|
struct pack_element;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
struct pack_element<parameter_pack<Args...>> {
|
||||||
|
template <size_t I>
|
||||||
|
using type = std::tuple_element_t<I, std::tuple<Args...>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <argument_type A>
|
||||||
|
using argument_storage_type_t = typename pack_element<type_variant_parameter_pack>::template type<A>;
|
||||||
|
|
||||||
|
static_assert(std::is_same_v<argument_storage_type_t<Argument_INT>, int64_t>, "argument_type must enumerate type_variant_parameter_pack in order");
|
||||||
|
static_assert(std::is_same_v<argument_storage_type_t<Argument_AGGREGATE_OF_INT>, std::vector<int64_t>>, "argument_type must enumerate type_variant_parameter_pack in order");
|
||||||
|
static_assert(std::is_same_v<argument_storage_type_t<Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE>, std::vector<std::vector<express::base>>>, "argument_type must enumerate type_variant_parameter_pack in order");
|
||||||
|
|
||||||
template <typename Pack>
|
template <typename Pack>
|
||||||
struct type_encoder_impl;
|
struct type_encoder_impl;
|
||||||
|
|
||||||
@@ -427,7 +446,7 @@ public:
|
|||||||
operator enumeration_reference() const;
|
operator enumeration_reference() const;
|
||||||
|
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
unsigned int size() const;
|
size_t size() const;
|
||||||
|
|
||||||
ifcopenshell::argument_type type() const;
|
ifcopenshell::argument_type type() const;
|
||||||
|
|
||||||
|
|||||||
@@ -197,17 +197,16 @@ public:
|
|||||||
return iterator();
|
return iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the element: every key under prefix + key + "|". The prefix
|
// Removes the element: every key under prefix + key + "|". The exclusive
|
||||||
// with its last byte incremented is the exclusive upper bound ('}'
|
// upper bound is the same prefix with its separator incremented. Returns
|
||||||
// follows '|'). Returns 1 if the element existed, 0 otherwise.
|
// 1 if the element existed, 0 otherwise.
|
||||||
size_t erase(const key_type& key) {
|
size_t erase(const key_type& key) {
|
||||||
#ifdef IFOPSH_WITH_ROCKSDB
|
#ifdef IFOPSH_WITH_ROCKSDB
|
||||||
if (find(key) == end()) {
|
if (find(key) == end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const std::string lower_bound = prefix_ + key_to_string(key) + "|";
|
const std::string lower_bound = prefix_ + key_to_string(key) + "|";
|
||||||
std::string upper_bound = lower_bound;
|
const std::string upper_bound = prefix_ + key_to_string(key) + std::string(1, '|' + 1);
|
||||||
upper_bound.back() = '}';
|
|
||||||
rocksdb::WriteBatch batch;
|
rocksdb::WriteBatch batch;
|
||||||
batch.DeleteRange(lower_bound, upper_bound);
|
batch.DeleteRange(lower_bound, upper_bound);
|
||||||
db_->Write(rocksdb::WriteOptions{}, &batch);
|
db_->Write(rocksdb::WriteOptions{}, &batch);
|
||||||
|
|||||||
Reference in New Issue
Block a user