11 #ifndef ROOT_RCOLUMNVALUE
12 #define ROOT_RCOLUMNVALUE
26 #include <initializer_list>
32 #include <type_traits>
38 using namespace ROOT::VecOps;
62 class R__CLING_PTRCHECK(off) RColumnValue {
65 using MustUseRVec_t = IsRVec_t<T>;
68 using ColumnValue_t =
typename std::conditional<MustUseRVec_t::value, TakeFirstParameter_t<T>, T>::type;
69 using TreeReader_t =
typename std::conditional<MustUseRVec_t::value, TTreeReaderArray<ColumnValue_t>,
70 TTreeReaderValue<ColumnValue_t>>::type;
74 enum class EColumnKind { kTree, kCustomColumn, kDataSource, kInvalid };
76 EColumnKind fColumnKind = EColumnKind::kInvalid;
78 unsigned int fSlot = std::numeric_limits<unsigned int>::max();
86 std::unique_ptr<TreeReader_t> fTreeReader;
92 RCustomColumnBase *fCustomColumn;
94 enum class EStorageType : char { kContiguous, kUnknown, kSparse };
97 EStorageType fStorageType = EStorageType::kUnknown;
99 RVec<ColumnValue_t> fRVec;
100 bool fCopyWarningPrinted =
false;
105 void SetTmpColumn(
unsigned int slot, RCustomColumnBase *customColumn)
107 fCustomColumn = customColumn;
110 const auto diffTypes = (0 != strcmp(customColumn->GetTypeId().name(),
typeid(T).name()));
111 auto inheritedType = [&](){
112 auto colTClass = TClass::GetClass(customColumn->GetTypeId());
113 return colTClass && colTClass->InheritsFrom(TClass::GetClass<T>());
116 if (diffTypes && !inheritedType()) {
117 const auto tName = TypeID2TypeName(
typeid(T));
118 const auto colTypeName = TypeID2TypeName(customColumn->GetTypeId());
119 std::string errMsg =
"RColumnValue: type specified for column \"" +
120 customColumn->GetName() +
"\" is ";
122 errMsg +=
typeid(T).name();
123 errMsg +=
" (extracted from type info)";
127 errMsg +=
" but temporary column has type ";
128 if (colTypeName.empty()) {
129 auto &
id = customColumn->GetTypeId();
131 errMsg +=
" (extracted from type info)";
133 errMsg += colTypeName;
135 throw std::runtime_error(errMsg);
138 if (customColumn->IsDataSourceColumn()) {
139 fColumnKind = EColumnKind::kDataSource;
140 fDSValuePtr =
static_cast<T **
>(customColumn->GetValuePtr(slot));
142 fColumnKind = EColumnKind::kCustomColumn;
143 fCustomValuePtr =
static_cast<T *
>(customColumn->GetValuePtr(slot));
148 void MakeProxy(TTreeReader *r,
const std::string &bn)
150 fColumnKind = EColumnKind::kTree;
151 fTreeReader = std::make_unique<TreeReader_t>(*r, bn.c_str());
158 template <typename U = T, typename std::enable_if<!RColumnValue<U>::MustUseRVec_t::value,
int>::type = 0>
159 T &Get(Long64_t entry)
161 if (fColumnKind == EColumnKind::kTree) {
162 return *(fTreeReader->Get());
164 fCustomColumn->Update(fSlot, entry);
165 return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
172 template <
typename U = T,
173 typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && !std::is_same<U, RVec<bool>>::value,
175 T &Get(Long64_t entry)
177 if (fColumnKind == EColumnKind::kTree) {
178 auto &readerArray = *fTreeReader;
185 if (EStorageType::kUnknown == fStorageType && readerArray.GetSize() > 1) {
188 (1 == (&readerArray[1] - &readerArray[0])) ? EStorageType::kContiguous : EStorageType::kSparse;
191 const auto readerArraySize = readerArray.GetSize();
192 if (EStorageType::kContiguous == fStorageType ||
193 (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
194 if (readerArraySize > 0) {
198 auto readerArrayAddr = &readerArray.At(0);
199 T rvec(readerArrayAddr, readerArraySize);
200 std::swap(fRVec, rvec);
203 std::swap(fRVec, emptyVec);
208 if (!fCopyWarningPrinted) {
209 Warning(
"RColumnValue::Get",
210 "Branch %s hangs from a non-split branch. A copy is being performed in order "
211 "to properly read the content.",
212 readerArray.GetBranchName());
213 fCopyWarningPrinted =
true;
216 (void)fCopyWarningPrinted;
218 if (readerArraySize > 0) {
219 T rvec(readerArray.begin(), readerArray.end());
220 std::swap(fRVec, rvec);
223 std::swap(fRVec, emptyVec);
229 fCustomColumn->Update(fSlot, entry);
230 return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
239 template <
typename U = T,
240 typename std::enable_if<RColumnValue<U>::MustUseRVec_t::value && std::is_same<U, RVec<bool>>::value,
242 T &Get(Long64_t entry)
244 if (fColumnKind == EColumnKind::kTree) {
245 auto &readerArray = *fTreeReader;
246 const auto readerArraySize = readerArray.GetSize();
247 if (readerArraySize > 0) {
249 T rvec(readerArray.begin(), readerArray.end());
250 std::swap(fRVec, rvec);
253 std::swap(fRVec, emptyVec);
258 fCustomColumn->Update(fSlot, entry);
259 return fColumnKind == EColumnKind::kCustomColumn ? *fCustomValuePtr : **fDSValuePtr;
273 if (EColumnKind::kTree == fColumnKind) {
282 #if __cplusplus < 201703L
283 extern template class RColumnValue<int>;
284 extern template class RColumnValue<unsigned int>;
285 extern template class RColumnValue<char>;
286 extern template class RColumnValue<unsigned char>;
287 extern template class RColumnValue<float>;
288 extern template class RColumnValue<double>;
289 extern template class RColumnValue<Long64_t>;
290 extern template class RColumnValue<ULong64_t>;
291 extern template class RColumnValue<std::vector<int>>;
292 extern template class RColumnValue<std::vector<unsigned int>>;
293 extern template class RColumnValue<std::vector<char>>;
294 extern template class RColumnValue<std::vector<unsigned char>>;
295 extern template class RColumnValue<std::vector<float>>;
296 extern template class RColumnValue<std::vector<double>>;
297 extern template class RColumnValue<std::vector<Long64_t>>;
298 extern template class RColumnValue<std::vector<ULong64_t>>;
301 template <
typename T>
302 struct TRDFValueTuple {
305 template <
typename... BranchTypes>
306 struct TRDFValueTuple<TypeList<BranchTypes...>> {
307 using type = std::tuple<RColumnValue<BranchTypes>...>;
310 template <
typename BranchType>
311 using RDFValueTuple_t =
typename TRDFValueTuple<BranchType>::type;
314 template <
typename ValueTuple, std::size_t... S>
315 void ResetRDFValueTuple(ValueTuple &values, std::index_sequence<S...>)
318 std::initializer_list<int> expander{(std::get<S>(values).Reset(), 0)...};
327 #endif // ROOT_RCOLUMNVALUE