opennurbs_array_defs.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(ON_ARRAY_DEFS_INC_)
18 #define ON_ARRAY_DEFS_INC_
19 
20 // When this file is parsed with /W4 warnings, two bogus warnings
21 // are generated.
22 #pragma ON_PRAGMA_WARNING_PUSH
23 
24 // The ON_ClassArray<T>::DestroyElement template function generates a
25 // C4100: 'x' : unreferenced formal parameter
26 // warning.
27 // This appears to be caused by a bug in the compiler warning code
28 // or the way templates are expanded. This pragma is needed squelch the
29 // bogus warning.
30 #pragma ON_PRAGMA_WARNING_DISABLE_MSC(4100)
31 
32 // The ON_CompareIncreasing and ON_CompareDecreasing templates generate a
33 // C4211: nonstandard extension used : redefined extern to static
34 // warning. Microsoft's compiler appears to have a little trouble
35 // when static functions are declared before they are defined in a
36 // single .cpp file. This pragma is needed squelch the bogus warning.
37 #pragma ON_PRAGMA_WARNING_DISABLE_MSC(4211)
38 
39 // The main reason the definitions of the functions for the
40 // ON_SimpleArray and ON_ClassArray templates are in this separate
41 // file is so that the Microsoft developer studio autocomplete
42 // functions will work on these classes.
43 //
44 // This file is included by opennurbs_array.h in the appropriate
45 // spot. If you need the definitions in the file, then you
46 // should include opennurbs_array.h and let it take care of
47 // including this file.
48 
49 
50 /////////////////////////////////////////////////////////////////////////////////////
51 // Class ON_SimpleArray<>
52 /////////////////////////////////////////////////////////////////////////////////////
53 
54 // construction ////////////////////////////////////////////////////////
55 
56 template <class T>
57 T* ON_SimpleArray<T>::Realloc(T* ptr,int capacity)
58 {
59  return (T*)onrealloc(ptr,capacity*sizeof(T));
60 }
61 
62 template <class T>
64  : m_a(nullptr)
65  , m_count(0)
66  , m_capacity(0)
67 {}
68 
69 template <class T>
71  : m_a(nullptr)
72  , m_count(0)
73  , m_capacity(0)
74 {
75  if ( c > 0 )
76  SetCapacity( c );
77 }
78 
79 // Copy constructor
80 template <class T>
82  : m_a(0)
83  , m_count(0)
84  , m_capacity(0)
85 {
86  *this = src; // operator= defined below
87 }
88 
89 template <class T>
91 {
92  SetCapacity(0);
93 }
94 
95 template <class T>
97 {
98  if( this != &src ) {
99  if ( src.m_count <= 0 ) {
100  m_count = 0;
101  }
102  else {
103  if ( m_capacity < src.m_count ) {
104  SetCapacity( src.m_count );
105  }
106  if ( m_a ) {
107  m_count = src.m_count;
108  memcpy( (void*)(m_a), (void*)(src.m_a), m_count*sizeof(T) );
109  }
110  }
111  }
112  return *this;
113 }
114 
115 #if defined(ON_HAS_RVALUEREF)
116 
117 // Clone constructor
118 template <class T>
120  : m_a(src.m_a)
121  , m_count(src.m_count)
122  , m_capacity(src.m_capacity)
123 {
124  src.m_a = 0;
125  src.m_count = 0;
126  src.m_capacity = 0;
127 }
128 
129 // Clone assignment
130 template <class T>
132 {
133  if( this != &src )
134  {
135  this->Destroy();
136  m_a = src.m_a;
137  m_count = src.m_count;
138  m_capacity = src.m_capacity;
139  src.m_a = 0;
140  src.m_count = 0;
141  src.m_capacity = 0;
142  }
143  return *this;
144 }
145 
146 #endif
147 
148 // emergency destroy ///////////////////////////////////////////////////
149 
150 template <class T>
152 {
153  m_count = 0;
154  m_capacity = 0;
155  m_a = 0;
156 }
157 
158 // query ///////////////////////////////////////////////////////////////
159 
160 template <class T>
162 {
163  return m_count;
164 }
165 
166 template <class T>
168 {
169  return ((unsigned int)m_count);
170 }
171 
172 template <class T>
174 {
175  return m_capacity;
176 }
177 
178 template <class T>
179 unsigned int ON_SimpleArray<T>::SizeOfArray() const
180 {
181  return ((unsigned int)(m_capacity*sizeof(T)));
182 }
183 
184 template <class T>
186 {
187  return ((unsigned int)(sizeof(T)));
188 }
189 
190 
191 template <class T>
192 ON__UINT32 ON_SimpleArray<T>::DataCRC(ON__UINT32 current_remainder) const
193 {
194  return ON_CRC32(current_remainder,m_count*sizeof(m_a[0]),m_a);
195 }
196 
197 template <class T>
199 {
200 #if defined(ON_DEBUG)
201  if ( i < 0 || i > m_capacity )
202  {
203  ON_ERROR("ON_SimpleArray[i]: i out of range.");
204  }
205 #endif
206  return m_a[i];
207 }
208 
209 template <class T>
210 T& ON_SimpleArray<T>::operator[]( unsigned int i )
211 {
212 #if defined(ON_DEBUG)
213  if ( i > (unsigned int)m_capacity )
214  {
215  ON_ERROR("ON_SimpleArray[i]: i out of range.");
216  }
217 #endif
218  return m_a[i];
219 }
220 
221 
222 template <class T>
224 {
225 #if defined(ON_DEBUG)
226  if ( i < 0 || i > (ON__INT64)m_capacity )
227  {
228  ON_ERROR("ON_SimpleArray[i]: i out of range.");
229  }
230 #endif
231  return m_a[i];
232 }
233 
234 template <class T>
236 {
237 #if defined(ON_DEBUG)
238  if ( i > (ON__UINT64)m_capacity )
239  {
240  ON_ERROR("ON_SimpleArray[i]: i out of range.");
241  }
242 #endif
243  return m_a[i];
244 }
245 
246 
247 #if defined(ON_RUNTIME_APPLE)
248 template <class T>
249 T& ON_SimpleArray<T>::operator[](size_t i )
250 {
251 #if defined(ON_DEBUG)
252  if ( i > (size_t)m_capacity )
253  {
254  ON_ERROR("ON_SimpleArray[i]: i out of range.");
255  }
256 #endif
257  return m_a[i];
258 }
259 #endif
260 
261 template <class T>
262 const T& ON_SimpleArray<T>::operator[](int i) const
263 {
264 #if defined(ON_DEBUG)
265  if ( i < 0 || i > m_capacity )
266  {
267  ON_ERROR("ON_SimpleArray[i]: i out of range.");
268  }
269 #endif
270  return m_a[i];
271 }
272 
273 template <class T>
274 const T& ON_SimpleArray<T>::operator[](unsigned int i) const
275 {
276 #if defined(ON_DEBUG)
277  if ( i > (unsigned int)m_capacity )
278  {
279  ON_ERROR("ON_SimpleArray[i]: i out of range.");
280  }
281 #endif
282  return m_a[i];
283 }
284 
285 
286 template <class T>
287 const T& ON_SimpleArray<T>::operator[](ON__INT64 i) const
288 {
289 #if defined(ON_DEBUG)
290  if ( i < 0 || i > ((ON__INT64)m_capacity) )
291  {
292  ON_ERROR("ON_SimpleArray[i]: i out of range.");
293  }
294 #endif
295  return m_a[i];
296 }
297 
298 template <class T>
299 const T& ON_SimpleArray<T>::operator[](ON__UINT64 i) const
300 {
301 #if defined(ON_DEBUG)
302  if ( i > (ON__UINT64)m_capacity )
303  {
304  ON_ERROR("ON_SimpleArray[i]: i out of range.");
305  }
306 #endif
307  return m_a[i];
308 }
309 
310 #if defined(ON_RUNTIME_APPLE)
311 template <class T>
312 const T& ON_SimpleArray<T>::operator[](size_t i) const
313 {
314 #if defined(ON_DEBUG)
315  if ( i > (size_t)m_capacity )
316  {
317  ON_ERROR("ON_SimpleArray[i]: i out of range.");
318  }
319 #endif
320  return m_a[i];
321 }
322 #endif
323 
324 template <class T>
326 {
327  return (m_count > 0) ? m_a : 0;
328 }
329 
330 template <class T>
332 {
333  return (m_count > 0) ? m_a : 0;
334 }
335 
336 template <class T>
338 {
339  return m_a;
340 }
341 
342 template <class T>
343 const T* ON_SimpleArray<T>::Array() const
344 {
345  return m_a;
346 }
347 
348 template <class T>
350 {
351  T* p = m_a;
352  m_a = 0;
353  m_count = 0;
354  m_capacity = 0;
355  return p;
356 }
357 
358 template <class T>
360 {
361  if ( m_a && m_a != p )
362  onfree(m_a);
363  m_a = p;
364 }
365 
366 template <class T>
367 void ON_SimpleArray<T>::SetArray(T* p, int count, int capacity)
368 {
369  if ( m_a && m_a != p )
370  onfree(m_a);
371  m_a = p;
372  m_count = count;
373  m_capacity = capacity;
374 }
375 
376 template <class T>
378 {
379  return (m_count > 0) ? m_a : 0;
380 }
381 
382 template <class T>
383 const T* ON_SimpleArray<T>::First() const
384 {
385  return (m_count > 0) ? m_a : 0;
386 }
387 
388 template <class T>
390 {
391  return (i >= 0 && i < m_count) ? m_a+i : 0;
392 }
393 
394 template <class T>
395 T* ON_SimpleArray<T>::At( unsigned int i )
396 {
397  return (i < (unsigned int)m_count) ? m_a+i : 0;
398 }
399 
400 template <class T>
401 const T* ON_SimpleArray<T>::At( int i) const
402 {
403  return (i >= 0 && i < m_count) ? m_a+i : 0;
404 }
405 
406 template <class T>
407 const T* ON_SimpleArray<T>::At( unsigned int i) const
408 {
409  return (i < (unsigned int)m_count) ? m_a+i : 0;
410 }
411 
412 template <class T>
413 T* ON_SimpleArray<T>::At( ON__INT64 i )
414 {
415  return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0;
416 }
417 
418 template <class T>
419 T* ON_SimpleArray<T>::At( ON__UINT64 i )
420 {
421  return (i < (ON__UINT64)m_count) ? m_a+i : 0;
422 }
423 
424 template <class T>
425 const T* ON_SimpleArray<T>::At( ON__INT64 i) const
426 {
427  return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0;
428 }
429 
430 template <class T>
431 const T* ON_SimpleArray<T>::At( ON__UINT64 i) const
432 {
433  return (i < (ON__UINT64)m_count) ? m_a+i : 0;
434 }
435 
436 template <class T>
438 {
439  return (m_count > 0) ? m_a+(m_count-1) : 0;
440 }
441 
442 template <class T>
443 const T* ON_SimpleArray<T>::Last() const
444 {
445  return (m_count > 0) ? m_a+(m_count-1) : 0;
446 }
447 
448 // array operations ////////////////////////////////////////////////////
449 
450 template <class T>
451 void ON_SimpleArray<T>::Move( int dest_i, int src_i, int ele_cnt )
452 {
453  // private function for moving blocks of array memory
454  // caller is responsible for updating m_count.
455  if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i ||
456  src_i + ele_cnt > m_count || dest_i > m_count )
457  return;
458 
459  int capacity = dest_i + ele_cnt;
460  if ( capacity > m_capacity ) {
461  if ( capacity < 2*m_capacity )
462  capacity = 2*m_capacity;
463  SetCapacity( capacity );
464  }
465 
466  memmove( &m_a[dest_i], &m_a[src_i], ele_cnt*sizeof(T) );
467 }
468 
469 template <class T>
471 {
472  if ( m_count == m_capacity )
473  {
474  int new_capacity = NewCapacity();
475  Reserve( new_capacity );
476  }
477  memset( (void*)(&m_a[m_count]), 0, sizeof(T) );
478  return m_a[m_count++];
479 }
480 
481 template <class T>
482 void ON_SimpleArray<T>::Append( const T& x )
483 {
484  if ( m_count == m_capacity )
485  {
486  const int newcapacity = NewCapacity();
487  if (m_a)
488  {
489  const int s = (int)(&x - m_a); // (int) cast is for 64 bit pointers
490  if ( s >= 0 && s < m_capacity )
491  {
492  // 26 Sep 2005 Dale Lear
493  // User passed in an element of the m_a[]
494  // that will get reallocated by the call
495  // to Reserve(newcapacity).
496  T temp; // ON_*Array<> templates do not require robust copy constructor.
497  temp = x; // ON_*Array<> templates require a robust operator=.
498  Reserve( newcapacity );
499  m_a[m_count++] = temp;
500  return;
501  }
502  }
503  Reserve(newcapacity);
504  }
505  m_a[m_count++] = x;
506 }
507 
508 template <class T>
509 void ON_SimpleArray<T>::Append( int count, const T* p )
510 {
511  if ( count > 0 && p )
512  {
513  if ( count + m_count > m_capacity )
514  {
515  int newcapacity = NewCapacity();
516  if ( newcapacity < count + m_count )
517  newcapacity = count + m_count;
518  Reserve( newcapacity );
519  }
520  memcpy( (void*)(m_a + m_count), (void*)(p), count*sizeof(T) );
521  m_count += count;
522  }
523 }
524 
525 template <class T>
526 void ON_SimpleArray<T>::Insert( int i, const T& x )
527 {
528  if( i >= 0 && i <= m_count )
529  {
530  if ( m_count == m_capacity )
531  {
532  int newcapacity = NewCapacity();
533  Reserve( newcapacity );
534  }
535  m_count++;
536  Move( i+1, i, m_count-1-i );
537  m_a[i] = x;
538  }
539 }
540 
541 template <class T>
543 {
544  Remove(m_count-1);
545 }
546 
547 template <class T>
549 {
550  if ( i >= 0 && i < m_count ) {
551  Move( i, i+1, m_count-1-i );
552  m_count--;
553  memset( (void*)(&m_a[m_count]), 0, sizeof(T) );
554  }
555 }
556 
557 template <class T>
559 {
560  if ( m_a )
561  memset( (void*)(m_a), 0, m_capacity*sizeof(T) );
562  m_count = 0;
563 }
564 
565 template <class T>
567 {
568  // NOTE:
569  // If anything in "T" depends on the value of this's address,
570  // then don't call Reverse().
571  T t;
572  int i = 0;
573  int j = m_count-1;
574  for ( /*empty*/; i < j; i++, j-- ) {
575  t = m_a[i];
576  m_a[i] = m_a[j];
577  m_a[j] = t;
578  }
579 }
580 
581 template <class T>
582 void ON_SimpleArray<T>::Swap( int i, int j )
583 {
584  if ( i != j ) {
585  const T t(m_a[i]);
586  m_a[i] = m_a[j];
587  m_a[j] = t;
588  }
589 }
590 
591 template <class T>
592 int ON_SimpleArray<T>::Search( const T& key ) const
593 {
594  const T* p = &key;
595  for ( int i = 0; i < m_count; i++ ) {
596  if (!memcmp(p,m_a+i,sizeof(T)))
597  return i;
598  }
599  return -1;
600 }
601 
602 template <class T>
603 int ON_SimpleArray<T>::Search( const T* key, int (*compar)(const T*,const T*) ) const
604 {
605  for ( int i = 0; i < m_count; i++ ) {
606  if (!compar(key,m_a+i))
607  return i;
608  }
609  return -1;
610 }
611 
612 template <class T>
613 int ON_SimpleArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const
614 {
615  const T* found = (key&&m_a&&m_count>0)
616  ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar )
617  : 0;
618 
619  // This worked on a wide range of 32 bit compilers.
620 
621  int rc;
622  if ( 0 != found )
623  {
624  // Convert "found" pointer to array index.
625 
626 #if defined(ON_COMPILER_MSC1300)
627  rc = ((int)(found - m_a));
628 #elif 8 == ON_SIZEOF_POINTER
629  // In an ideal world, return ((int)(found - m_a)) would work everywhere.
630  // In practice, this should work any 64 bit compiler and we can hope
631  // the optimzer generates efficient code.
632  const ON__UINT64 fptr = (ON__UINT64)found;
633  const ON__UINT64 aptr = (ON__UINT64)m_a;
634  const ON__UINT64 sz = (ON__UINT64)sizeof(T);
635  const ON__UINT64 i = (fptr - aptr)/sz;
636  rc = (int)i;
637 #else
638  // In an ideal world, return ((int)(found - m_a)) would work everywhere.
639  // In practice, this should work any 32 bit compiler and we can hope
640  // the optimzer generates efficient code.
641  const ON__UINT32 fptr = (ON__UINT32)found;
642  const ON__UINT32 aptr = (ON__UINT32)m_a;
643  const ON__UINT32 sz = (ON__UINT32)sizeof(T);
644  const ON__UINT32 i = (fptr - aptr)/sz;
645  rc = (int)i;
646 #endif
647  }
648  else
649  {
650  // "key" not found
651  rc = -1;
652  }
653 
654  return rc;
655 
656 }
657 
658 template <class T>
659 int ON_SimpleArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*), int count ) const
660 {
661  if ( count > m_count )
662  count = m_count;
663  if ( count <= 0 )
664  return -1;
665  const T* found = (key&&m_a&&m_count>0)
666  ? (const T*)bsearch( key, m_a, count, sizeof(T), (int(*)(const void*,const void*))compar )
667  : 0;
668 
669  // This worked on a wide range of 32 bit compilers.
670 
671  int rc;
672  if ( 0 != found )
673  {
674  // Convert "found" pointer to array index.
675 
676 #if defined(ON_COMPILER_MSC1300)
677  rc = ((int)(found - m_a));
678 #elif 8 == ON_SIZEOF_POINTER
679  // In an ideal world, return ((int)(found - m_a)) would work everywhere.
680  // In practice, this should work any 64 bit compiler and we can hope
681  // the optimzer generates efficient code.
682  const ON__UINT64 fptr = (ON__UINT64)found;
683  const ON__UINT64 aptr = (ON__UINT64)m_a;
684  const ON__UINT64 sz = (ON__UINT64)sizeof(T);
685  const ON__UINT64 i = (fptr - aptr)/sz;
686  rc = (int)i;
687 #else
688  // In an ideal world, return ((int)(found - m_a)) would work everywhere.
689  // In practice, this should work any 32 bit compiler and we can hope
690  // the optimzer generates efficient code.
691  const ON__UINT32 fptr = (ON__UINT32)found;
692  const ON__UINT32 aptr = (ON__UINT32)m_a;
693  const ON__UINT32 sz = (ON__UINT32)sizeof(T);
694  const ON__UINT32 i = (fptr - aptr)/sz;
695  rc = (int)i;
696 #endif
697  }
698  else
699  {
700  // "key" not found
701  rc = -1;
702  }
703  return rc;
704 }
705 
706 
707 
708 template <class T>
709 bool ON_SimpleArray<T>::HeapSort( int (*compar)(const T*,const T*) )
710 {
711  bool rc = false;
712  if ( m_a && m_count > 0 && compar ) {
713  if ( m_count > 1 )
714  ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
715  rc = true;
716  }
717  return rc;
718 }
719 
720 template <class T>
721 bool ON_SimpleArray<T>::QuickSort( int (*compar)(const T*,const T*) )
722 {
723  bool rc = false;
724  if ( m_a && m_count > 0 && compar ) {
725  if ( m_count > 1 )
726  ON_qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
727  rc = true;
728  }
729  return rc;
730 }
731 
732 template <class T>
733 bool ON_SimpleArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const
734 {
735  bool rc = false;
736  if ( m_a && m_count > 0 && compar && index ) {
737  if ( m_count > 1 )
738  ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
739  else if ( m_count == 1 )
740  index[0] = 0;
741  rc = true;
742  }
743  return rc;
744 }
745 
746 template <class T>
747 bool ON_SimpleArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const
748 {
749  bool rc = false;
750  if ( m_a && m_count > 0 && compar && index ) {
751  if ( m_count > 1 )
752  ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p );
753  else if ( m_count == 1 )
754  index[0] = 0;
755  rc = true;
756  }
757  return rc;
758 }
759 
760 template <class T>
761 bool ON_SimpleArray<T>::Permute( const int* index )
762 {
763  bool rc = false;
764  if ( m_a && m_count > 0 && index ) {
765  int i;
766  T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0]));
767  memcpy( (void*)(buffer), (void*)(m_a), m_count*sizeof(T) );
768  for (i = 0; i < m_count; i++ )
769  memcpy( (void*)(m_a+i), (void*)(buffer+index[i]), sizeof(T) ); // must use memcopy and not operator=
770  onfree(buffer);
771  rc = true;
772  }
773  return rc;
774 }
775 
776 template <class T>
778 {
779  if ( m_a && m_capacity > 0 ) {
780  memset( (void*)(m_a), 0, m_capacity*sizeof(T) );
781  }
782 }
783 
784 template <class T>
785 void ON_SimpleArray<T>::MemSet( unsigned char value )
786 {
787  if ( m_a && m_capacity > 0 ) {
788  memset( (void*)(m_a), value, m_capacity*sizeof(T) );
789  }
790 }
791 
792 // memory managment ////////////////////////////////////////////////////
793 
794 template <class T>
795 T* ON_SimpleArray<T>::Reserve( size_t newcap )
796 {
797  if( (size_t)m_capacity < newcap )
798  SetCapacity( newcap );
799  return m_a;
800 }
801 
802 template <class T>
804 {
805  SetCapacity( m_count );
806 }
807 
808 template <class T>
810 {
811  SetCapacity( 0 );
812 }
813 
814 // low level memory managment //////////////////////////////////////////
815 
816 template <class T>
817 void ON_SimpleArray<T>::SetCount( int count )
818 {
819  if ( count >= 0 && count <= m_capacity )
820  m_count = count;
821 }
822 
823 template <class T>
824 T* ON_SimpleArray<T>::SetCapacity( size_t new_capacity )
825 {
826  if (0 == m_capacity)
827  {
828  // Allow "expert" users of ON_SimpleArray<>.SetArray(*,*,0) to clean up after themselves
829  // and deals with the case when the forget to clean up after themselves.
830  m_a = nullptr;
831  m_count = 0;
832  }
833 
834  // sets capacity to input value
835  int capacity = (new_capacity > 0 && new_capacity < ON_UNSET_UINT_INDEX)
836  ? (int)new_capacity
837  : 0;
838  if ( capacity != m_capacity ) {
839  if( capacity > 0 ) {
840  if ( m_count > capacity )
841  m_count = capacity;
842  // NOTE: Realloc() does an allocation if the first argument is nullptr.
843  m_a = Realloc( m_a, capacity );
844  if ( m_a ) {
845  if ( capacity > m_capacity ) {
846  // zero new memory
847  memset( (void*) (m_a + m_capacity), 0, (capacity-m_capacity)*sizeof(T) );
848  }
849  m_capacity = capacity;
850  }
851  else {
852  // out of memory
853  m_count = m_capacity = 0;
854  }
855  }
856  else if (m_a) {
857  Realloc(m_a,0);
858  m_a = 0;
859  m_count = m_capacity = 0;
860  }
861  }
862  return m_a;
863 }
864 
865 template <class T>
867 {
868  // Note:
869  // This code appears in ON_SimpleArray<T>::NewCapacity()
870  // and ON_ClassArray<T>::NewCapacity(). Changes made to
871  // either function should be made to both functions.
872  // Because this code is template code that has to
873  // support dynamic linking and the code is defined
874  // in a header, I'm using copy-and-paste rather
875  // than a static.
876 
877  // This function returns 2*m_count unless that will
878  // result in an additional allocation of more than
879  // cap_size bytes. The cap_size concept was added in
880  // January 2010 because some calculations on enormous
881  // models were slightly underestimating the initial
882  // Reserve() size and then wasting gigabytes of memory.
883 
884  // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os
885  const size_t cap_size = 32*sizeof(void*)*1024*1024;
886  if (m_count*sizeof(T) <= cap_size || m_count < 8)
887  return ((m_count <= 2) ? 4 : 2*m_count);
888 
889  // Growing the array will increase the memory
890  // use by more than cap_size.
891  int delta_count = 8 + cap_size/sizeof(T);
892  if ( delta_count > m_count )
893  delta_count = m_count;
894  return (m_count + delta_count);
895 }
896 
897 template <class T>
899 {
900  // Note:
901  // This code appears in ON_SimpleArray<T>::NewCapacity()
902  // and ON_ClassArray<T>::NewCapacity(). Changes made to
903  // either function should be made to both functions.
904  // Because this code is template code that has to
905  // support dynamic linking and the code is defined
906  // in a header, I'm using copy-and-paste rather
907  // than a static.
908 
909  // This function returns 2*m_count unless that will
910  // result in an additional allocation of more than
911  // cap_size bytes. The cap_size concept was added in
912  // January 2010 because some calculations on enormous
913  // models were slightly underestimating the initial
914  // Reserve() size and then wasting gigabytes of memory.
915 
916  // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os
917  const size_t cap_size = 32*sizeof(void*)*1024*1024;
918  if (m_count*sizeof(T) <= cap_size || m_count < 8)
919  return ((m_count <= 2) ? 4 : 2*m_count);
920 
921  // Growing the array will increase the memory
922  // use by more than cap_size.
923  int delta_count = 8 + cap_size/sizeof(T);
924  if ( delta_count > m_count )
925  delta_count = m_count;
926  return (m_count + delta_count);
927 }
928 
929 /////////////////////////////////////////////////////////////////////////////////////
930 // Class ON_ObjectArray<>
931 /////////////////////////////////////////////////////////////////////////////////////
932 
933 template <class T>
935 {
936 }
938 template <class T>
940 {
941 }
943 template <class T>
945 {
946 }
948 template <class T>
950 {
951  if( this != &src)
952  {
954  }
955  return *this;
956 }
957 
958 #if defined(ON_HAS_RVALUEREF)
959 
960 // Clone constructor
961 template <class T>
963  : ON_ClassArray<T>(std::move(src))
964 {}
965 
966 // Clone assignment
967 template <class T>
969 {
970  if( this != &src )
971  {
972  this->Destroy();
973  m_a = src.m_a;
974  m_count = src.m_count;
975  m_capacity = src.m_capacity;
976  src.m_a = 0;
977  src.m_count = 0;
978  src.m_capacity = 0;
979  }
980  return *this;
981 }
982 
983 #endif
984 
985 template <class T>
987  : ON_ClassArray<T>(c)
988 {
989 }
990 
991 template <class T>
992 T* ON_ObjectArray<T>::Realloc(T* ptr,int capacity)
993 {
994  T* reptr = (T*)onrealloc(ptr,capacity*sizeof(T));
995  if ( ptr && reptr && reptr != ptr )
996  {
997  // The "this->" in this->m_count and this->m_a
998  // are needed for gcc 4 to compile.
999  int i;
1000  for ( i = 0; i < this->m_count; i++ )
1001  {
1002  reptr[i].MemoryRelocate();
1003  }
1004  }
1005  return reptr;
1006 }
1007 
1008 /////////////////////////////////////////////////////////////////////////////////////
1009 // Class ON_ClassArray<>
1010 /////////////////////////////////////////////////////////////////////////////////////
1011 
1012 
1013 // construction ////////////////////////////////////////////////////////
1014 
1015 template <class T>
1016 T* ON_ClassArray<T>::Realloc(T* ptr,int capacity)
1017 {
1018  return (T*)onrealloc(ptr,capacity*sizeof(T));
1020 
1021 template <class T>
1022 ON__UINT32 ON_ObjectArray<T>::DataCRC(ON__UINT32 current_remainder) const
1023 {
1024  // The "this->" in this->m_count and this->m_a
1025  // are needed for gcc 4 to compile.
1026  int i;
1027  for ( i = 0; i < this->m_count; i++ )
1028  {
1029  current_remainder = this->m_a[i].DataCRC(current_remainder);
1030  }
1031  return current_remainder;
1032 }
1033 
1034 template <class T>
1035 ON_ClassArray<T>::ON_ClassArray() ON_NOEXCEPT
1036  : m_a(nullptr)
1037  , m_count(0)
1039 {}
1040 
1041 template <class T>
1043  : m_a(nullptr)
1044  , m_count(0)
1046 {
1047  if ( c > 0 )
1048  SetCapacity( c );
1049 }
1050 
1051 // Copy constructor
1052 template <class T>
1054  : m_a(nullptr)
1055  , m_count(0)
1057 {
1058  *this = src; // operator= defined below
1059 }
1060 
1061 template <class T>
1063 {
1064  SetCapacity(0);
1066 
1067 template <class T>
1069 {
1070  int i;
1071  if( this != &src ) {
1072  if ( src.m_count <= 0 ) {
1073  m_count = 0;
1074  }
1075  else {
1076  if ( m_capacity < src.m_count ) {
1077  SetCapacity( src.m_count );
1078  }
1079  if ( m_a ) {
1080  m_count = src.m_count;
1081  for ( i = 0; i < m_count; i++ ) {
1082  m_a[i] = src.m_a[i];
1083  }
1084  }
1085  }
1086  }
1087  return *this;
1088 }
1089 
1090 #if defined(ON_HAS_RVALUEREF)
1091 
1092 // Clone constructor
1093 template <class T>
1095  : m_a(src.m_a)
1096  , m_count(src.m_count)
1097  , m_capacity(src.m_capacity)
1098 {
1099  src.m_a = 0;
1100  src.m_count = 0;
1101  src.m_capacity = 0;
1102 }
1103 
1104 // Clone assignment
1105 template <class T>
1107 {
1108  if( this != &src )
1109  {
1110  this->Destroy();
1111  m_a = src.m_a;
1112  m_count = src.m_count;
1113  m_capacity = src.m_capacity;
1114  src.m_a = 0;
1115  src.m_count = 0;
1116  src.m_capacity = 0;
1117  }
1118  return *this;
1119 }
1120 
1121 #endif
1122 
1123 // emergency destroy ///////////////////////////////////////////////////
1124 
1125 template <class T>
1127 {
1128  m_count = 0;
1130  m_a = 0;
1131 }
1132 
1133 // query ///////////////////////////////////////////////////////////////
1134 
1135 template <class T>
1136 int ON_ClassArray<T>::Count() const
1137 {
1138  return m_count;
1140 
1141 template <class T>
1142 unsigned int ON_ClassArray<T>::UnsignedCount() const
1143 {
1144  return ((unsigned int)m_count);
1146 
1147 template <class T>
1148 int ON_ClassArray<T>::Capacity() const
1149 {
1150  return m_capacity;
1152 
1153 template <class T>
1154 unsigned int ON_ClassArray<T>::SizeOfArray() const
1155 {
1156  return ((unsigned int)(m_capacity*sizeof(T)));
1158 
1159 template <class T>
1160 unsigned int ON_ClassArray<T>::SizeOfElement() const
1161 {
1162  return ((unsigned int)(sizeof(T)));
1164 
1165 template <class T>
1166 T& ON_ClassArray<T>::operator[]( int i )
1167 {
1168 #if defined(ON_DEBUG)
1169  if ( i < 0 || i > m_capacity )
1170  {
1171  ON_ERROR("ON_ClassArray[i]: i out of range.");
1172  }
1173 #endif
1174  return m_a[i];
1175 }
1176 
1177 
1178 template <class T>
1179 T& ON_ClassArray<T>::operator[]( ON__INT64 i )
1180 {
1181 #if defined(ON_DEBUG)
1182  if ( i < 0 || i > (ON__INT64)m_capacity )
1183  {
1184  ON_ERROR("ON_ClassArray[i]: i out of range.");
1185  }
1186 #endif
1187  return m_a[i];
1188 }
1189 
1190 template <class T>
1191 T& ON_ClassArray<T>::operator[]( unsigned int i )
1192 {
1193 #if defined(ON_DEBUG)
1194  if ( i > (unsigned int)m_capacity )
1195  {
1196  ON_ERROR("ON_ClassArray[i]: i out of range.");
1197  }
1198 #endif
1199  return m_a[i];
1200 }
1201 
1202 template <class T>
1203 T& ON_ClassArray<T>::operator[]( ON__UINT64 i )
1204 {
1205 #if defined(ON_DEBUG)
1206  if ( i > (ON__UINT64)m_capacity )
1207  {
1208  ON_ERROR("ON_ClassArray[i]: i out of range.");
1209  }
1210 #endif
1211  return m_a[i];
1212 }
1213 
1214 #if defined(ON_RUNTIME_APPLE)
1215 template <class T>
1216 T& ON_ClassArray<T>::operator[](size_t i )
1217 {
1218 #if defined(ON_DEBUG)
1219  if ( i > (size_t)m_capacity )
1220  {
1221  ON_ERROR("ON_ClassArray[i]: i out of range.");
1222  }
1223 #endif
1224  return m_a[i];
1225 }
1226 #endif
1227 
1228 template <class T>
1229 const T& ON_ClassArray<T>::operator[](int i) const
1230 {
1231 #if defined(ON_DEBUG)
1232  if ( i < 0 || i > m_capacity )
1233  {
1234  ON_ERROR("ON_ClassArray[i]: i out of range.");
1235  }
1236 #endif
1237  return m_a[i];
1238 }
1239 
1240 template <class T>
1241 const T& ON_ClassArray<T>::operator[](ON__INT64 i) const
1242 {
1243 #if defined(ON_DEBUG)
1244  if ( i < 0 || i > (ON__INT64)m_capacity )
1245  {
1246  ON_ERROR("ON_ClassArray[i]: i out of range.");
1247  }
1248 #endif
1249  return m_a[i];
1250 }
1251 
1252 template <class T>
1253 const T& ON_ClassArray<T>::operator[](unsigned int i) const
1254 {
1255 #if defined(ON_DEBUG)
1256  if ( i > (unsigned int)m_capacity )
1257  {
1258  ON_ERROR("ON_ClassArray[i]: i out of range.");
1259  }
1260 #endif
1261  return m_a[i];
1262 }
1263 
1264 template <class T>
1265 const T& ON_ClassArray<T>::operator[](ON__UINT64 i) const
1266 {
1267 #if defined(ON_DEBUG)
1268  if ( i > (ON__UINT64)m_capacity )
1269  {
1270  ON_ERROR("ON_ClassArray[i]: i out of range.");
1271  }
1272 #endif
1273  return m_a[i];
1274 }
1275 
1276 #if defined(ON_RUNTIME_APPLE)
1277 template <class T>
1278 const T& ON_ClassArray<T>::operator[](size_t i) const
1279 {
1280 #if defined(ON_DEBUG)
1281  if ( i > (size_t)m_capacity )
1282  {
1283  ON_ERROR("ON_ClassArray[i]: i out of range.");
1284  }
1285 #endif
1286  return m_a[i];
1287 }
1288 #endif
1289 
1290 template <class T>
1292 {
1293  return (m_count > 0) ? m_a : 0;
1295 
1296 template <class T>
1297 ON_ClassArray<T>::operator const T*() const
1298 {
1299  return (m_count > 0) ? m_a : 0;
1301 
1302 template <class T>
1304 {
1305  return m_a;
1307 
1308 template <class T>
1309 const T* ON_ClassArray<T>::Array() const
1310 {
1311  return m_a;
1313 
1314 template <class T>
1316 {
1317  T* p = m_a;
1318  m_a = 0;
1319  m_count = 0;
1320  m_capacity = 0;
1321  return p;
1322 }
1323 
1324 template <class T>
1325 void ON_ClassArray<T>::SetArray(T* p)
1326 {
1327  if ( m_a && m_a != p )
1329  m_a = p;
1330 }
1331 
1332 template <class T>
1333 void ON_ClassArray<T>::SetArray(T* p, int count, int capacity)
1334 {
1335  if ( m_a && m_a != p )
1337  m_a = p;
1338  m_count = count;
1339  m_capacity = capacity;
1340 }
1341 
1342 template <class T>
1344 {
1345  return (m_count > 0) ? m_a : 0;
1347 
1348 template <class T>
1349 const T* ON_ClassArray<T>::First() const
1350 {
1351  return (m_count > 0) ? m_a : 0;
1353 
1354 template <class T>
1355 T* ON_ClassArray<T>::At( int i )
1356 {
1357  return (i >= 0 && i < m_count) ? m_a+i : 0;
1359 
1360 template <class T>
1361 T* ON_ClassArray<T>::At( unsigned int i )
1362 {
1363  return (i < (unsigned int)m_count) ? m_a+i : 0;
1365 
1366 template <class T>
1367 const T* ON_ClassArray<T>::At( int i) const
1368 {
1369  return (i >= 0 && i < m_count) ? m_a+i : 0;
1371 
1372 template <class T>
1373 const T* ON_ClassArray<T>::At( unsigned int i) const
1374 {
1375  return (i < (unsigned int)m_count) ? m_a+i : 0;
1377 
1378 
1379 template <class T>
1380 T* ON_ClassArray<T>::At( ON__INT64 i )
1381 {
1382  return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0;
1384 
1385 template <class T>
1386 T* ON_ClassArray<T>::At( ON__UINT64 i )
1387 {
1388  return (i < (ON__UINT64)m_count) ? m_a+i : 0;
1390 
1391 template <class T>
1392 const T* ON_ClassArray<T>::At( ON__INT64 i) const
1393 {
1394  return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0;
1396 
1397 template <class T>
1398 const T* ON_ClassArray<T>::At( ON__UINT64 i) const
1399 {
1400  return (i < (ON__UINT64)m_count) ? m_a+i : 0;
1402 
1403 
1404 template <class T>
1406 {
1407  return (m_count > 0) ? m_a+(m_count-1) : 0;
1409 
1410 template <class T>
1411 const T* ON_ClassArray<T>::Last() const
1412 {
1413  return (m_count > 0) ? m_a+(m_count-1) : 0;
1415 
1416 // array operations ////////////////////////////////////////////////////
1417 
1418 template <class T>
1419 void ON_ClassArray<T>::Move( int dest_i, int src_i, int ele_cnt )
1420 {
1421  // private function for moving blocks of array memory
1422  // caller is responsible for updating m_count and managing
1423  // destruction/creation.
1424  if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i ||
1425  src_i + ele_cnt > m_count || dest_i > m_count )
1426  return;
1427 
1428  int capacity = dest_i + ele_cnt;
1429  if ( capacity > m_capacity ) {
1430  if ( capacity < 2*m_capacity )
1431  capacity = 2*m_capacity;
1432  SetCapacity( capacity );
1433  }
1434 
1435  // This call to memmove is ok, even when T is a class with a vtable
1436  // because the it doesn't change the vtable for the class.
1437  // Classes that have back pointers, like ON_UserData, are
1438  // handled elsewhere and cannot be in ON_ClassArray<>s.
1439  memmove( (void*)(&m_a[dest_i]), (const void*)(&m_a[src_i]), ele_cnt*sizeof(T) );
1440 }
1441 
1442 template <class T>
1444 {
1445  // use placement ( new(size_t,void*) ) to construct
1446  // T in supplied memory
1447  new(p) T;
1448 }
1449 
1450 template <class T>
1452 {
1453  x.~T();
1455 
1456 template <class T>
1458 {
1459  if ( m_count == m_capacity )
1460  {
1461  int newcapacity = NewCapacity();
1462  Reserve( newcapacity );
1463  }
1464  else
1465  {
1466  // First destroy what's there ..
1468  // and then get a properly initialized element
1469  ConstructDefaultElement(&m_a[m_count]);
1470  }
1471  return m_a[m_count++];
1472 }
1473 
1474 template <class T>
1475 void ON_ClassArray<T>::Append( const T& x )
1476 {
1477  if ( m_count == m_capacity )
1478  {
1479  const int newcapacity = NewCapacity();
1480  if (m_a)
1481  {
1482  const int s = (int)(&x - m_a); // (int) cast is for 64 bit pointers
1483  if ( s >= 0 && s < m_capacity )
1484  {
1485  // 26 Sep 2005 Dale Lear
1486  // User passed in an element of the m_a[]
1487  // that will get reallocated by the call
1488  // to Reserve(newcapacity).
1489  T temp; // ON_*Array<> templates do not require robust copy constructor.
1490  temp = x; // ON_*Array<> templates require a robust operator=.
1491  Reserve( newcapacity );
1492  m_a[m_count++] = temp;
1493  return;
1494  }
1495  }
1496  Reserve(newcapacity);
1497  }
1498  m_a[m_count++] = x;
1499 }
1500 
1501 template <class T>
1502 void ON_ClassArray<T>::Append( int count, const T* p )
1503 {
1504  int i;
1505  if ( count > 0 && p )
1506  {
1507  if ( count + m_count > m_capacity )
1508  {
1509  int newcapacity = NewCapacity();
1510  if ( newcapacity < count + m_count )
1511  newcapacity = count + m_count;
1512  Reserve( newcapacity );
1513  }
1514  for ( i = 0; i < count; i++ ) {
1515  m_a[m_count++] = p[i];
1516  }
1517  }
1518 }
1519 
1520 // Insert called with a reference uses operator =
1521 template <class T>
1522 void ON_ClassArray<T>::Insert( int i, const T& x )
1523 {
1524  if( i >= 0 && i <= m_count )
1525  {
1526  if ( m_count == m_capacity )
1527  {
1528  int newcapacity = NewCapacity();
1529  Reserve( newcapacity );
1530  }
1532  m_count++;
1533  if ( i < m_count-1 ) {
1534  Move( i+1, i, m_count-1-i );
1535  // This call to memset is ok even when T has a vtable
1536  // because in-place construction is used later.
1537  memset( (void*)(&m_a[i]), 0, sizeof(T) );
1539  }
1540  else {
1541  ConstructDefaultElement( &m_a[m_count-1] );
1542  }
1543  m_a[i] = x; // uses T::operator=() to copy x to array
1544  }
1545 }
1546 
1547 template <class T>
1549 {
1550  Remove(m_count-1);
1551 }
1552 
1553 template <class T>
1554 void ON_ClassArray<T>::Remove( int i )
1555 {
1556  if ( i >= 0 && i < m_count )
1557  {
1558  DestroyElement( m_a[i] );
1559  // This call to memset is ok even when T has a vtable
1560  // because in-place construction is used later.
1561  memset( (void*)(&m_a[i]), 0, sizeof(T) );
1562  Move( i, i+1, m_count-1-i );
1563  // This call to memset is ok even when T has a vtable
1564  // because in-place construction is used later.
1565  memset( (void*)(&m_a[m_count-1]), 0, sizeof(T) );
1567  m_count--;
1568  }
1569 }
1570 
1571 template <class T>
1573 {
1574  int i;
1575  for ( i = m_count-1; i >= 0; i-- ) {
1576  DestroyElement( m_a[i] );
1577  // This call to memset is ok even when T has a vtable
1578  // because in-place construction is used later.
1579  memset( (void*)(&m_a[i]), 0, sizeof(T) );
1581  }
1582  m_count = 0;
1583 }
1584 
1585 template <class T>
1587 {
1588  // NOTE:
1589  // If anything in "T" depends on the value of this's address,
1590  // then don't call Reverse().
1591  char t[sizeof(T)];
1592  int i = 0;
1593  int j = m_count-1;
1594  for ( /*empty*/; i < j; i++, j-- ) {
1595  memcpy( (void*)(t), (void*)(&m_a[i]), sizeof(T) );
1596  memcpy( (void*)(&m_a[i]), (void*)(&m_a[j]), sizeof(T) );
1597  memcpy( (void*)(&m_a[j]), (void*)(t), sizeof(T) );
1598  }
1599 }
1600 
1601 template <class T>
1602 void ON_ClassArray<T>::Swap( int i, int j )
1603 {
1604  if ( i != j && i >= 0 && j >= 0 && i < m_count && j < m_count ) {
1605  char t[sizeof(T)];
1606  memcpy( (void*)(t), (void*)(&m_a[i]), sizeof(T) );
1607  memcpy( (void*)(&m_a[i]), (void*)(&m_a[j]), sizeof(T) );
1608  memcpy( (void*)(&m_a[j]), (void*)(t), sizeof(T) );
1609  }
1610 }
1611 
1612 template <class T>
1613 int ON_ClassArray<T>::Search( const T* key, int (*compar)(const T*,const T*) ) const
1614 {
1615  for ( int i = 0; i < m_count; i++ )
1616  {
1617  if (!compar(key,m_a+i))
1618  return i;
1619  }
1620  return -1;
1621 }
1622 
1623 template <class T>
1624 int ON_ClassArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const
1625 {
1626  const T* found = (key&&m_a&&m_count>0) ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ) : nullptr;
1627  return (nullptr != found && found >= m_a) ? ((int)(found - m_a)) : -1;
1629 
1630 template <class T>
1631 int ON_ClassArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*), int count ) const
1632 {
1633  if ( count > m_count )
1634  count = m_count;
1635  if ( count <= 0 )
1636  return -1;
1637  const T* found = (key&&m_a&&m_count>0) ? (const T*)bsearch( key, m_a, count, sizeof(T), (int(*)(const void*,const void*))compar ) : nullptr;
1638  return (nullptr != found && found >= m_a) ? ((int)(found - m_a)) : -1;
1639 }
1640 
1641 template <class T>
1642 bool ON_ClassArray<T>::HeapSort( int (*compar)(const T*,const T*) )
1643 {
1644  bool rc = false;
1645  if ( m_a && m_count > 0 && compar )
1646  {
1647  if ( m_count > 1 )
1648  ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1649  rc = true;
1650  }
1651  return rc;
1652 }
1653 
1654 template <class T>
1655 bool ON_ClassArray<T>::QuickSort( int (*compar)(const T*,const T*) )
1656 {
1657  bool rc = false;
1658  if ( m_a && m_count > 0 && compar )
1659  {
1660  if ( m_count > 1 )
1661  ON_qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1662  rc = true;
1663  }
1664  return rc;
1665 }
1666 
1667 
1668 
1669 template <class T>
1670 bool ON_ObjectArray<T>::HeapSort( int (*compar)(const T*,const T*) )
1671 {
1672  bool rc = false;
1673  // The "this->" in this->m_count and this->m_a
1674  // are needed for gcc 4 to compile.
1675  if ( this->m_a && this->m_count > 0 && compar )
1676  {
1677  if ( this->m_count > 1 )
1678  {
1679  ON_hsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1680 
1681  // The MemoryRelocate step is required to synch userdata back pointers
1682  // so the user data destructor will work correctly.
1683  int i;
1684  for ( i = 0; i < this->m_count; i++ )
1685  {
1686  this->m_a[i].MemoryRelocate();
1687  }
1688  }
1689  rc = true;
1690  }
1691  return rc;
1692 }
1693 
1694 template <class T>
1695 bool ON_ObjectArray<T>::QuickSort( int (*compar)(const T*,const T*) )
1696 {
1697  bool rc = false;
1698  // The "this->" in this->m_count and this->m_a
1699  // are needed for gcc 4 to compile.
1700  if ( this->m_a && this->m_count > 0 && compar )
1701  {
1702  if ( this->m_count > 1 )
1703  {
1704  ON_qsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1705 
1706  // The MemoryRelocate step is required to synch userdata back pointers
1707  // so the user data destructor will work correctly.
1708  int i;
1709  for ( i = 0; i < this->m_count; i++ )
1710  {
1711  this->m_a[i].MemoryRelocate();
1712  }
1713  }
1714  rc = true;
1715  }
1716  return rc;
1717 }
1718 
1719 
1720 template <class T>
1721 bool ON_ClassArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const
1722 {
1723  bool rc = false;
1724  if ( m_a && m_count > 0 && compar && index )
1725  {
1726  if ( m_count > 1 )
1727  ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1728  else if ( m_count == 1 )
1729  index[0] = 0;
1730  rc = true;
1731  }
1732  return rc;
1733 }
1734 
1735 template <class T>
1736 bool ON_ClassArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const
1737 {
1738  bool rc = false;
1739  if ( m_a && m_count > 0 && compar && index )
1740  {
1741  if ( m_count > 1 )
1742  ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p );
1743  else if ( m_count == 1 )
1744  index[0] = 0;
1745  rc = true;
1746  }
1747  return rc;
1748 }
1749 
1750 template <class T>
1751 bool ON_ClassArray<T>::Permute( const int* index )
1752 {
1753  bool rc = false;
1754  if ( m_a && m_count > 0 && index )
1755  {
1756  int i;
1757  T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0]));
1758  memcpy( (void*)(buffer), (void*)(m_a), m_count*sizeof(T) );
1759  for (i = 0; i < m_count; i++ )
1760  memcpy( (void*)(m_a+i), (void*)(buffer+index[i]), sizeof(T) ); // must use memcopy and not operator=
1761  onfree(buffer);
1762  rc = true;
1763  }
1764  return rc;
1765 }
1766 
1767 template <class T>
1769 {
1770  int i;
1771  if ( m_a && m_capacity > 0 ) {
1772  for ( i = m_capacity-1; i >= 0; i-- ) {
1773  DestroyElement(m_a[i]);
1774  // This call to memset is ok even when T has a vtable
1775  // because in-place construction is used later.
1776  memset( (void*)(&m_a[i]), 0, sizeof(T) );
1778  }
1779  }
1780 }
1781 
1782 // memory managment ////////////////////////////////////////////////////
1783 
1784 template <class T>
1785 T* ON_ClassArray<T>::Reserve( size_t newcap )
1786 {
1787  if( (size_t)m_capacity < newcap )
1788  SetCapacity( newcap );
1789  return m_a;
1790 }
1791 
1792 template <class T>
1794 {
1795  SetCapacity( m_count );
1796 }
1798 template <class T>
1800 {
1801  SetCapacity( 0 );
1802 }
1804 // low level memory managment //////////////////////////////////////////
1805 
1806 template <class T>
1807 void ON_ClassArray<T>::SetCount( int count )
1808 {
1809  if ( count >= 0 && count <= m_capacity )
1810  m_count = count;
1812 
1813 template <class T>
1814 T* ON_ClassArray<T>::SetCapacity( size_t new_capacity )
1815 {
1816  if (0 == m_capacity)
1817  {
1818  // Allow "expert" users of ON_SimpleArray<>.SetArray(*,*,0) to clean up after themselves
1819  // and deals with the case when the forget to clean up after themselves.
1820  m_a = nullptr;
1821  m_count = 0;
1822  }
1823  // uses "placement" for class construction/destruction
1824  int i;
1825  int capacity = (new_capacity > 0 && new_capacity < ON_UNSET_UINT_INDEX)
1826  ? (int)new_capacity
1827  : 0;
1828 
1829  if ( capacity <= 0 ) {
1830  if ( m_a ) {
1831  for ( i = m_capacity-1; i >= 0; i-- ) {
1832  DestroyElement(m_a[i]);
1833  }
1834  Realloc(m_a,0);
1835  m_a = 0;
1836  }
1837  m_count = 0;
1838  m_capacity = 0;
1839  }
1840  else if ( m_capacity < capacity ) {
1841  // growing
1842  m_a = Realloc( m_a, capacity );
1843  // initialize new elements with default constructor
1844  if ( 0 != m_a )
1845  {
1846  // even when m_a is an array of classes with vtable pointers,
1847  // this call to memset(..., 0, ...) is what I want to do
1848  // because in-place construction will be used when needed
1849  // on this memory.
1850  memset( (void*)(m_a + m_capacity), 0, (capacity-m_capacity)*sizeof(T) );
1851  for ( i = m_capacity; i < capacity; i++ ) {
1853  }
1854  m_capacity = capacity;
1855  }
1856  else
1857  {
1858  // memory allocation failed
1859  m_capacity = 0;
1860  m_count = 0;
1861  }
1862  }
1863  else if ( m_capacity > capacity ) {
1864  // shrinking
1865  for ( i = m_capacity-1; i >= capacity; i-- ) {
1866  DestroyElement(m_a[i]);
1867  }
1868  if ( m_count > capacity )
1869  m_count = capacity;
1870  m_capacity = capacity;
1871  m_a = Realloc( m_a, capacity );
1872  if ( 0 == m_a )
1873  {
1874  // memory allocation failed
1875  m_capacity = 0;
1876  m_count = 0;
1877  }
1878  }
1879  return m_a;
1880 }
1881 
1882 /////////////////////////////////////////////////////////////////////////////////////
1883 /////////////////////////////////////////////////////////////////////////////////////
1884 /////////////////////////////////////////////////////////////////////////////////////
1885 
1886 template< class T>
1887 int ON_CompareIncreasing( const T* a, const T* b)
1888 {
1889  if( *a < *b )
1890  return -1;
1891  if( *b < *a )
1892  return 1;
1893  return 0;
1894 }
1895 
1896 template< class T>
1897 int ON_CompareDecreasing( const T* a, const T* b)
1898 {
1899  if( *b < *a )
1900  return -1;
1901  if( *a < *b )
1902  return 1;
1903  return 0;
1904 }
1905 
1906 #pragma ON_PRAGMA_WARNING_POP
1907 
1908 #endif
void Empty()
Definition: opennurbs_array_defs.h:558
void EmergencyDestroy(void)
emergency bailout ///////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1129
int Capacity() const
Definition: opennurbs_array_defs.h:173
virtual ~ON_SimpleArray()
Definition: opennurbs_array_defs.h:90
T & operator[](int)
Definition: opennurbs_array_defs.h:1169
ON_SimpleArray() ON_NOEXCEPT
construction ////////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:63
T * At(int)
At(index) returns nullptr if index < 0 or index >= count.
Definition: opennurbs_array_defs.h:389
void Zero()
Definition: opennurbs_array_defs.h:778
void Append(const T &)
Definition: opennurbs_array_defs.h:1478
void Empty()
Definition: opennurbs_array_defs.h:1575
int Count() const
query ///////////////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1139
T * Last()
Definition: opennurbs_array_defs.h:1408
T * KeepArray()
Definition: opennurbs_array_defs.h:1318
void Move(int, int, int)
implimentation //////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:451
int NewCapacity() const
Definition: opennurbs_array_defs.h:900
T * KeepArray()
Expert user tool to take charge of the memory used by the dyanmic array.
Definition: opennurbs_array_defs.h:349
T * Last()
Definition: opennurbs_array_defs.h:437
int m_count
Definition: opennurbs_array.h:360
virtual ~ON_ClassArray()
Definition: opennurbs_array_defs.h:1065
unsigned int SizeOfArray() const
Definition: opennurbs_array_defs.h:1157
ON_ObjectArray()
Class ON_ObjectArray<>
Definition: opennurbs_array_defs.h:937
void SetArray(T *)
Do not use this version of SetArray(). Use the one that takes a pointer, count and capacity...
Definition: opennurbs_array_defs.h:359
ON_SimpleArray< T > & operator=(const ON_SimpleArray< T > &)
Definition: opennurbs_array_defs.h:96
Definition: opennurbs_array.h:36
void Swap(int, int)
Definition: opennurbs_array_defs.h:583
bool Permute(const int *)
Definition: opennurbs_array_defs.h:1755
int Capacity() const
Definition: opennurbs_array_defs.h:1151
void Shrink()
Definition: opennurbs_array_defs.h:804
T * SetCapacity(size_t)
Definition: opennurbs_array_defs.h:825
virtual bool QuickSort(int(*)(const T *, const T *))
Sorts the array using the heap sort algorithm.
Definition: opennurbs_array_defs.h:1659
int m_capacity
Definition: opennurbs_array.h:708
ON_Object array is used to store lists of classes that are derived from ON_Object. It differs from ON_ClassArray in that the virtual ON_Object::MemoryRelocate function is called when growing the dynamic array requires changing the location of the memory buffer used to store the elements in the array.
Definition: opennurbs_array.h:725
int BinarySearch(const T *, int(*)(const T *, const T *)) const
Definition: opennurbs_array_defs.h:614
void ConstructDefaultElement(T *)
Definition: opennurbs_array_defs.h:1446
T * Reserve(size_t)
memory managment /////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1789
int BinarySearch(const T *, int(*)(const T *, const T *)) const
Definition: opennurbs_array_defs.h:1628
int Search(const T &) const
Definition: opennurbs_array_defs.h:593
virtual T * Realloc(T *, int)
low level memory managment //////////////////////////////////////////
Definition: opennurbs_array_defs.h:57
void Move(int, int, int)
implimentation //////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1422
bool Sort(ON::sort_algorithm sort_algorithm, int *, int(*)(const T *, const T *)) const
Sort() fills in the index[] array so that array[index[i]] <= array[index[i+1]]. The array is not modi...
Definition: opennurbs_array_defs.h:1725
T * Realloc(T *, int)
low level memory managment ///////////////////////////////////////
Definition: opennurbs_array_defs.h:995
T * m_a
Definition: opennurbs_array.h:359
virtual bool HeapSort(int(*)(const T *, const T *))
Definition: opennurbs_array_defs.h:1646
void Insert(int, const T &)
Insert called with a reference uses operator =.
Definition: opennurbs_array_defs.h:1525
void MemSet(unsigned char)
Definition: opennurbs_array_defs.h:786
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const
Definition: opennurbs_array_defs.h:1025
bool QuickSort(int(*)(const T *, const T *))
Definition: opennurbs_array_defs.h:722
void Insert(int, const T &)
Definition: opennurbs_array_defs.h:526
void SetCount(int)
low level memory managment //////////////////////////////////////////
Definition: opennurbs_array_defs.h:1811
int m_capacity
Definition: opennurbs_array.h:361
bool QuickSort(int(*)(const T *, const T *))
Sorts the array using the heap sort algorithm.
Definition: opennurbs_array_defs.h:1699
bool HeapSort(int(*)(const T *, const T *))
Definition: opennurbs_array_defs.h:1674
T * First()
Definition: opennurbs_array_defs.h:1346
ON_ClassArray< T > & operator=(const ON_ClassArray< T > &)
Assignment operator.
Definition: opennurbs_array_defs.h:1071
void Remove()
Definition: opennurbs_array_defs.h:1551
bool Permute(const int *)
Definition: opennurbs_array_defs.h:762
unsigned int UnsignedCount() const
Definition: opennurbs_array_defs.h:167
void Shrink()
Definition: opennurbs_array_defs.h:1797
void Append(const T &)
Definition: opennurbs_array_defs.h:482
T * Reserve(size_t)
memory managment ////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:796
bool Sort(ON::sort_algorithm sort_algorithm, int *, int(*)(const T *, const T *)) const
Sort() fills in the index[] array so that array[index[i]] <= array[index[i+1]]. The array is not modi...
Definition: opennurbs_array_defs.h:734
int m_count
Definition: opennurbs_array.h:707
void Swap(int, int)
Definition: opennurbs_array_defs.h:1606
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const
Definition: opennurbs_array_defs.h:192
virtual T * Realloc(T *, int)
low level memory managment ///////////////////////////////////////
Definition: opennurbs_array_defs.h:1019
T * m_a
Definition: opennurbs_array.h:706
void Zero()
Definition: opennurbs_array_defs.h:1772
unsigned int SizeOfElement() const
Definition: opennurbs_array_defs.h:185
T & operator[](int)
Definition: opennurbs_array_defs.h:198
T & AppendNew()
array operations ////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1460
void Destroy()
Definition: opennurbs_array_defs.h:1803
void SetArray(T *)
Do not use this version of SetArray(). Use the one that takes a pointer, count and capacity: SetArray...
Definition: opennurbs_array_defs.h:1328
~ON_ObjectArray()
Definition: opennurbs_array_defs.h:942
void Reverse()
Definition: opennurbs_array_defs.h:566
unsigned int SizeOfArray() const
Definition: opennurbs_array_defs.h:179
unsigned int SizeOfElement() const
Definition: opennurbs_array_defs.h:1163
ON_ObjectArray< T > & operator=(const ON_ObjectArray< T > &)
Definition: opennurbs_array_defs.h:952
Definition: opennurbs_array.h:409
void SetCount(int)
low level memory managment //////////////////////////////////////////
Definition: opennurbs_array_defs.h:818
void Reverse()
Definition: opennurbs_array_defs.h:1589
ON_ClassArray() ON_NOEXCEPT
construction ////////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:1038
T * SetCapacity(size_t)
Definition: opennurbs_array_defs.h:1818
T * First()
Definition: opennurbs_array_defs.h:377
void EmergencyDestroy(void)
emergency bailout ///////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:151
T * At(int)
At(index) returns nullptr if index < 0 or index >= count.
Definition: opennurbs_array_defs.h:1358
T * Array()
Definition: opennurbs_array_defs.h:1306
int NewCapacity() const
Definition: opennurbs_array_defs.h:867
bool HeapSort(int(*)(const T *, const T *))
Definition: opennurbs_array_defs.h:710
void DestroyElement(T &)
Definition: opennurbs_array_defs.h:1454
int Count() const
query ///////////////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:161
T * Array()
Definition: opennurbs_array_defs.h:337
int Search(const T *, int(*)(const T *, const T *)) const
Definition: opennurbs_array_defs.h:1617
void Remove()
Definition: opennurbs_array_defs.h:542
void Destroy()
Definition: opennurbs_array_defs.h:810
T & AppendNew()
array operations ////////////////////////////////////////////////////
Definition: opennurbs_array_defs.h:470
unsigned int UnsignedCount() const
Definition: opennurbs_array_defs.h:1145