Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 158 additions & 49 deletions DataFormats/Headers/include/Headers/DataHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,63 +79,186 @@ struct DataHeader;
struct DataIdentifier;

//__________________________________________________________________________________________________
// internal implementations
/// @ingroup aliceo2_dataformat_tools
namespace Internal {
// terminating initializer implementation
template <typename T>
constexpr T String2__()
{
return 0;
}
// recursive initializer implementation
template <typename T, typename... Targs>
constexpr T String2__(char c, Targs... Fargs)
{
return (T) c | String2__<T>(Fargs...) << 8;
}

/// compile time evaluation of the number of arguments in argument pack
template<typename T, typename... Targs>
struct getnargs {
static int const value = getnargs<Targs...>::value + 1;
};
template<typename T>
struct getnargs<T> {
static int const value = 1;
};

/// get the number of active bits (set to 1) in a bitfield
template <unsigned int N>
struct NumberOfActiveBits {
static int const value = NumberOfActiveBits<(N >> 1)>::value + (N & 0x1);
};
template <>
struct NumberOfActiveBits<0> {
static int const value = 0;
};

/// evaluate the array size necessary to hold a N-byte number with type T
template <int N, typename T>
struct ArraySize {
static_assert(N >= sizeof(T), "get this code to work first");
static int const value = 1;
//static int const value = std::conditional<(N > sizeof(T)), ArraySize<(N - sizeof(T)), T>, ArraySize<0, T>>::value + 1;
};
template <typename T>
struct ArraySize<0, T> {
static int const value = 0;
};

/// select uint type depending on size, default is uint64_t
template <int N>
struct TraitsIntType {
typedef uint64_t type;
};
template <>
struct TraitsIntType<1> {
typedef uint8_t type;
};
template <>
struct TraitsIntType<2> {
typedef uint16_t type;
};
template <>
struct TraitsIntType<4> {
typedef uint32_t type;
};

struct defaultPrinter {
void operator()(const char* str) const {}
};
};

//__________________________________________________________________________________________________
/// constexpr intializer, evaluated at compile time
/// generic intializer for variable char argument list
template <typename T, typename... Targs>
constexpr T String2(char c, Targs... Fargs)
{
// number of arguments has either to match the size of the type, or the last element is treated
// as '0' if missing
static_assert(Internal::getnargs<T, Targs...>::value == sizeof(T) ||
Internal::getnargs<T, Targs...>::value == sizeof(T) - 1,
"number of arguments does not match the uint type width"
);
return Internal::String2__<T>(c, Fargs...);
}

/// constexpr intializer, evaluated at compile time
/// backward compatibility, might be removed in the future
constexpr uint64_t String2uint64(char c1, char c2, char c3, char c4,
char c5, char c6, char c7, char c8)
{
return((uint64_t) c1 | (uint64_t) c2 << 8 | (uint64_t) c3 << 16 | (uint64_t) c4 << 24 |
(uint64_t) c5 << 32 | (uint64_t) c6 << 40 | (uint64_t) c7 << 48 | (uint64_t) c8 << 56);
return String2<uint64_t>(c1, c2, c3, c4, c5, c6, c7, c8);
}

