ATLAS Offline Software
Loading...
Searching...
No Matches
JaggedVecVector.icc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
3 */
4/**
5 * @file AthContainers/tools/JaggedVecVector.icc
6 * @author scott snyder <snyder@bnl.gov>
7 * @date Mar, 2024
8 * @brief Implementation of @c IAuxTypeVector for @c JaggedVecElt types.
9 */
10
11
12#include "AthContainers/AuxTypeRegistry.h"
13
14
15namespace SG {
16
17
18/**
19 * @brief Constructor.
20 * @param auxid The auxid of the variable this vector represents.
21 * @param vecPtr Pointer to the object.
22 * @param linkedVec Interface for the linked vector of DataLinks.
23 * @param ownFlag If true, take ownership of the object.
24 */
25template <class T, class ALLOC>
26JaggedVecVectorHolder<T, ALLOC>::JaggedVecVectorHolder
27 (auxid_t auxid,
28 vector_type* vecPtr,
29 IAuxTypeVector* linkedVec,
30 bool ownFlag)
31 : Base (auxid, vecPtr, ownFlag, false),
32 m_linkedVec (linkedVec)
33{
34}
35
36
37/**
38 * @brief Change the size of the vector.
39 * @param sz The new vector size.
40 * Returns true if it is known that iterators have not been invalidated;
41 * false otherwise.
42 */
43template <class T, class ALLOC>
44inline
45bool JaggedVecVectorHolder<T, ALLOC>::resize (size_t sz)
46{
47 bool valid = true;
48 vector_type& vec = this->vec();
49 Elt zero;
50 if (sz < vec.size()) {
51 size_t payload_sz = sz > 0 ? vec[sz-1].end() : 0;
52 valid = m_linkedVec->resize (payload_sz);
53 }
54 else if (vec.size() > 0) {
55 size_t payload_sz = vec.back().end();
56 zero = Elt (payload_sz);
57 }
58 const void* orig = vec.data();
59 vec.resize (sz, zero);
60 this->storeDataSpan();
61 return valid && vec.data() == orig;
62}
63
64
65/**
66 * @brief Shift the elements of the vector.
67 * @param pos The starting index for the shift.
68 * @param offs The (signed) amount of the shift.
69 *
70 * This operation shifts the elements in the vectors for all
71 * aux data items, to implement an insertion or deletion.
72 * @c offs may be either positive or negative.
73 *
74 * If @c offs is positive, then the container is growing.
75 * The container size should be increased by @c offs,
76 * the element at @c pos moved to @c pos + @c offs,
77 * and similarly for following elements.
78 * The elements between @c pos and @c pos + @c offs should
79 * be default-initialized.
80 *
81 * If @c offs is negative, then the container is shrinking.
82 * The element at @c pos should be moved to @c pos + @c offs,
83 * and similarly for following elements.
84 * The container should then be shrunk by @c -offs elements
85 * (running destructors as appropriate).
86 *
87 * Returns true if it is known that iterators have not been invalidated;
88 * false otherwise. (Will always return false when increasing the size
89 * of an empty container.)
90 */
91template <class T, class ALLOC>
92bool JaggedVecVectorHolder<T, ALLOC>::shift (size_t pos, ptrdiff_t offs)
93{
94 vector_type& vec = this->vec();
95 if (offs < 0) {
96 if (-offs > static_cast<ptrdiff_t>(pos)) offs = -pos;
97 size_t ppos = pos < vec.size() ? vec[pos].begin(pos) : m_linkedVec->size();
98 ptrdiff_t poffs = - (ppos - vec[pos+offs].begin(pos+offs));
99 m_linkedVec->shift (ppos, poffs);
100 vec.erase (vec.begin() + pos+offs, vec.begin() + pos);
101 std::for_each (vec.begin() + pos+offs, vec.end(), Shift (poffs));
102 this->storeDataSpan();
103 return true;
104 }
105 else if (offs > 0) {
106 const void* orig = vec.data();
107 size_t oldsz = vec.size();
108 Elt zero;
109 if (!vec.empty()) {
110 index_type end = vec.back().end();
111 zero = Elt (end);
112 }
113 // Add to the end, zero-filled.
114 vec.resize (vec.size() + offs, zero);
115 if (oldsz != pos) {
116 // Shift existing elements. If we're just extending,
117 // then we can skip this.
118 std::copy (vec.rbegin() + offs,
119 vec.rbegin() + (offs+oldsz-pos),
120 vec.rbegin());
121 if (pos == 0) {
122 zero = Elt (0);
123 }
124 else {
125 index_type end = vec[pos-1].end();
126 zero = Elt (end);
127 }
128 std::fill_n (vec.begin() + pos, offs, zero);
129 }
130 this->storeDataSpan();
131 return vec.data() == orig;
132 }
133 return true;
134}
135
136
137/**
138 * @brief Insert elements into the vector via move semantics.
139 * @param pos The starting index of the insertion.
140 * @param src Start of the vector containing the range of elements to insert.
141 * @param src_pos Position of the first element to insert.
142 * @param src_n Number of elements to insert.
143 * @param srcStore The source store.
144 *
145 * @c beg and @c end define a range of container elements, with length
146 * @c len defined by the difference of the pointers divided by the
147 * element size.
148 *
149 * The size of the container will be increased by @c len, with the elements
150 * starting at @c pos copied to @c pos+len.
151 *
152 * The contents of the source range will then be moved to our vector
153 * starting at @c pos. This will be done via move semantics if possible;
154 * otherwise, it will be done with a copy.
155 *
156 * Returns true if it is known that the vector's memory did not move,
157 * false otherwise.
158 */
159template <class T, class ALLOC>
160bool JaggedVecVectorHolder<T, ALLOC>::insertMove
161 (size_t pos, void* src, size_t src_pos, size_t src_n, IAuxStore& srcStore)
162{
163 if (src_n <= 0) return true;
164 element_type* srcp = reinterpret_cast<element_type*> (src);
165 element_type* beg = srcp + src_pos;
166 element_type* end = beg + src_n;
167
168 vector_type& vec = this->vec();
169 const element_type* orig = vec.data();
170 vec.insert (vec.begin() + pos, beg, end);
171 size_t begidx = srcp[src_pos].begin(src_pos);
172 size_t npayload = beg[src_n-1].end() - begidx;
173 size_t ppos = vec[pos].begin(pos);
174 IAuxTypeVector* srcPayloadVec = srcStore.linkedVector (this->auxid());
175 T* srcPayload = reinterpret_cast<T*> (srcPayloadVec->toPtr());
176 bool pflag = m_linkedVec->insertMove (ppos,
177 srcPayload,
178 begidx,
179 npayload,
180 srcStore);
181 std::for_each (vec.begin() + pos, vec.begin() + pos + src_n,
182 Shift (ppos - begidx));
183 std::for_each (vec.begin() + pos + src_n, vec.end(),
184 Shift (npayload));
185 this->storeDataSpan();
186 return pflag && (vec.data() == orig);
187}
188
189
190//*****************************************************************************
191
192
193/**
194 * @brief Constructor. Makes a new vector.
195 * @param auxid The auxid of the variable this vector represents.
196 * @param size Initial size of the new vector.
197 * @param capacity Initial capacity of the new vector.
198 * @param linkedVec Ownership of the linked vector.
199 */
200template <class HOLDER>
201JaggedVecVectorT<HOLDER>::JaggedVecVectorT (auxid_t auxid,
202 size_t size,
203 size_t capacity,
204 std::unique_ptr<IAuxTypeVector> linkedVec)
205 : Base (auxid, &m_vec, linkedVec.get(), false),
206 m_linkedVecHolder (std::move (linkedVec))
207{
208 m_vec.reserve (capacity);
209 m_vec.resize (size);
210}
211
212
213/**
214 * @brief Copy constructor.
215 */
216template <class HOLDER>
217JaggedVecVectorT<HOLDER>::JaggedVecVectorT (const JaggedVecVectorT& other)
218 : Base (other.auxid(), &m_vec, false, false),
219 m_vec (other.m_vec),
220 m_linkedVecHolder (other.m_linkedVec->clone())
221{
222 Base::m_linkedVec = m_linkedVecHolder.get();
223}
224
225
226/**
227 * @brief Move constructor.
228 */
229template <class HOLDER>
230JaggedVecVectorT<HOLDER>::JaggedVecVectorT (JaggedVecVectorT&& other)
231 : Base (other.auxid(), &m_vec, false, other.m_linkedVec),
232 m_vec (std::move (other.m_vec)),
233 m_linkedVecHolder (std::move (other.m_linkedVecHolder))
234{
235}
236
237
238/**
239 * @brief Make a copy of this vector.
240 */
241template <class HOLDER>
242inline
243std::unique_ptr<IAuxTypeVector> JaggedVecVectorT<HOLDER>::clone() const
244{
245 return std::make_unique<JaggedVecVectorT> (*this);
246}
247
248
249/**
250 * @brief Return ownership of the linked vector.
251 */
252template <class HOLDER>
253inline
254std::unique_ptr<IAuxTypeVector> JaggedVecVectorT<HOLDER>::linkedVector()
255{
256 return std::move (m_linkedVecHolder);
257}
258
259
260} // namespace SG