diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 592864528244c..0e4c2b82ffa8f 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -34,6 +34,7 @@ #include #include // IWYU pragma: export #include +#include namespace o2::framework { @@ -694,6 +695,7 @@ struct DynamicColumn { template struct IndexColumn { using inherited_t = INHERIT; + static constexpr const uint32_t hash = 0; static constexpr const char* const& columnLabel() { return INHERIT::mLabel; } }; @@ -701,6 +703,7 @@ struct IndexColumn { template struct MarkerColumn { using inherited_t = INHERIT; + static constexpr const uint32_t hash = 0; static constexpr const char* const& columnLabel() { return INHERIT::mLabel; } }; @@ -1907,7 +1910,7 @@ class Table static constexpr auto hashes() { - return [](framework::pack) { return std::set{{o2::framework::TypeIdHelpers::uniqueId()...}}; }(columns_t{}); + return [](framework::pack) { return std::set{{C::hash...}}; }(columns_t{}); } Table(std::shared_ptr table, uint64_t offset = 0) @@ -2279,6 +2282,17 @@ O2ORIGIN("TEST"); O2HASH("TEST/0"); } // namespace o2::aod +namespace +{ +template +consteval static std::string_view namespace_prefix() +{ + constexpr auto name = o2::framework::type_name(); + const auto pos = name.rfind(std::string_view{":"}); + return name.substr(0, pos - 1); +} +} // namespace + #define DECLARE_EQUIVALENT_FOR_INDEX(_Base_, _Equiv_) \ template <> \ struct EquivalentIndexNG, o2::aod::Hash<_Equiv_::ref.desc_hash>> { \ @@ -2294,6 +2308,7 @@ O2HASH("TEST/0"); #define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \ struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column<_Type_, _Name_>; \ using type = _Type_; \ @@ -2317,8 +2332,7 @@ O2HASH("TEST/0"); return _Getter_(); \ } \ }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_) \ DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_) @@ -2330,6 +2344,7 @@ O2HASH("TEST/0"); #define DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, _Label_) \ struct _Name_ : o2::soa::Column { \ static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column; \ using type = MAKEINT(_Size_); \ @@ -2352,82 +2367,81 @@ O2HASH("TEST/0"); return (*mColumnIterator & (static_cast(1) << bit)) >> bit; \ } \ }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType() } #define DECLARE_SOA_BITMAP_COLUMN(_Name_, _Getter_, _Size_) \ DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, "f" #_Name_) /// An 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on static C++ expression. -#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - \ - static o2::framework::expressions::Projector Projector() \ - { \ - return _Expression_; \ - } \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + \ + static o2::framework::expressions::Projector Projector() \ + { \ + return _Expression_; \ + } \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_) \ DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_, _Expression_); /// A configurable 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on dynamically supplied C++ expression or a string definition. -#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - static constexpr const int32_t mHash = _Label_ ""_h; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + static constexpr const int32_t mHash = _Label_ ""_h; \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } /// An index column is a column of indices to elements / of another table named /// _Name_##s. The column name will be _Name_##Id and will always be stored in @@ -2461,6 +2475,7 @@ consteval auto getIndexTargets() static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ static constexpr const char* mLabel = "fIndexSlice" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \ using type = _Type_[2]; \ using column_t = _Name_##IdSlice; \ @@ -2547,6 +2562,7 @@ consteval auto getIndexTargets() static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ static constexpr const char* mLabel = "fIndexArray" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column, _Name_##Ids>; \ using type = std::vector<_Type_>; \ using column_t = _Name_##Ids; \ @@ -2697,143 +2713,143 @@ consteval auto getIndexTargets() #define DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// NORMAL -#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ - static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using binding_t = _Table_; \ - static constexpr auto index_targets = getIndexTargets<_Table_>(); \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ - o2::soa::notBoundTable(#_Table_); \ - } \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - auto _Getter_() const \ - { \ - return _Getter_##_as(); \ - } \ - \ - template \ - bool setCurrent(T* current) \ - { \ - if constexpr (o2::soa::is_binding_compatible_v()) { \ - assert(current != nullptr); \ - this->mBinding.bind(current); \ - return true; \ - } \ - return false; \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - binding_t const* getCurrent() const { return mBinding.get(); } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ + static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using binding_t = _Table_; \ + static constexpr auto index_targets = getIndexTargets<_Table_>(); \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ + o2::soa::notBoundTable(#_Table_); \ + } \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + auto _Getter_() const \ + { \ + return _Getter_##_as(); \ + } \ + \ + template \ + bool setCurrent(T* current) \ + { \ + if constexpr (o2::soa::is_binding_compatible_v()) { \ + assert(current != nullptr); \ + this->mBinding.bind(current); \ + return true; \ + } \ + return false; \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + binding_t const* getCurrent() const { return mBinding.get(); } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_) #define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "") #define DECLARE_SOA_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// SELF -#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static constexpr const char* mLabel = "fIndex" _Label_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using self_index_t = std::true_type; \ - using compatible_signature = std::conditional, _IndexTarget_, void>; \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static constexpr const char* mLabel = "fIndex" _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using self_index_t = std::true_type; \ + using compatible_signature = std::conditional, _IndexTarget_, void>; \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void) #define DECLARE_SOA_SELF_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, #_Name_) @@ -2842,6 +2858,7 @@ consteval auto getIndexTargets() struct _Name_##IdSlice : o2::soa::Column<_Type_[2], _Name_##IdSlice> { \ static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static constexpr const char* mLabel = "fIndexSlice" _Label_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \ using type = _Type_[2]; \ using column_t = _Name_##IdSlice; \ @@ -2905,6 +2922,7 @@ consteval auto getIndexTargets() struct _Name_##Ids : o2::soa::Column, _Name_##Ids> { \ static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static constexpr const char* mLabel = "fIndexArray" _Label_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column, _Name_##Ids>; \ using type = std::vector<_Type_>; \ using column_t = _Name_##Ids; \ @@ -3021,6 +3039,7 @@ consteval auto getIndexTargets() using callback_holder_t = _Name_##Callback; \ using callable_t = helper::callable_t; \ using callback_t = callable_t::type; \ + static constexpr const uint32_t hash = 0; \ \ _Name_(arrow::ChunkedArray const*) \ { \ diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index 3da10fb0f561d..e450764576c29 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -13,9 +13,11 @@ #define O2_FRAMEWORK_STRINGHELPERS_H_ #include +#include #include #include #include +#include // CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = {0x0L, 0x77073096L, 0xee0e612cL, @@ -72,6 +74,17 @@ consteval uint32_t crc32(char const* str, int length) return crc; } +template + requires(std::same_as && ...) +consteval uint32_t crc32(Ts... Vs) +{ + uint32_t crc = 0xFFFFFFFF; + for (auto& c : std::vector{Vs...} | std::ranges::views::join) { + crc = (crc >> 8) ^ crc_table[(crc ^ static_cast(c)) & 0x000000FF]; + } + return crc; +} + consteval uint32_t compile_time_hash(char const* str) { return crc32(str, static_cast(__builtin_strlen(str)) - 1) ^ 0xFFFFFFFF; diff --git a/Framework/Foundation/include/Framework/TypeIdHelpers.h b/Framework/Foundation/include/Framework/TypeIdHelpers.h index d4f72b8f3f7ff..5eaac2151b909 100644 --- a/Framework/Foundation/include/Framework/TypeIdHelpers.h +++ b/Framework/Foundation/include/Framework/TypeIdHelpers.h @@ -75,10 +75,9 @@ struct TypeIdHelpers { constexpr static uint32_t uniqueId() { #ifdef __CLING__ - constexpr uint32_t r = crc32(unique_type_id_v.data(), unique_type_id_v.size()); - return r; + return crc32(unique_type_id_v.data(), unique_type_id_v.size()); #else - return compile_time_hash(type_name().data()); + return crc32(type_name().data(), type_name().size()); #endif } };