Skip to content

Commit 57ee03f

Browse files
matthiasrichterMohammadAlTurany
authored andcommitted
Bugfix: Initialization of DataDescription with strings < 8
Because the Sting2<type> function is called two times, the second call has to check for the actual string length and the char length array. The bug originates from the initial implementation.
1 parent cf2754c commit 57ee03f

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

DataFormats/Headers/include/Headers/DataHeader.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ struct NumberOfActiveBits<0> {
116116
};
117117

118118
/// evaluate the array size necessary to hold a N-byte number with type T
119-
template <int N, typename T>
119+
template <int N, typename T>
120120
struct ArraySize {
121121
static_assert(N >= sizeof(T), "get this code to work first");
122122
static int const value = 1;
@@ -148,6 +148,20 @@ struct TraitsIntType<4> {
148148
struct defaultPrinter {
149149
void operator()(const char* str) const {}
150150
};
151+
152+
/// helper wrapper to define a type from an integer, which can than
153+
/// be used as template argument
154+
template <int N>
155+
struct intWrapper {
156+
static const int value = N;
157+
};
158+
159+
/// compile time evaluation of a string length, which is either N - 1 or
160+
/// shorter if one character in the array has been set to 0.
161+
template <int N>
162+
constexpr std::size_t strLength(const char (&str)[N], std::size_t pos = 0) {
163+
return ((pos >= N || str[pos] == 0) ? 0 : 1 + strLength(str, pos + 1));
164+
}
151165
};
152166

153167
//__________________________________________________________________________________________________
@@ -529,7 +543,19 @@ struct DataDescription {
529543
// note: no operator=(const char*) as this potentially runs into trouble with this
530544
// general pointer type, use: somedesc = DataDescription("SOMEDESCRIPTION")
531545
template<std::size_t N>
532-
constexpr DataDescription(const char (&desc)[N]) : itg{String2<uint64_t, N, 0, true>(desc),String2<uint64_t, N, 8>(desc)} {}
546+
constexpr DataDescription(const char (&desc)[N]) : itg{String2<uint64_t, N, 0, true>(desc), (Internal::strLength(desc) > 8 ? String2<uint64_t, N, std::conditional< (N > 8), Internal::intWrapper<8>, Internal::intWrapper<N-1>>::type::value >(desc) : 0)} {
547+
// the initializer implements a number of compile time checks
548+
// - for the conversion of the first part of the string to the first 64bit field
549+
// the check for the string length needs to be disabled as it is naturally longer
550+
// then the type size
551+
// - the second field only has to be filled if the string is longer than 8 chars, padding
552+
// with 0 otherwize, this catches the rare case that one character within the array
553+
// has been explicitely set to 0, but the compile time length is longer
554+
// - depending on the length of the char field, either the offset 8 can be chosen or the
555+
// offset is set to the maximum, which will lead also to 0
556+
// - it's probably given that N > 0
557+
static_assert(N > 0, "Strange error, that should not happen at all");
558+
}
533559
bool operator==(const DataDescription&) const;
534560
bool operator!=(const DataDescription& other) const {return not this->operator==(other);}
535561
void print() const;

0 commit comments

Comments
 (0)