ATLAS Offline Software
Loading...
Searching...
No Matches
ColumnVectorWrapper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8//
9// includes
10//
11
13
17
18#include <boost/core/demangle.hpp>
19
20#include <stdexcept>
21
22//
23// method implementations
24//
25
26namespace columnar
27{
28 ColumnVectorHeader ::
29 ColumnVectorHeader ()
30 {
32
33 // we always reserve the first column as having a null value
34 m_elements.at(nullIndex).debugName = "<null>";
35 m_elements.at(nullIndex).isOptional = true;
36
37 // we always reserve the second column as the size column
38 m_elements.at(sizeIndex).debugName = "<size>";
39 m_elements.at(sizeIndex).type = &typeid(std::size_t);
40 m_elements.at(sizeIndex).isOptional = false;
41 m_elements.at(sizeIndex).readOnly = true;
42 }
43
44
45
46 [[nodiscard]] std::size_t ColumnVectorHeader ::
47 addColumn (const ColumnInfo& columnInfo)
48 {
49 m_elements.emplace_back();
50 m_elements.at(sizeIndex).arraySize = m_elements.size();
51
52 auto& header = m_elements.back();
53 header.debugName = columnInfo.name;
54 header.type = columnInfo.type;
55
56 switch (columnInfo.accessMode)
57 {
59 break;
61 header.readOnly = false;
62 break;
64 header.readOnly = false;
65 break;
66 }
67 for (unsigned dim : columnInfo.fixedDimensions)
68 header.arraySize *= dim;
69 header.isOffset = columnInfo.isOffset;
70 if (!columnInfo.isOptional)
71 header.isOptional = false;
72 if (!columnInfo.offsetName.empty())
73 header.offsetIndex = unsetIndex;
74 return m_elements.size() - 1;
75 }
76
77
78
79 void ColumnVectorHeader ::
80 setOffsetColumn (std::size_t columnIndex, std::size_t offsetIndex)
81 {
82 if (columnIndex >= m_elements.size())
83 throw std::logic_error ("column index out of range");
84 if (offsetIndex >= m_elements.size())
85 throw std::logic_error ("offset index out of range");
86 auto& column = m_elements.at(columnIndex);
87 auto& offset = m_elements.at(offsetIndex);
88 if (!offset.isOffset)
89 throw std::runtime_error ("trying to set " + offset.debugName + " as offset column for " + column.debugName + ", but it is not marked as offset column");
90 if (column.offsetIndex != unsetIndex && column.offsetIndex != offsetIndex)
91 throw std::runtime_error ("trying to set " + offset.debugName + " as offset column for " + column.debugName + ", but it is already set to " + m_elements.at(column.offsetIndex).debugName);
92 column.offsetIndex = offsetIndex;
93 }
94
95
96
97 void ColumnVectorHeader ::
98 checkSelf () const
99 {
100 if (m_elements.size() < numFixedColumns)
101 throw std::logic_error ("header has too few m_elements, expected at least " + std::to_string(numFixedColumns) + " but got " + std::to_string(m_elements.size()));
102 if (m_elements[sizeIndex].arraySize != m_elements.size())
103 throw std::logic_error ("size column has wrong array size, expected " + std::to_string(m_elements.size()) + " but got " + std::to_string(m_elements[sizeIndex].arraySize));
104
105 // skipping the first column, which is always the null column
106 // and behaves in a funny manner
107 for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
108 {
109 const auto& column = m_elements[columnIndex];
110 if (column.debugName.empty())
111 throw std::logic_error ("column " + std::to_string(columnIndex) + " has no name");
112 if (column.type == nullptr)
113 throw std::logic_error ("column " + column.debugName + " has no type");
114 if (column.isOffset && *column.type != typeid(ColumnarOffsetType))
115 throw std::logic_error ("column " + column.debugName + " is an offset column that is of type " + boost::core::demangle(column.type->name()) + " instead of ColumnarOffsetType");
116 }
117
118 for (std::size_t columnIndex = 1u; columnIndex != m_elements.size(); ++ columnIndex)
119 {
120 const auto& column = m_elements[columnIndex];
121 if (column.offsetIndex != nullIndex)
122 {
123 if (column.offsetIndex == unsetIndex)
124 throw std::logic_error ("column " + column.debugName + " has an offset index that was never set");
125 if (column.offsetIndex >= m_elements.size())
126 throw std::logic_error ("column " + column.debugName + " has invalid offset index " + std::to_string(column.offsetIndex) + " (max is " + std::to_string(m_elements.size()-1) + ")");
127 const auto& offsetElement = m_elements[column.offsetIndex];
128 if (!offsetElement.isOffset)
129 throw std::logic_error ("column " + column.debugName + " has offset index that is not marked as offset");
130 }
131 }
132 }
133
134
135
136 void ColumnVectorHeader ::
137 checkData (std::span<const void* const> data) const
138 {
139 if (data.size() != m_elements.size())
140 throw std::logic_error ("data vector has wrong size, expected " + std::to_string(m_elements.size()) + " but got " + std::to_string(data.size()));
141 if (data[nullIndex] != nullptr)
142 throw std::logic_error ("null column is not set to a nullptr value");
143 const auto* sizeVector = static_cast<const std::size_t*>(data[sizeIndex]);
144 for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
145 {
146 const auto& column = m_elements[columnIndex];
147 if (data[columnIndex] == nullptr)
148 {
149 if (column.isOptional)
150 continue;
151 if (column.offsetIndex != nullIndex && data[column.offsetIndex] == nullptr)
152 continue;
153 throw std::logic_error ("column " + column.debugName + " was not set");
154 }
155 if (column.isOffset)
156 {
157 const auto size = sizeVector[columnIndex];
158 if (size < 1)
159 throw std::runtime_error ("offset column " + column.debugName + " has size " + std::to_string(size) + ", but needs at least 1 element");
160 auto *offsets = static_cast<const ColumnarOffsetType*>(data[columnIndex]);
161 if (offsets[0] != 0)
162 throw std::runtime_error ("offset column doesn't start with 0: " + column.debugName);
163 for (std::size_t i = 1u; i != size; ++ i)
164 {
165 if (offsets[i] < offsets[i-1])
166 throw std::runtime_error ("offset column " + column.debugName + " is not monotonically increasing at index " + std::to_string(i) + ": " + std::to_string(offsets[i-1]) + " > " + std::to_string(offsets[i]));
167 }
168 }
169 }
170 for (std::size_t columnIndex = 0u; columnIndex != m_elements.size(); ++ columnIndex)
171 {
172 if (data[columnIndex] == nullptr)
173 continue;
174 const auto& column = m_elements[columnIndex];
175 std::size_t expectedSize = 1u;
176 if (column.offsetIndex != ColumnVectorHeader::nullIndex)
177 {
178 if (data[column.offsetIndex] == nullptr)
179 throw std::runtime_error ("column " + column.debugName + " uses offset column " + m_elements[column.offsetIndex].debugName + " that is not set");
180 const auto offsetIndex = column.offsetIndex;
181 auto *offsetsPtr = static_cast<const ColumnarOffsetType*>(data[offsetIndex]);
182 expectedSize = offsetsPtr[sizeVector[offsetIndex]-1];
183 }
184 expectedSize *= column.arraySize;
185
186 if (column.isOffset)
187 expectedSize += 1u;
188
189 if (sizeVector[columnIndex] != expectedSize)
190 throw std::runtime_error ("column size doesn't match expected size: " + column.debugName + ", found " + std::to_string (sizeVector[columnIndex]) + " vs exptected=" + std::to_string (expectedSize) + " isOffset=" + std::to_string (column.isOffset));
191 }
192 }
193
194
195
196 ColumnVectorData ::
197 ColumnVectorData (const ColumnVectorHeader *val_header)
198 : m_header (val_header),
199 m_data (val_header->numColumns(), nullptr),
200 m_dataSize (val_header->numColumns(), 0u)
201 {
203 }
204
205
206
207 void ColumnVectorData ::
208 setColumnVoid (std::size_t columnIndex, std::size_t size, const void *dataPtr, const std::type_info& type, bool isConst)
209 {
210 if (columnIndex == ColumnVectorHeader::nullIndex)
211 throw std::logic_error ("cannot set the null column");
212 if (columnIndex >= m_header->numColumns())
213 throw std::logic_error ("invalid column index: " + std::to_string(columnIndex) + " (max is " + std::to_string(m_header->numColumns()-1) + ")");
214 auto& header = m_header->getColumn (columnIndex);
215
216 // If dataPtr is null, we use a dummy value to avoid issues in which
217 // we check whether a column exists by checking for a null pointer,
218 // which would return false for columns that were set with a
219 // nullptr.
220 if (dataPtr == nullptr)
221 {
222 if (size != 0) [[unlikely]]
223 throw std::logic_error ("dataPtr is null but size is not zero for column: " + header.debugName);
224 static const unsigned dummyValue = 0;
225 dataPtr = &dummyValue;
226 }
227
228 if (type != *header.type)
229 throw std::runtime_error ("invalid type for column: " + header.debugName);
230 if (isConst && !header.readOnly)
231 throw std::runtime_error ("assigning const vector to a column that is not read-only: " + header.debugName);
232 if (m_data[columnIndex] != nullptr)
233 throw std::runtime_error ("column filled multiple times: " + header.debugName);
234 auto *castDataPtr ATLAS_THREAD_SAFE = const_cast<void*>(dataPtr);
235 m_data[columnIndex] = castDataPtr;
236 m_dataSize[columnIndex] = size;
237 }
238
239
240
241 std::pair<std::size_t,const void*> ColumnVectorData ::
242 getColumnVoid (std::size_t columnIndex, const std::type_info *type, bool isConst)
243 {
244 if (columnIndex >= m_header->numColumns())
245 throw std::runtime_error ("invalid column index: " + std::to_string(columnIndex) + " (max is " + std::to_string(m_header->numColumns()-1) + ")");
246
247 auto& header = m_header->getColumn (columnIndex);
248 if (*type != *header.type)
249 throw std::runtime_error ("invalid type for column: " + header.debugName);
250 if (!isConst && header.readOnly)
251 throw std::runtime_error ("retrieving non-const vector from a read-only column: " + header.debugName);
252 if (m_data[columnIndex] != nullptr)
253 return std::make_pair (m_dataSize[columnIndex], m_data[columnIndex]);
254 else
255 return std::make_pair (0u, nullptr);
256 }
257
258
259
260 void ColumnVectorData ::
261 callNoCheck (const IColumnarTool& tool)
262 {
263 tool.callVoid (m_data.data());
264 }
265}
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
const ColumnVectorHeader * m_header
void setColumn(std::size_t columnIndex, std::size_t size, CT *dataPtr)
set the data for the given column
std::vector< std::size_t > m_dataSize
the header information for the entire columnar data vector
static constexpr std::size_t nullIndex
the index used for an invalid index (always has to be 0)
static constexpr std::size_t numFixedColumns
the number of fix elements in the columnar data vector
static constexpr std::size_t unsetIndex
the number used for an unset but non-null index
std::vector< ColumnVectorElementHeader > m_elements
the elements in the columnar data vector
static constexpr std::size_t sizeIndex
the index used for the column size column
an interface for tools that operate on columnar data
#define unlikely(x)
Definition dictionary.h:41
@ update
an updateable column
Definition ColumnInfo.h:27
@ output
an output column
Definition ColumnInfo.h:24
@ input
an input column
Definition ColumnInfo.h:21
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition ColumnInfo.h:35
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition ColumnInfo.h:74
std::vector< unsigned > fixedDimensions
the fixed dimensions this column has (if any)
Definition ColumnInfo.h:82
bool isOptional
whether this column is optional
Definition ColumnInfo.h:121
std::string name
the name of the column
Definition ColumnInfo.h:42
bool isOffset
whether this is an offset column
Definition ColumnInfo.h:92
ColumnAccessMode accessMode
the access mode for the column
Definition ColumnInfo.h:58
const std::type_info * type
the type of the individual entries in the column
Definition ColumnInfo.h:54