41#ifndef GEOGRAM_BASIC_ATTRIBUTES
42#define GEOGRAM_BASIC_ATTRIBUTES
50#include <geogram/basic/logger.h>
77 base_addr_(nullptr), size_(0), dimension_(0),
78 disconnected_(false) {
91 base_addr_ = base_addr;
119 return size_ * dimension_;
150 base_addr_ =
nullptr;
153 disconnected_ =
true;
163 return disconnected_;
206 std::string element_type_name_;
207 std::string element_typeid_name_;
250 const std::string& type_name
283 return cached_capacity_;
304 virtual void clear(
bool keep_memory =
false) = 0;
312 return !observers_.empty();
395 size_t item_size = element_size_ * dimension_;
396 if(lifecycle_.is_null()) {
398 cached_base_addr_+to*item_size,
399 cached_base_addr_+from*item_size,
404 cached_base_addr_+to*item_size,
405 cached_base_addr_+from*item_size
416 size_t item_size = element_size_ * dimension_;
417 if(lifecycle_.is_null()) {
419 cached_base_addr_+to*item_size,
423 lifecycle_->reset(cached_base_addr_+to*item_size);
457 return cached_base_addr_;
465 return cached_base_addr_;
473 return element_size_;
485 const std::string& element_type_name
488 type_name_to_creator_.find(element_type_name) !=
489 type_name_to_creator_.end()
502 const std::string& element_typeid_name
505 typeid_name_to_type_name_.find(element_typeid_name) !=
506 typeid_name_to_type_name_.end()
520 const std::string& element_type_name
524 type_name_to_creator_[
526 ]->elements_are_trivially_copyable()
540 const std::string& element_typeid_name
543 std::string element_type_name =
544 typeid_name_to_type_name_[element_typeid_name];
545 return element_by_type_name_is_trivially_copyable(element_type_name);
555 const std::string& element_type_name,
558 geo_assert(element_type_name_is_known(element_type_name));
559 return type_name_to_creator_[element_type_name]->
560 create_attribute_store(dimension);
571 const std::string& element_typeid_name
573 geo_assert(element_typeid_name_is_known(element_typeid_name));
574 return typeid_name_to_type_name_[element_typeid_name];
586 const std::string& element_type_name
588 geo_assert(element_type_name_is_known(element_type_name));
589 return type_name_to_typeid_name_[element_type_name];
604 const std::string& element_type_name,
605 const std::string& element_typeid_name
663 size_t element_size_;
669 std::set<AttributeStoreObserver*> observers_;
672 static std::map<std::string, AttributeStoreCreator_var>
673 type_name_to_creator_;
675 static std::map<std::string, std::string>
676 typeid_name_to_type_name_;
678 static std::map<std::string, std::string>
679 type_name_to_typeid_name_;
705 index_t dim=1,
const std::type_info& user_type_info =
typeid(ST)
708 storage_type_(typeid(ST)),
709 user_type_(user_type_info) {
710 if(!std::is_trivially_copyable<ST>::value) {
716 store_.resize(new_size*dimension_);
726 store_.reserve(new_capacity*dimension_);
727 cached_capacity_ = new_capacity;
736 void clear(
bool keep_memory=
false)
override {
742 notify(
nullptr, 0, dimension_);
753 for(
index_t c = 0; c < copy_dim; ++c) {
754 new_store[dim * i + c] = store_[dimension_ * i + c];
757 store_.swap(new_store);
767 type_name == storage_type_.name() ||
768 type_name == user_type_.name()
773 return storage_type_.name();
777 return user_type_.name();
784 result->store_ = store_;
785 result->lifecycle_ = lifecycle_;
795 for(
index_t i=0; i<dimension_; ++i) {
796 scale_value(store_[to*dimension_+i], s);
803 for(
index_t i=0; i<dimension_; ++i) {
805 store_[to*dimension_+i], s, store_[from*dimension_+i]
818 template<
class TT>
static void scale_value(TT& to,
double s) {
823 static void scale_value(uint8_t& to,
double s) {
824 to = uint8_t(
double(to)*s != 0.0);
827 static void scale_value(int32_t& to,
double s) {
828 to = int32_t(
double(to)*s);
831 static void scale_value(uint32_t& to,
double s) {
832 to = uint32_t(
double(to)*s);
835 static void scale_value(
float& to,
double s) {
836 to = float(
double(to)*s);
839 static void scale_value(
double& to,
double s) {
843 template<
class TT>
static void madd_value(TT& to,
double s, TT& from) {
849 static void madd_value(uint8_t& to,
double s, uint8_t& from) {
850 to = uint8_t(
double(to) + s*
double(from) != 0.0);
853 static void madd_value(int32_t& to,
double s, int32_t& from) {
854 to = int32_t(
double(to) + s*
double(from));
857 static void madd_value(uint32_t& to,
double s, uint32_t& from) {
858 to = uint32_t(
double(to) + s*
double(from));
861 static void madd_value(
float& to,
double s,
float& from) {
862 to = float(
double(to) + s*
double(from));
865 static void madd_value(
double& to,
double s,
double& from) {
871 const std::type_info& storage_type_;
872 const std::type_info& user_type_;
882 template <
class UT,
class ST=UT>
896 return(std::is_trivially_copyable<ST>::value);
923 type_name,
typeid(UT).name()
925 if(type_name ==
"bool") {
934 read_ascii_attribute<UT>,
935 write_ascii_attribute<UT>
966 return index_t(attributes_.size());
1019 void clear(
bool keep_attributes,
bool keep_memory =
false);
1052 const std::string& name
1063 return (find_attribute_store(name) !=
nullptr);
1173 const std::string& name,
const std::string& new_name
1185 const std::string& old_name,
const std::string& new_name
1210 std::map<std::string, AttributeStore*> attributes_;
1223 template <
class UT,
class ST = UT>
1233 existed_already_(false) {
1248 existed_already_(false) {
1258 return (store_ !=
nullptr && !disconnected_);
1269 return existed_already_;
1281 if(!disconnected_) {
1286 existed_already_ =
false;
1302 if(store_ ==
nullptr) {
1305 existed_already_ =
false;
1308 existed_already_ =
true;
1328 if(store_ !=
nullptr) {
1331 existed_already_ =
true;
1334 existed_already_ =
false;
1353 if(store_ !=
nullptr) {
1354 existed_already_ =
true;
1363 existed_already_ =
false;
1375 const std::string& name,
1411 store_->
redim(new_dim);
1443 ((dim == 0) || (store->
dimension() == dim))
1493 return typed_store->get_vector();
1506 return typed_store->get_vector();
1535 bool existed_already_;
1577 return ((T*)(
void*)superclass::base_addr_)[i];
1588 return ((
const T*)(
void*)superclass::base_addr_)[i];
1613 (*this)[i] = rhs[i];
1622 return (T*)AttributeStoreObserver::base_addr_;
1630 return (
const T*)AttributeStoreObserver::base_addr_;
1667 class BoolAttributeAccessor;
1673 class ConstBoolAttributeAccessor {
1682 attribute_(&attribute),
1691 return (attribute_->element(index_) != 0);
1698 friend class BoolAttributeAccessor;
1705 class BoolAttributeAccessor {
1714 attribute_(&attribute),
1723 return (attribute_->element(index_) != 0);
1732 attribute_ = rhs.attribute_;
1733 index_ = rhs.index_;
1751 const BoolAttributeAccessor& rhs
1754 attribute_->element(index_) =
1755 rhs.attribute_->element(rhs.index_);
1766 const ConstBoolAttributeAccessor& rhs
1768 attribute_->element(index_) =
1769 rhs.attribute_->element(rhs.index_);
1780 return BoolAttributeAccessor(*
this,i);
1784 return ConstBoolAttributeAccessor(*
this,i);
1808 element(i) = rhs.element(i);
1814 friend class BoolAttributeAccessor;
1815 friend class ConstBoolAttributeAccessor;
1883 ) : attribute_(attribute), index_(index) {
1886 operator double()
const {
1887 return attribute_.get_element_as_double(index_);
1890 void operator=(
double x) {
1891 attribute_.set_element_as_double(index_, x);
1908 ) : attribute_(attribute), index_(index) {
1911 operator double()
const {
1912 return attribute_.get_element_as_double(index_);
1926 element_type_(ET_NONE),
1944 bind_if_is_defined(manager, name);
1953 return (store_ !=
nullptr);
1965 element_type_ = ET_NONE;
2013 return (store_ ==
nullptr) ? 0 : store_->size();
2024 return element_type_;
2034 return element_index_;
2054 return element_type(store) != ET_NONE;
2104 double result = 0.0;
2105 switch(element_type()) {
2107 result = double(get_element<Numeric::uint8>(i));
2110 result = double(get_element<Numeric::int8>(i));
2113 result = double(get_element<Numeric::uint32>(i));
2116 result = double(get_element<Numeric::int32>(i));
2119 result = double(get_element<Numeric::float32>(i));
2122 result = double(get_element<Numeric::float64>(i));
2125 result = double(get_element<Numeric::float64>(i,2));
2128 result = double(get_element<Numeric::float64>(i,3));
2147 return static_cast<const T*
>(store_->data())[
2148 (i * store_->dimension() * multiplier) +
2160 double result = 0.0;
2161 switch(element_type()) {
2206 const_cast<T*
>(
static_cast<const T*
>(store_->data()))[
2207 (i * store_->dimension() * multiplier) +
2215 ElementType element_type_;
#define geo_assert_not_reached
Sets a non reachable point in the program.
#define geo_assert(x)
Verifies that a condition is met.
#define geo_debug_assert(x)
Verifies that a condition is met.
Base class for Attributes, that manipulates an attribute stored in an AttributesManager.
bool can_get_vector()
Tests whether get_vector() can be called on this Attribute.
void zero()
Sets all the elements of this Attribute to zero.
void bind(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager.
AttributeBase(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
vector< ST > & get_vector()
Gets a reference to the internal vector<T> used to store the attribute.
bool bind_if_is_compatible(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager and types ...
bool is_bound() const
Tests whether an Attribute is bound.
void redim(index_t new_dim)
Sets the dimension.
static bool can_bind_to(const AttributeStore *store)
Tests whether this Attribute can be bound to an AttributeStore.
AttributeBase()
Creates an uninitialized (unbound) Attribute.
AttributesManager * manager() const
Gets the AttributesManager this Attribute is bound to.
void destroy()
Destroys this attribute in the AttributesManager.
static bool is_defined(AttributesManager &manager, const std::string &name, index_t dim=0)
Tests whether an attribute with the specified name and with corresponding type exists in an Attribute...
~AttributeBase()
Attribute destructor.
index_t size() const
Gets the size.
bool existed_already() const
Tests whether the latest bound attribute existed already.
void unbind()
Unbinds this Attribute.
const vector< ST > & get_vector() const
Gets a const reference to the internal vector<T> used to store the attribute.
bool bind_if_is_defined(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
void create_vector_attribute(AttributesManager &manager, const std::string &name, index_t dimension)
Creates and binds a new vector attribute.
Internal class for creating an AttributeStore from the type name of its elements.
~AttributeStoreCreator() override
AttributeStoreCreator destructor.
virtual bool elements_are_trivially_copyable() const =0
Tests whether elements of this attribute can be trivially copyable.
virtual AttributeStore * create_attribute_store(index_t dimension)=0
Creates a new attribute store.
Base class for attributes. They are notified whenever the AttributeStore is modified.
AttributeStoreObserver()
Creates a new uninitialied AttributeStore.
void register_me(AttributeStore *store)
Registers this observer to an AttributeStore.
index_t size() const
Gets the size.
void notify(Memory::pointer base_addr, index_t size, index_t dim)
Callback function, called by the AttributeStore whenever it is modified.
index_t nb_elements() const
Gets the total number of elements.
bool disconnected() const
Tests whether this AttributeStoreObserver was disconnected.
void disconnect()
Disconnects this AttributeStoreObserver from its AttributeStore.
void unregister_me(AttributeStore *store)
Unregisters this observer from an AttributeStore.
index_t dimension() const
Gets the dimension.
Memory::pointer base_addr() const
Gets a pointer to the storage.
Notifies a set of AttributeStoreObservers each time the stored array changes size and/or base address...
void * data()
Gets a pointer to the stored data.
static AttributeStore * create_attribute_store_by_element_type_name(const std::string &element_type_name, index_t dimension)
Creates an attribute store of a given type.
bool has_observers() const
Tests whether observers listen to this AttributeStore.
void zero_item(index_t to)
Sets an item to zero.
virtual ~AttributeStore()
AttributeStore destructor.
static std::string element_typeid_name_by_element_type_name(const std::string &element_type_name)
Gets an element mangled type name from its C++ name.
static void register_attribute_creator(AttributeStoreCreator *creator, const std::string &element_type_name, const std::string &element_typeid_name)
Registers a new element type.
index_t size() const
Gets the size.
const void * data() const
Gets a pointer to the stored data.
virtual void clear(bool keep_memory=false)=0
Resizes this AttributeStore to 0.
virtual void notify(Memory::pointer base_addr, index_t size, index_t dim)
If size or base address differ from the cached values, notify all the observers, and update the cache...
AttributeStore(size_t elemsize, index_t dim=1)
AttributeStore constructor.
index_t capacity() const
Gets the capacity.
virtual void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
static bool element_by_typeid_name_is_trivially_copyable(const std::string &element_typeid_name)
Tests whether an element type is trivially copyable.
static bool element_type_name_is_known(const std::string &element_type_name)
Tests whether a given element type is registered in the system.
void apply_permutation_with_lifecycle(const vector< index_t > &permutation)
implementation of apply_permutation() used when there is a lifecycle, that is, when attribute type is...
virtual void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
LifeCycle * lifecycle() const
Gets the LifeCycle.
virtual std::string element_typeid_name() const =0
Gets the typeid name of the element type stored in this AttributeStore.
void copy_item(index_t to, index_t from)
Copies an item.
virtual AttributeStore * clone() const =0
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
static bool element_typeid_name_is_known(const std::string &element_typeid_name)
Tests whether a given element type is registered in the system.
virtual std::string user_element_typeid_name() const =0
Gets the user typeid name of the element type stored in this AttributeStore.
void register_observer(AttributeStoreObserver *observer)
Registers an observer.
virtual void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
virtual void resize(index_t new_size)=0
Resizes this AttributeStore.
virtual void scale_item(index_t to, double s)
Scales an item.
void unregister_observer(AttributeStoreObserver *observer)
Unregisters an observer.
virtual void redim(index_t dim)=0
Sets the dimension.
index_t dimension() const
Gets the dimension.
static std::string element_type_name_by_element_typeid_name(const std::string &element_typeid_name)
Gets an element type name from its mangled name.
virtual bool elements_type_matches(const std::string &type_name) const =0
Tests whether this AttributeStore stores elements of a given type.
void swap_items(index_t i, index_t j)
Swaps two items.
static bool element_by_type_name_is_trivially_copyable(const std::string &element_type_name)
Tests whether an element type is trivially copyable.
size_t element_size() const
Gets the element size.
virtual void reserve(index_t new_capacity)=0
Reserves memory.
virtual void zero()
Zeroes all the memory associated with this AttributeStore.
BoolAttributeAccessor(Attribute< bool > &attribute, index_t index)
BoolAttributeAccessor constructor.
BoolAttributeAccessor & operator=(const BoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(const ConstBoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(bool x)
Assigns a bool to a BoolAttributeAccessor.
BoolAttributeAccessor(const BoolAttributeAccessor &rhs)
Copy-constructor.
ConstBoolAttributeAccessor(const Attribute< bool > &attribute, index_t index)
ConstBoolAttributeAccessor constructor.
Numeric::uint8 & element(index_t i)
Gets a modifiable element by index.
void fill(bool val)
Sets all the elements in this attribute to a specified value.
const Numeric::uint8 & element(index_t i) const
Gets an element by index.
void copy(const Attribute< bool > &rhs)
Copies all the values from another attribute.
Manages an attribute attached to a set of object.
Attribute(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
const T & operator[](index_t i) const
Gets an element by index.
Attribute()
Creates an uninitialized (unbound) Attribute.
T * data()
Gets the pointer to the data.
void fill(const T &val)
Sets all the elements in this attribute to a specified value.
const T * data() const
Gets the pointer to the data.
T & operator[](index_t i)
Gets a modifiable element by index.
void copy(const Attribute< T > &rhs)
Copies all the values from another attribute.
Manages a set of attributes attached to an object.
void delete_attribute_store(AttributeStore *as)
Deletes an AttributeStore.
void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
void zero_item(index_t to)
Sets an item to zero.
void copy(const AttributesManager &rhs)
Copies all the attributes from another AttributesManager.
AttributesManager()
Constructs a new empty AttributesManager.
index_t nb() const
Gets the number of attributes.
bool rename_attribute(const std::string &old_name, const std::string &new_name)
Renames an attribute.
void scale_item(index_t to, double s)
Scales an item.
const AttributeStore * find_attribute_store(const std::string &name) const
Finds an AttributeStore by name.
void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
AttributeStore * find_attribute_store(const std::string &name)
Finds an AttributeStore by name.
void bind_attribute_store(const std::string &name, AttributeStore *as)
Binds an AttributeStore with the specified name. Ownership of this AttributeStore is transferred to t...
void list_attribute_names(vector< std::string > &names) const
Gets the names of all the attributes in this AttributeStore.
~AttributesManager()
AttributesManager destructor.
void copy_item(index_t to, index_t from)
Copies all the attributes of an item into another one.
void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
bool is_defined(const std::string &name) const
Tests whether an attribute is defined.
void swap_items(index_t i, index_t j)
Swaps all the attributes of two items.
index_t size() const
Gets the size.
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
void delete_attribute_store(const std::string &name)
Deletes an AttributeStore by name.
bool copy_attribute(const std::string &name, const std::string &new_name)
Copies an attribute.
void zero()
Zeroes all the attributes.
void reserve(index_t new_capacity)
Pre-allocates memory for a number of items.
void resize(index_t new_size)
Resizes all the attributes managed by this AttributesManager.
Base class for reference-counted objects.
Concrete implementation of LifeCycle.
static void register_ascii_attribute_serializer(const std::string &type_name, AsciiAttributeReadSerializer read, AsciiAttributeWriteSerializer write)
Declares a new attribute type that can be read from and written to ascii files.
Manages the life cycle of an object.
Readonly access to an attribute as a double regardless its type.
double operator[](index_t i)
Gets a property value.
Readwrite access to an attribute as a double regardless its type.
Accessor class used by ScalarAttributeAdapter to implement indexing operator.
Accessor class used by ScalarAttributeAdapter to implement indexing operator (const version).
Access to an attribute as a double regardless its type.
index_t element_index() const
Gets the element index.
T get_element(index_t i, index_t multiplier=1) const
Gets an element.
ElementType
Internal representation of the attribute.
static std::string attribute_base_name(const std::string &name)
Gets the base attribute name from a compound name.
void bind_if_is_defined(const AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
bool is_bound() const
Tests whether an Attribute is bound.
static index_t nb_scalar_elements_per_item(const AttributeStore *store)
Gets the number of scalar components per item in an AttributeStore.
double get_element_as_double(index_t i) const
Gets an attribute value.
~ScalarAttributeAdapterBase()
ReadonlyScalarAttributeAdapterBase destructor.
static ElementType element_type(const AttributeStore *store)
Gets the element type stored in an AttributeStore.
const AttributeStore * attribute_store() const
Gets the AttributeStore.
ScalarAttributeAdapterBase()
ScalarAttributeAdapterBase constructor.
static bool can_be_bound_to(const AttributeStore *store)
Tests whether a ScalarAttributeAdapterBase can be bound to a given attribute store.
void unbind()
Unbinds this Attribute.
static bool is_defined(const AttributesManager &manager, const std::string &name)
Tests whether an attribute with the specified name and with a type that can be converted to double ex...
ScalarAttributeAdapterBase(const AttributesManager &manager, const std::string &name)
ScalarAttributeAdapterBase constructor.
double set_element_as_double(index_t i, double value)
Sets an attribute value.
void set_element(T value, index_t i, index_t multiplier=1) const
Sets an element.
static index_t attribute_element_index(const std::string &name)
Gets the base attribute name from a compound name.
index_t size() const
Gets the size.
ElementType element_type() const
Gets the internal representation of the elements.
A smart pointer with reference-counted copy semantics.
Implementation of AttributeStoreCreator for a specific type.
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
bool elements_are_trivially_copyable() const override
Tests whether elements of this attribute can be trivially copyable.
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
void madd_item(index_t to, double s, index_t from) override
Adds a scaled item to another item \detais item[to] += s * item[from].
void resize(index_t new_size) override
Resizes this AttributeStore.
TypedAttributeStore(index_t dim=1, const std::type_info &user_type_info=typeid(ST))
Creates a new empty attribute store.
void reserve(index_t new_capacity) override
Reserves memory.
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
std::string user_element_typeid_name() const override
Gets the user typeid name of the element type stored in this AttributeStore.
void notify(Memory::pointer base_addr, index_t size, index_t dim) override
If size or base address differ from the cached values, notify all the observers, and update the cache...
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
void redim(index_t dim) override
Sets the dimension.
void scale_item(index_t to, double s) override
Scales an item.
Helper class to register new attribute types.
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Vector with aligned memory allocation.
T * data()
Gets a pointer to the array of elements.
index_t size() const
Gets the number of elements.
Common include file, providing basic definitions. Should be included before anything else by all head...
Functions to read and write structured files.
Implementation of generic object lifecycle service.
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
std::atomic_flag spinlock
A lightweight synchronization structure.
Global Vorpaline namespace.
void geo_argused(const T &)
Suppresses compiler warnings about unused parameters.
geo_index_t index_t
The type for storing and manipulating indices.
SmartPointer< AttributeStoreCreator > AttributeStoreCreator_var
An automatic reference-counted pointer to an AttributeStoreCreator.
bool read_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
bool write_ascii_attribute< bool >(FILE *file, Memory::const_pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Types and functions for numbers manipulation.
Function and classes for process manipulation.