/// constexpr intializer, evaluated at compile time
constexpr uint64_t String2uint64(const char* str, int pos=0)
/// generic initializer, convert a string to unsigned integer of different width
/// Example usage: String2<uint64_t>("IDENTIFY")
/// @ingroup aliceo2_dataformat_tools
template <typename T>
constexpr T String2(const char* str, int pos=0)
{
return((uint64_t) str[0+pos] |
(str[0+pos] ? ((uint64_t) str[1+pos] << 8 |
(str[1+pos] ? ((uint64_t) str[2+pos] << 16 |
(str[2+pos] ? ((uint64_t) str[3+pos] << 24 |
(str[3+pos] ? ((uint64_t) str[4+pos] << 32 |
(str[4+pos] ? ((uint64_t) str[5+pos] << 40 |
(str[5+pos] ? ((uint64_t) str[6+pos] << 48 |
(str[6+pos] ? ((uint64_t) str[7+pos] << 56 )
return((T) str[0+pos] |
(str[0+pos] && sizeof(T) >= 2 ? ((T) str[1+pos] << (sizeof(T) >= 2 ? 8 : 0) |
(str[1+pos] && sizeof(T) >= 4 ? ((T) str[2+pos] << (sizeof(T) >= 4 ? 16 : 0) |
(str[2+pos] && sizeof(T) >= 4 ? ((T) str[3+pos] << (sizeof(T) >= 4 ? 24 : 0) |
(str[3+pos] && sizeof(T) >= 8 ? ((T) str[4+pos] << (sizeof(T) >= 8 ? 32 : 0) |
(str[4+pos] && sizeof(T) >= 8 ? ((T) str[5+pos] << (sizeof(T) >= 8 ? 40 : 0) |
(str[5+pos] && sizeof(T) >= 8 ? ((T) str[6+pos] << (sizeof(T) >= 8 ? 48 : 0) |
(str[6+pos] && sizeof(T) >= 8 ? ((T) str[7+pos] << (sizeof(T) >= 8 ? 56 : 0) )
: 0)) : 0)) : 0)) : 0)) : 0)) : 0)) : 0));
}

/// constexpr intializer, evaluated at compile time
constexpr uint32_t String2uint32(char c1, char c2, char c3)
/// backward compatibility, can be removed
/// forwards to generic function
constexpr uint64_t String2uint64(const char* str, int pos=0)
{
return((uint32_t) c1 | (uint32_t) c2 << 8 | (uint32_t) c3 << 16);
return String2<uint64_t>(str, pos);
}

/// constexpr intializer, evaluated at compile time
constexpr uint32_t String2uint32(const char* str)
/// backward compatibility, can be removed
/// forwards to generic function
constexpr uint32_t String2uint32(const char* str, int pos=0)
{
return((uint32_t) str[0] |
(str[0] ? ((uint32_t) str[1] << 8 |
(str[1] ? ((uint32_t) str[2] << 16 |
(str[2] ? ((uint32_t) str[3] << 24 )
:0 )) : 0)) : 0));
return String2<uint32_t>(str, pos);
}


/// constexpr intializer, evaluated at compile time
constexpr uint32_t CharArr2uint32(char c1, char c2, char c3, char c4)
/// backward compatibility, might be removed in the future
constexpr uint32_t String2uint32(char c1, char c2, char c3)
{
return((uint32_t) c1 |
(uint32_t) c2 << 8 |
(uint32_t) c3 << 16 |
(uint32_t) c4 << 24);
return String2<uint32_t>(c1, c2, c3);
}

/// constexpr intializer, evaluated at compile time
constexpr uint32_t CharArr2uint32(const char* str)
/// backward compatibility, might be removed in the future
constexpr uint32_t CharArr2uint32(char c1, char c2, char c3, char c4)
{
return((uint32_t) str[0] |
(str[0] ? ((uint32_t) str[1] << 8 |
(str[1] ? ((uint32_t) str[2] << 16 |
(str[2] ? ((uint32_t) str[3] << 24)
: 0)) : 0)) : 0));
return String2<uint32_t>(c1, c2, c3, c4);
}

//__________________________________________________________________________________________________
/// generic descriptor class faturing the union of a char and a uint element
/// of the same size
/// this is currently working only for up to 8 bytes aka uint64_t, the general
/// solution is working also for multiples of 64 bit, but then the itg member needs
/// to be an array for all. This has not been enabled yet, first the implications
/// have to be studied.
template <int N, typename PrinterPolicy = Internal::defaultPrinter>
struct Descriptor {
static_assert(Internal::NumberOfActiveBits<N>::value == 1 && N <= 8,
"size is required to be 1 or a multiple of 2");
static int const size = N;
static int const bitcount = size*8;
static int const arraySize = 1; //Internal::ArraySize<size, uint64_t>::value;
typedef typename Internal::TraitsIntType<N>::type ItgType;

union {
char str[N];
ItgType itg; // for extension > 64 bit: [arraySize];
};
Descriptor() {};
Descriptor(const Descriptor& other) : itg(other.itg) {}
Descriptor& operator=(const Descriptor& other) {
if (&other != this) itg = other.itg;
return *this;
}
// note: no operator=(const char*) as this potentially runs into trouble with this
// general pointer type, use: somedescriptor = Descriptor("DESCRIPTION")
constexpr Descriptor(const char* origin) : itg(String2<ItgType>(origin)) {};
bool operator==(const Descriptor& other) const {return itg == other.itg;}
bool operator!=(const Descriptor& other) const {return not this->operator==(other);}
// print function needs to be implemented for every derivation
PrinterPolicy printer;
void print() const {
// eventually terminate string before printing
printer(str);
};
};

//__________________________________________________________________________________________________
/// default int representation of 'invalid' token for 4-byte char field
const uint32_t gInvalidToken32 = 0xFFFFFFFF;
Expand Down Expand Up @@ -439,24 +562,10 @@ struct DataDescription {

//__________________________________________________________________________________________________
// 32bit (4 characters) for data origin, ex. the detector or subsystem name
struct DataOrigin {
union {
char str[gSizeDataOriginString];
uint32_t itg;
};
DataOrigin();
DataOrigin(const DataOrigin& other) : itg(other.itg) {}
DataOrigin& operator=(const DataOrigin& other) {
if (&other != this) itg = other.itg;
return *this;
}
// note: no operator=(const char*) as this potentially runs into trouble with this
// general pointer type, use: someorigin = DataOrigin("BLA")
constexpr DataOrigin(const char* origin) : itg{String2uint32(origin)} {};
bool operator==(const DataOrigin&) const;
bool operator!=(const DataOrigin& other) const {return not this->operator==(other);}
void print() const;
struct printDataOrigin {
void operator()(const char* str) const;
};
typedef Descriptor<gSizeDataOriginString, printDataOrigin> DataOrigin;

//__________________________________________________________________________________________________
/// @struct DataHeader
Expand Down
13 changes: 2 additions & 11 deletions DataFormats/Headers/src/DataHeader.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <cstring> // strncpy

//the answer to life and everything
const uint32_t AliceO2::Header::BaseHeader::sMagicString = CharArr2uint32("O2O2");
const uint32_t AliceO2::Header::BaseHeader::sMagicString = String2<uint32_t>("O2O2");

//possible serialization types
const AliceO2::Header::SerializationMethod AliceO2::Header::gSerializationMethodAny ("*******");
Expand Down Expand Up @@ -176,16 +176,7 @@ bool AliceO2::Header::DataHeader::operator==(const DataHeader& that) const
}

//__________________________________________________________________________________________________
AliceO2::Header::DataOrigin::DataOrigin() : itg(gInvalidToken32) {}

//__________________________________________________________________________________________________
bool AliceO2::Header::DataOrigin::operator==(const DataOrigin& other) const
{
return itg == other.itg;
}

//__________________________________________________________________________________________________
void AliceO2::Header::DataOrigin::print() const
void AliceO2::Header::printDataOrigin::operator()(const char* str) const
{
printf("Data origin : %s\n", str);
}
Expand Down