0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / NCollection / NCollection_Array1.hxx
CommitLineData
1103eb60 1// Copyright (c) 2002-2023 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
7fd59977 13
14#ifndef NCollection_Array1_HeaderFile
15#define NCollection_Array1_HeaderFile
16
7fd59977 17#include <Standard_DimensionMismatch.hxx>
18#include <Standard_OutOfMemory.hxx>
1103eb60 19#include <Standard_NotImplemented.hxx>
7fd59977 20#include <Standard_OutOfRange.hxx>
7fd59977 21
ddf2fe8e 22#include <NCollection_DefineAlloc.hxx>
1103eb60 23#include <NCollection_Iterator.hxx>
24#include <NCollection_Allocator.hxx>
25#include <StdFail_NotDone.hxx>
26#include <NCollection_IndexedIterator.hxx>
27
28#include <algorithm>
29#include <array>
30#include <vector>
7fd59977 31
5e6e5914 32//! The class NCollection_Array1 represents unidimensional arrays of fixed size known at run time.
33//! The range of the index is user defined.
34//! An array1 can be constructed with a "C array".
35//! This functionality is useful to call methods expecting an Array1.
36//! It allows to carry the bounds inside the arrays.
37//!
38//! Examples:
39//! @code
40//! Item tab[100]; // an example with a C array
41//! NCollection_Array1<Item> ttab (tab[0], 1, 100);
42//!
43//! NCollection_Array1<Item> tttab (ttab(10), 10, 20); // a slice of ttab
44//! @endcode
45//! If you want to reindex an array from 1 to Length do:
46//! @code
47//! NCollection_Array1<Item> tab1 (tab (tab.Lower()), 1, tab.Length());
48//! @endcode
49//! Warning: Programs client of such a class must be independent of the range of the first element.
50//! Then, a C++ for loop must be written like this
51//! @code
52//! for (i = A.Lower(); i <= A.Upper(); i++)
53//! @endcode
ddf2fe8e 54template <class TheItemType>
55class NCollection_Array1
7fd59977 56{
79a35943 57public:
1103eb60 58 //! Memory allocation
59 DEFINE_STANDARD_ALLOC;
60 DEFINE_NCOLLECTION_ALLOC;
61public:
62 typedef NCollection_Allocator<TheItemType> allocator_type;
63public:
64 // Define various type aliases for convenience
65 using value_type = TheItemType;
66 using size_type = size_t;
67 using difference_type = size_t;
68 using pointer = TheItemType*;
69 using const_pointer = const TheItemType*;
70 using reference = TheItemType&;
71 using const_reference = const TheItemType&;
72
73 using iterator = NCollection_IndexedIterator<std::random_access_iterator_tag, NCollection_Array1, value_type, false>;
74 using const_iterator = NCollection_IndexedIterator<std::random_access_iterator_tag, NCollection_Array1, value_type, true>;
ffd7a3aa 75 using Iterator = NCollection_Iterator<NCollection_Array1<TheItemType>>;
7fd59977 76
79a35943 77public:
1103eb60 78
1103eb60 79 const_iterator begin() const
80 {
81 return const_iterator(*this);
82 }
79a35943 83
1103eb60 84 iterator begin()
85 {
86 return iterator(*this);
87 }
79a35943 88
1103eb60 89 const_iterator cbegin() const
90 {
91 return const_iterator(*this);
92 }
79a35943 93
1103eb60 94 iterator end()
95 {
96 return iterator(mySize, *this);
97 }
79a35943 98
1103eb60 99 const_iterator end() const
100 {
101 return const_iterator(mySize, *this);
102 }
79a35943 103
1103eb60 104 const_iterator cend() const
105 {
106 return const_iterator(mySize, *this);
107 }
7fd59977 108
1103eb60 109public:
110 // Constructors
111 NCollection_Array1() :
112 myLowerBound(1),
113 mySize(0)
114 {}
115
116 explicit NCollection_Array1(const Standard_Integer theLower,
117 const Standard_Integer theUpper) :
118 myLowerBound(theLower),
119 mySize(theUpper - theLower + 1)
4954e497 120 {
1103eb60 121 if (mySize == 0)
122 {
123 return;
124 }
125 myPointer = myAllocator.allocate(mySize);
126 myIsOwner = true;
127 construct();
4954e497 128 }
129
1103eb60 130 explicit NCollection_Array1(const allocator_type& theAlloc,
131 const Standard_Integer theLower,
132 const Standard_Integer theUpper) :
133 myLowerBound(theLower),
134 mySize(theUpper - theLower + 1),
135 myPointer(nullptr),
136 myIsOwner(false),
ffd7a3aa 137 myAllocator(theAlloc)
7fd59977 138 {
1103eb60 139 if (mySize == 0)
140 {
141 return;
142 }
143 myPointer = myAllocator.allocate(mySize);
144 myIsOwner = true;
145 construct();
146 }
7fd59977 147
1103eb60 148 explicit NCollection_Array1(const_reference theBegin,
149 const Standard_Integer theLower,
150 const Standard_Integer theUpper,
151 const bool theUseBuffer = true) :
152 myLowerBound(theLower),
153 mySize(theUpper - theLower + 1),
154 myPointer(theUseBuffer ? const_cast<pointer>(&theBegin) : nullptr),
155 myIsOwner(!theUseBuffer)
156 {
157 if (!myIsOwner)
158 {
159 return;
160 }
161 myPointer = myAllocator.allocate(mySize);
162 myIsOwner = true;
163 construct();
7fd59977 164 }
165
166 //! Copy constructor
1103eb60 167 NCollection_Array1(const NCollection_Array1& theOther) :
168 myLowerBound(theOther.myLowerBound),
169 mySize(theOther.mySize)
7fd59977 170 {
1103eb60 171 if (mySize == 0)
172 {
173 return;
174 }
175 myPointer = myAllocator.allocate(mySize);
176 myIsOwner = true;
177 copyConstruct(theOther.myPointer, mySize);
7fd59977 178 }
179
4954e497 180 //! Move constructor
1103eb60 181 NCollection_Array1(NCollection_Array1&& theOther) noexcept :
182 myLowerBound(theOther.myLowerBound),
183 mySize(theOther.mySize),
184 myPointer(theOther.myPointer),
185 myIsOwner(theOther.myIsOwner)
186 {
187 theOther.myIsOwner = false;
188 }
189
190 virtual ~NCollection_Array1()
191 {
192 if (!myIsOwner)
193 {
194 return;
195 }
196 destroy();
197 myAllocator.deallocate(myPointer, mySize);
7fd59977 198 }
199
200 //! Initialise the items with theValue
1103eb60 201 void Init(const_reference theValue)
7fd59977 202 {
1103eb60 203 for (size_t anIter = 0; anIter < mySize; anIter++)
204 {
205 myPointer[anIter] = theValue;
206 }
7fd59977 207 }
208
209 //! Size query
1103eb60 210 Standard_Integer Size() const
211 {
212 return Length();
213 }
214
7fd59977 215 //! Length query (the same)
1103eb60 216 Standard_Integer Length() const
217 {
218 return static_cast<Standard_Integer>(mySize);
219 }
7fd59977 220
4954e497 221 //! Return TRUE if array has zero length.
1103eb60 222 Standard_Boolean IsEmpty() const
223 {
224 return mySize == 0;
225 }
4954e497 226
7fd59977 227 //! Lower bound
1103eb60 228 Standard_Integer Lower() const
229 {
230 return myLowerBound;
231 }
7fd59977 232
1103eb60 233 //! Upper bound
234 Standard_Integer Upper() const
235 {
236 return myLowerBound + static_cast<int>(mySize) - 1;
237 }
7fd59977 238
6286195c 239 //! Copies data of theOther array to this.
240 //! This array should be pre-allocated and have the same length as theOther;
241 //! otherwise exception Standard_DimensionMismatch is thrown.
1103eb60 242 NCollection_Array1& Assign(const NCollection_Array1& theOther)
7fd59977 243 {
244 if (&theOther == this)
4954e497 245 {
246 return *this;
247 }
1103eb60 248 Standard_DimensionMismatch_Raise_if(mySize != theOther.mySize, "NCollection_Array1::operator=");
249 for (size_t anInd = 0; anInd < mySize; anInd++)
250 {
251 myPointer[anInd] = theOther.myPointer[anInd];
252 }
253 // Current implementation disable changing bounds by assigning
4954e497 254 return *this;
255 }
256
6286195c 257 //! Move assignment.
258 //! This array will borrow all the data from theOther.
259 //! The moved object will keep pointer to the memory buffer and
260 //! range, but it will not free the buffer on destruction.
1103eb60 261 NCollection_Array1& Move(NCollection_Array1&& theOther) noexcept
4954e497 262 {
263 if (&theOther == this)
264 {
265 return *this;
266 }
1103eb60 267 if (myIsOwner)
4954e497 268 {
1103eb60 269 destroy();
270 myAllocator.deallocate(myPointer, mySize);
4954e497 271 }
272 myLowerBound = theOther.myLowerBound;
1103eb60 273 mySize = theOther.mySize;
274 myPointer = theOther.myPointer;
275 myIsOwner = theOther.myIsOwner;
276 theOther.myIsOwner = false;
4954e497 277 return *this;
7fd59977 278 }
279
1103eb60 280 NCollection_Array1& Move(NCollection_Array1& theOther)
281 {
282 return Move(std::move(theOther));
283 }
284
6286195c 285 //! Assignment operator; @sa Assign()
ddf2fe8e 286 NCollection_Array1& operator= (const NCollection_Array1& theOther)
1103eb60 287 {
288 return Assign(theOther);
ddf2fe8e 289 }
290
6286195c 291 //! Move assignment operator; @sa Move()
1103eb60 292 NCollection_Array1& operator= (NCollection_Array1&& theOther) noexcept
4954e497 293 {
1103eb60 294 return Move(std::forward<NCollection_Array1>(theOther));
4954e497 295 }
296
a174a3c5 297 //! @return first element
1103eb60 298 const_reference First() const
a174a3c5 299 {
1103eb60 300 return myPointer[0];
a174a3c5 301 }
302
303 //! @return first element
1103eb60 304 reference ChangeFirst()
a174a3c5 305 {
1103eb60 306 return myPointer[0];
a174a3c5 307 }
308
309 //! @return last element
1103eb60 310 const_reference Last() const
a174a3c5 311 {
1103eb60 312 return myPointer[mySize - 1];
a174a3c5 313 }
314
315 //! @return last element
1103eb60 316 reference ChangeLast()
a174a3c5 317 {
1103eb60 318 return myPointer[mySize - 1];
a174a3c5 319 }
320
7fd59977 321 //! Constant value access
1103eb60 322 const_reference Value(const Standard_Integer theIndex) const
7fd59977 323 {
1103eb60 324 const size_t aPos = theIndex - myLowerBound;
325 Standard_OutOfRange_Raise_if(aPos >= mySize, "NCollection_Array1::Value");
326 return myPointer[aPos];
7fd59977 327 }
328
329 //! operator() - alias to Value
1103eb60 330 const_reference operator() (const Standard_Integer theIndex) const
331 {
332 return Value(theIndex);
333 }
7fd59977 334
b8f7f608 335 //! operator[] - alias to Value
1103eb60 336 const_reference operator[] (const Standard_Integer theIndex) const
337 {
338 return Value(theIndex);
339 }
b8f7f608 340
7fd59977 341 //! Variable value access
1103eb60 342 reference ChangeValue(const Standard_Integer theIndex)
7fd59977 343 {
1103eb60 344 const size_t aPos = theIndex - myLowerBound;
345 Standard_OutOfRange_Raise_if(aPos >= mySize, "NCollection_Array1::ChangeValue");
346 return myPointer[aPos];
7fd59977 347 }
348
349 //! operator() - alias to ChangeValue
1103eb60 350 reference operator() (const Standard_Integer theIndex)
351 {
352 return ChangeValue(theIndex);
353 }
7fd59977 354
b8f7f608 355 //! operator[] - alias to ChangeValue
1103eb60 356 reference operator[] (const Standard_Integer theIndex)
357 {
358 return ChangeValue(theIndex);
359 }
360
361 //! Set value
362 void SetValue(const Standard_Integer theIndex,
363 const value_type& theItem)
364 {
365 const size_t aPos = theIndex - myLowerBound;
366 Standard_OutOfRange_Raise_if(aPos >= mySize, "NCollection_Array1::SetValue");
367 myPointer[aPos] = theItem;
368 }
b8f7f608 369
7fd59977 370 //! Set value
1103eb60 371 void SetValue(const Standard_Integer theIndex,
372 value_type&& theItem)
7fd59977 373 {
1103eb60 374 const size_t aPos = theIndex - myLowerBound;
375 Standard_OutOfRange_Raise_if(aPos >= mySize, "NCollection_Array1::SetValue");
376 myPointer[aPos] = std::forward<value_type>(theItem);
377 }
378
379 //! Changes the lowest bound. Do not move data
380 void UpdateLowerBound(const Standard_Integer theLower)
381 {
382 myLowerBound = theLower;
383 }
384
385 //! Changes the upper bound. Do not move data
386 void UpdateUpperBound(const Standard_Integer theUpper)
387 {
388 myLowerBound = myLowerBound - Upper() + theUpper;
7fd59977 389 }
390
4954e497 391 //! Resizes the array to specified bounds.
392 //! No re-allocation will be done if length of array does not change,
393 //! but existing values will not be discarded if theToCopyData set to FALSE.
394 //! @param theLower new lower bound of array
395 //! @param theUpper new upper bound of array
396 //! @param theToCopyData flag to copy existing data into new array
1103eb60 397 void Resize(const Standard_Integer theLower,
398 const Standard_Integer theUpper,
399 const Standard_Boolean theToCopyData)
4954e497 400 {
1103eb60 401 Standard_RangeError_Raise_if(theUpper < theLower, "NCollection_Array1::Resize");
402 const size_t aNewSize = static_cast<size_t>(theUpper - theLower + 1);
403 const size_t anOldSize = mySize;
404 pointer aPrevContPnt = myPointer;
405 if (aNewSize == anOldSize)
4954e497 406 {
1103eb60 407 myLowerBound = theLower;
4954e497 408 return;
409 }
1103eb60 410 if (myIsOwner)
411 {
412 if (theToCopyData)
413 destroy(myPointer, aNewSize, mySize);
414 else
415 destroy();
416 }
417 myLowerBound = theLower;
418 mySize = aNewSize;
419 if (theToCopyData)
420 {
421 const size_t aMinSize = std::min<size_t>(aNewSize, anOldSize);
422 if (myIsOwner)
423 {
424 myPointer = myAllocator.reallocate(myPointer, aNewSize);
425 }
426 else
427 {
428 myPointer = myAllocator.allocate(aNewSize);
429 copyConstruct(aPrevContPnt, aMinSize);
430 }
431 construct(anOldSize, aNewSize);
432 }
433 else
434 {
435 if (myIsOwner)
436 myAllocator.deallocate(aPrevContPnt, mySize);
437 myPointer = myAllocator.allocate(aNewSize);
438 construct();
439 }
440 myIsOwner = true;
441 }
442
443 bool IsDeletable() const
444 {
445 return myIsOwner;
446 }
447
448 friend iterator;
449 friend const_iterator;
450
451protected:
452
453 const_reference at(const size_t theIndex) const
454 {
455 Standard_OutOfRange_Raise_if(theIndex >= mySize, "NCollection_Array1::at");
456 return myPointer[theIndex];
457 }
458
459 reference at(const size_t theIndex)
460 {
461 Standard_OutOfRange_Raise_if(theIndex >= mySize, "NCollection_Array1::at");
462 return myPointer[theIndex];
463 }
464
465protected:
466
467 template <typename U = TheItemType>
468 typename std::enable_if<std::is_arithmetic<U>::value, void>::type construct()
469 {
470 // Do nothing
471 }
4954e497 472
1103eb60 473 template <typename U = TheItemType>
474 typename std::enable_if<!std::is_arithmetic<U>::value, void>::type construct()
475 {
476 for (size_t anInd = 0; anInd < mySize; anInd++)
4954e497 477 {
1103eb60 478 myAllocator.construct(myPointer + anInd);
4954e497 479 }
1103eb60 480 }
481
482 template <typename U = TheItemType>
483 typename std::enable_if<std::is_arithmetic<U>::value, void>::type construct(const size_t,
484 const size_t)
485 {
486 // Do nothing
487 }
488
489 template <typename U = TheItemType>
490 typename std::enable_if<!std::is_arithmetic<U>::value, void>::type construct(const size_t theFrom,
491 const size_t theTo)
492 {
493 for (size_t anInd = theFrom; anInd < theTo; anInd++)
4954e497 494 {
1103eb60 495 myAllocator.construct(myPointer + anInd);
4954e497 496 }
1103eb60 497 }
4954e497 498
1103eb60 499 template <typename U = TheItemType>
500 typename std::enable_if<std::is_arithmetic<U>::value, void>::type destroy()
501 {
502 // Do nothing
503 }
504
505 template <typename U = TheItemType>
506 typename std::enable_if<!std::is_arithmetic<U>::value, void>::type destroy()
507 {
508 for (size_t anInd = 0; anInd < mySize; anInd++)
4954e497 509 {
1103eb60 510 myAllocator.destroy(myPointer + anInd);
4954e497 511 }
1103eb60 512 }
513
514 template <typename U = TheItemType>
515 typename std::enable_if<std::is_arithmetic<U>::value, void>::type destroy(pointer,
516 const size_t,
517 const size_t)
518 {
519 // Do nothing
520 }
521
522 template <typename U = TheItemType>
523 typename std::enable_if<!std::is_arithmetic<U>::value, void>::type destroy(pointer theWhat,
524 const size_t theFrom,
525 const size_t theTo)
526 {
527 for (size_t anInd = theFrom; anInd < theTo; anInd++)
4954e497 528 {
1103eb60 529 myAllocator.destroy(theWhat + anInd);
4954e497 530 }
4954e497 531 }
532
1103eb60 533 void copyConstruct(const pointer theFrom,
534 const size_t theCount)
535 {
536 for (size_t anInd = 0; anInd < theCount; anInd++)
537 {
538 myAllocator.construct(myPointer + anInd, theFrom[anInd]);
539 }
6286195c 540 }
7fd59977 541
7fd59977 542 // ---------- PROTECTED FIELDS -----------
1103eb60 543 Standard_Integer myLowerBound;
544 size_t mySize;
545 pointer myPointer = nullptr;
546 bool myIsOwner = false;
547 allocator_type myAllocator;
7fd59977 548};
549
7fd59977 550#endif