QCAD
Open Source 2D CAD
Loading...
Searching...
No Matches
opennurbs_array_defs.h
Go to the documentation of this file.
1/* $NoKeywords: $ */
2/*
3//
4// Copyright (c) 1993-2007 Robert McNeel & Associates. All rights reserved.
5// Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
6//
7// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
8// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
9// MERCHANTABILITY ARE HEREBY DISCLAIMED.
10//
11// For complete openNURBS copyright information see <http://www.opennurbs.org>.
12//
14*/
15
16#if !defined(ON_ARRAY_DEFS_INC_)
17#define ON_ARRAY_DEFS_INC_
18
19#if defined(ON_COMPILER_MSC)
20
21// When this file is parsed with /W4 warnings, two bogus warnings
22// are generated.
23#pragma warning(push)
24
25// The ON_ClassArray<T>::DestroyElement template function generates a
26// C4100: 'x' : unreferenced formal parameter
27// warning.
28// This appears to be caused by a bug in the compiler warning code
29// or the way templates are expanded. This pragma is needed squelch the
30// bogus warning.
31#pragma warning(disable:4100)
32
33// The ON_CompareIncreasing and ON_CompareDecreasing templates generate a
34// C4211: nonstandard extension used : redefined extern to static
35// warning. Microsoft's compiler appears to have a little trouble
36// when static functions are declared before they are defined in a
37// single .cpp file. This pragma is needed squelch the bogus warning.
38#pragma warning(disable:4211)
39#endif
40
41// qcad: compile fix for gcc 4.7:
42#include "opennurbs_math.h"
43// qcad: end
44
45// The main reason the definitions of the functions for the
46// ON_SimpleArray and ON_ClassArray templates are in this separate
47// file is so that the Microsoft developer studio autocomplete
48// functions will work on these classes.
49//
50// This file is included by opennurbs_array.h in the appropriate
51// spot. If you need the definitions in the file, then you
52// should include opennurbs_array.h and let it take care of
53// including this file.
54
56// Class ON_SimpleArray<>
58
59// construction ////////////////////////////////////////////////////////
60
61template <class T>
62T* ON_SimpleArray<T>::Realloc(T* ptr,int capacity)
64 return (T*)onrealloc(ptr,capacity*sizeof(T));
65}
67template <class T>
69 : m_a(0),
70 m_count(0),
71 m_capacity(0)
72{}
73
74template <class T>
76 : m_a(0),
77 m_count(0),
78 m_capacity(0)
79{
80 if ( c > 0 )
81 SetCapacity( c );
83
84// Copy constructor
85template <class T>
87 : m_a(0),
88 m_count(0),
89 m_capacity(0)
91 *this = src; // operator= defined below
92}
94template <class T>
96{
97 SetCapacity(0);
98}
100template <class T>
102{
103 if( &src != this ) {
104 if ( src.m_count <= 0 ) {
105 m_count = 0;
106 }
107 else {
108 if ( m_capacity < src.m_count ) {
109 SetCapacity( src.m_count );
110 }
111 if ( m_a ) {
112 m_count = src.m_count;
113 memcpy( m_a, src.m_a, m_count*sizeof(T) );
115 }
116 }
117 return *this;
118}
120// emergency destroy ///////////////////////////////////////////////////
121
122template <class T>
124{
125 m_count = 0;
126 m_capacity = 0;
127 m_a = 0;
129
130// query ///////////////////////////////////////////////////////////////
131
132template <class T>
134{
135 return m_count;
136}
137
138template <class T>
140{
141 return m_capacity;
142}
143
144template <class T>
146{
147 return ((unsigned int)(m_capacity*sizeof(T)));
148}
149
150template <class T>
152{
153 return ON_CRC32(current_remainder,m_count*sizeof(m_a[0]),m_a);
155
156template <class T>
158{
159#if defined(ON_DEBUG)
160 ON_ASSERT( i >=0 && i < m_capacity);
161#endif
162 return m_a[i];
163}
165template <class T>
167{
168#if defined(ON_DEBUG)
169 ON_ASSERT( i >=0 && i < m_capacity);
170#endif
171 return m_a[i];
172}
174template <class T>
176{
177 return (m_count > 0) ? m_a : 0;
178}
180template <class T>
182{
183 return (m_count > 0) ? m_a : 0;
184}
185
186template <class T>
188{
189 return m_a;
190}
191
192template <class T>
194{
195 return m_a;
196}
197
198template <class T>
200{
201 T* p = m_a;
202 m_count = 0;
203 m_capacity = 0;
204 m_a = NULL;
205 return p;
206}
207
208template <class T>
210{
211 m_a = p;
212}
214
215template <class T>
217{
218 return (m_count > 0) ? m_a : 0;
219}
220
221template <class T>
223{
224 return (m_count > 0) ? m_a : 0;
225}
227template <class T>
229{
230 return (i >= 0 && i < m_count) ? m_a+i : 0;
231}
232
233template <class T>
234const T* ON_SimpleArray<T>::At( int i) const
235{
236 return (i >= 0 && i < m_count) ? m_a+i : 0;
237}
238
239template <class T>
241{
242 return (m_count > 0) ? m_a+(m_count-1) : 0;
243}
244
245template <class T>
247{
248 return (m_count > 0) ? m_a+(m_count-1) : 0;
249}
251// array operations ////////////////////////////////////////////////////
253template <class T>
254void ON_SimpleArray<T>::Move( int dest_i, int src_i, int ele_cnt )
255{
256 // private function for moving blocks of array memory
257 // caller is responsible for updating m_count.
258 if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i ||
259 src_i + ele_cnt > m_count || dest_i > m_count )
260 return;
261
262 int capacity = dest_i + ele_cnt;
263 if ( capacity > m_capacity ) {
264 if ( capacity < 2*m_capacity )
265 capacity = 2*m_capacity;
266 SetCapacity( capacity );
267 }
268
269 memmove( &m_a[dest_i], &m_a[src_i], ele_cnt*sizeof(T) );
270}
271
272template <class T>
274{
275 if ( m_count == m_capacity )
276 {
277 int new_capacity = NewCapacity();
278 Reserve( new_capacity );
279 }
280 memset( &m_a[m_count], 0, sizeof(T) );
281 return m_a[m_count++];
282}
283
284template <class T>
285void ON_SimpleArray<T>::Append( const T& x )
286{
287 if ( m_count == m_capacity )
289 const int newcapacity = NewCapacity();
290 if (m_a)
291 {
292 const int s = (int)(&x - m_a); // (int) cast is for 64 bit pointers
293 if ( s >= 0 && s < m_capacity )
294 {
295 // 26 Sep 2005 Dale Lear
296 // User passed in an element of the m_a[]
297 // that will get reallocated by the call
298 // to Reserve(newcapacity).
299 T temp; // ON_*Array<> templates do not require robust copy constructor.
300 temp = x; // ON_*Array<> templates require a robust operator=.
301 Reserve( newcapacity );
302 m_a[m_count++] = temp;
303 return;
304 }
305 }
306 Reserve(newcapacity);
307 }
308 m_a[m_count++] = x;
309}
310
311template <class T>
312void ON_SimpleArray<T>::Append( int count, const T* p )
313{
314 if ( count > 0 && p )
315 {
316 if ( count + m_count > m_capacity )
317 {
318 int newcapacity = NewCapacity();
319 if ( newcapacity < count + m_count )
320 newcapacity = count + m_count;
321 Reserve( newcapacity );
322 }
323 memcpy( m_a + m_count, p, count*sizeof(T) );
324 m_count += count;
325 }
326}
327
328template <class T>
329void ON_SimpleArray<T>::Insert( int i, const T& x )
330{
331 if( i >= 0 && i <= m_count )
332 {
333 if ( m_count == m_capacity )
334 {
335 int newcapacity = NewCapacity();
336 Reserve( newcapacity );
337 }
338 m_count++;
339 Move( i+1, i, m_count-1-i );
340 m_a[i] = x;
341 }
342}
343
344template <class T>
346{
347 Remove(m_count-1);
348}
349
350template <class T>
352{
353 if ( i >= 0 && i < m_count ) {
354 Move( i, i+1, m_count-1-i );
355 m_count--;
356 memset( &m_a[m_count], 0, sizeof(T) );
357 }
358}
359
360template <class T>
362{
363 if ( m_a )
364 memset( m_a, 0, m_capacity*sizeof(T) );
365 m_count = 0;
366}
367
368template <class T>
370{
371 // NOTE:
372 // If anything in "T" depends on the value of this's address,
373 // then don't call Reverse().
374 T t;
375 int i = 0;
376 int j = m_count-1;
377 for ( /*empty*/; i < j; i++, j-- ) {
378 t = m_a[i];
379 m_a[i] = m_a[j];
380 m_a[j] = t;
381 }
382}
383
384template <class T>
385void ON_SimpleArray<T>::Swap( int i, int j )
386{
387 if ( i != j ) {
388 const T t(m_a[i]);
389 m_a[i] = m_a[j];
390 m_a[j] = t;
391 }
392}
393
394template <class T>
395int ON_SimpleArray<T>::Search( const T& key ) const
396{
397 const T* p = &key;
398 for ( int i = 0; i < m_count; i++ ) {
399 if (!memcmp(p,m_a+i,sizeof(T)))
400 return i;
401 }
402 return -1;
403}
404
405template <class T>
406int ON_SimpleArray<T>::Search( const T* key, int (*compar)(const T*,const T*) ) const
407{
408 for ( int i = 0; i < m_count; i++ ) {
409 if (!compar(key,m_a+i))
410 return i;
411 }
412 return -1;
413}
414
415template <class T>
416int ON_SimpleArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const
417{
418 const T* found = (key&&m_a&&m_count>0)
419 ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar )
420 : 0;
421
422 // This worked on a wide range of 32 bit compilers.
423
424 int rc;
425 if ( 0 != found )
426 {
427 // Convert "found" pointer to array index.
428
429#if defined(ON_COMPILER_MSC1300)
430 rc = ((int)(found - m_a));
431#elif 8 == ON_SIZEOF_POINTER
432 // In an ideal world, return ((int)(found - m_a)) would work everywhere.
433 // In practice, this should work any 64 bit compiler and we can hope
434 // the optimzer generates efficient code.
435 const ON__UINT64 fptr = (ON__UINT64)found;
436 const ON__UINT64 aptr = (ON__UINT64)m_a;
437 const ON__UINT64 sz = (ON__UINT64)sizeof(T);
438 const ON__UINT64 i = (fptr - aptr)/sz;
439 rc = (int)i;
440#else
441 // In an ideal world, return ((int)(found - m_a)) would work everywhere.
442 // In practice, this should work any 32 bit compiler and we can hope
443 // the optimzer generates efficient code.
444 const ON__UINT32 fptr = (ON__UINT32)found;
445 const ON__UINT32 aptr = (ON__UINT32)m_a;
446 const ON__UINT32 sz = (ON__UINT32)sizeof(T);
447 const ON__UINT32 i = (fptr - aptr)/sz;
448 rc = (int)i;
449#endif
450 }
451 else
452 {
453 // "key" not found
454 rc = -1;
455 }
456
457 return rc;
458
459}
460
461template <class T>
462bool ON_SimpleArray<T>::HeapSort( int (*compar)(const T*,const T*) )
463{
464 bool rc = false;
465 if ( m_a && m_count > 0 && compar ) {
466 if ( m_count > 1 )
467 ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
468 rc = true;
469 }
470 return rc;
471}
472
473template <class T>
474bool ON_SimpleArray<T>::QuickSort( int (*compar)(const T*,const T*) )
475{
476 bool rc = false;
477 if ( m_a && m_count > 0 && compar ) {
478 if ( m_count > 1 )
479 qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
480 rc = true;
481 }
482 return rc;
483}
484
485template <class T>
486bool ON_SimpleArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const
487{
488 bool rc = false;
489 if ( m_a && m_count > 0 && compar && index ) {
490 if ( m_count > 1 )
491 ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
492 else if ( m_count == 1 )
493 index[0] = 0;
494 rc = true;
495 }
496 return rc;
497}
498
499template <class T>
500bool ON_SimpleArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const
501{
502 bool rc = false;
503 if ( m_a && m_count > 0 && compar && index ) {
504 if ( m_count > 1 )
505 ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p );
506 else if ( m_count == 1 )
507 index[0] = 0;
508 rc = true;
509 }
510 return rc;
511}
512
513template <class T>
514bool ON_SimpleArray<T>::Permute( const int* index )
515{
516 bool rc = false;
517 if ( m_a && m_count > 0 && index ) {
518 int i;
519 T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0]));
520 memcpy( buffer, m_a, m_count*sizeof(T) );
521 for (i = 0; i < m_count; i++ )
522 memcpy( m_a+i, buffer+index[i], sizeof(T) ); // must use memcopy and not operator=
523 onfree(buffer);
524 rc = true;
525 }
526 return rc;
527}
528
529template <class T>
531{
532 if ( m_a && m_capacity > 0 ) {
533 memset( m_a, 0, m_capacity*sizeof(T) );
534 }
535}
536
537template <class T>
538void ON_SimpleArray<T>::MemSet( unsigned char value )
539{
540 if ( m_a && m_capacity > 0 ) {
541 memset( m_a, value, m_capacity*sizeof(T) );
542 }
543}
544
545// memory managment ////////////////////////////////////////////////////
546
547template <class T>
548void ON_SimpleArray<T>::Reserve( int newcap )
549{
550 if( m_capacity < newcap )
551 SetCapacity( newcap );
552}
553
554template <class T>
556{
557 SetCapacity( m_count );
558}
559
560template <class T>
562{
563 SetCapacity( 0 );
564}
565
566// low level memory managment //////////////////////////////////////////
567
568template <class T>
570{
571 if ( count >= 0 && count <= m_capacity )
572 m_count = count;
573}
574
575template <class T>
577{
578 // sets capacity to input value
579 if ( capacity != m_capacity ) {
580 if( capacity > 0 ) {
581 if ( m_count > capacity )
582 m_count = capacity;
583 // NOTE: Realloc() does an allocation if the first argument is NULL.
584 m_a = Realloc( m_a, capacity );
585 if ( m_a ) {
586 if ( capacity > m_capacity ) {
587 // zero new memory
588 memset( m_a + m_capacity, 0, (capacity-m_capacity)*sizeof(T) );
589 }
590 m_capacity = capacity;
591 }
592 else {
593 // out of memory
594 m_count = m_capacity = 0;
595 }
596 }
597 else if (m_a) {
598 Realloc(m_a,0);
599 m_a = 0;
600 m_count = m_capacity = 0;
601 }
602 }
603}
604
605template <class T>
607{
608 // Note:
609 // This code appears in ON_SimpleArray<T>::NewCapacity()
610 // and ON_ClassArray<T>::NewCapacity(). Changes made to
611 // either function should be made to both functions.
612 // Because this code is template code that has to
613 // support dynamic linking and the code is defined
614 // in a header, I'm using copy-and-paste rather
615 // than a static.
616
617 // This function returns 2*m_count unless that will
618 // result in an additional allocation of more than
619 // cap_size bytes. The cap_size concept was added in
620 // January 2010 because some calculations on enormous
621 // models were slightly underestimating the initial
622 // Reserve() size and then wasting gigabytes of memory.
623
624 // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os
625 const size_t cap_size = 32*sizeof(void*)*1024*1024;
626 if (m_count*sizeof(T) <= cap_size || m_count < 8)
627 return ((m_count <= 2) ? 4 : 2*m_count);
628
629 // Growing the array will increase the memory
630 // use by more than cap_size.
631 int delta_count = 8 + cap_size/sizeof(T);
632 if ( delta_count > m_count )
633 delta_count = m_count;
634 return (m_count + delta_count);
635}
636
637template <class T>
639{
640 // Note:
641 // This code appears in ON_SimpleArray<T>::NewCapacity()
642 // and ON_ClassArray<T>::NewCapacity(). Changes made to
643 // either function should be made to both functions.
644 // Because this code is template code that has to
645 // support dynamic linking and the code is defined
646 // in a header, I'm using copy-and-paste rather
647 // than a static.
648
649 // This function returns 2*m_count unless that will
650 // result in an additional allocation of more than
651 // cap_size bytes. The cap_size concept was added in
652 // January 2010 because some calculations on enormous
653 // models were slightly underestimating the initial
654 // Reserve() size and then wasting gigabytes of memory.
655
656 // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os
657 const size_t cap_size = 32*sizeof(void*)*1024*1024;
658 if (m_count*sizeof(T) <= cap_size || m_count < 8)
659 return ((m_count <= 2) ? 4 : 2*m_count);
660
661 // Growing the array will increase the memory
662 // use by more than cap_size.
663 int delta_count = 8 + cap_size/sizeof(T);
664 if ( delta_count > m_count )
665 delta_count = m_count;
666 return (m_count + delta_count);
667}
668
670// Class ON_ObjectArray<>
672
673template <class T>
677
678template <class T>
682
683template <class T>
687
688template <class T>
690{
691 if( this != &src)
692 {
694 }
695 return *this;
696}
697
698
699template <class T>
704
705template <class T>
706T* ON_ObjectArray<T>::Realloc(T* ptr,int capacity)
707{
708 T* reptr = (T*)onrealloc(ptr,capacity*sizeof(T));
709 if ( ptr && reptr && reptr != ptr )
710 {
711 // The "this->" in this->m_count and this->m_a
712 // are needed for gcc 4 to compile.
713 int i;
714 for ( i = 0; i < this->m_count; i++ )
715 {
716 reptr[i].MemoryRelocate();
717 }
718 }
719 return reptr;
720}
721
723// Class ON_ClassArray<>
725
726
727// construction ////////////////////////////////////////////////////////
728
729template <class T>
730T* ON_ClassArray<T>::Realloc(T* ptr,int capacity)
731{
732 return (T*)onrealloc(ptr,capacity*sizeof(T));
733}
734
735template <class T>
737{
738 // The "this->" in this->m_count and this->m_a
739 // are needed for gcc 4 to compile.
740 int i;
741 for ( i = 0; i < this->m_count; i++ )
742 {
743 current_remainder = this->m_a[i].DataCRC(current_remainder);
744 }
745 return current_remainder;
746}
747
748template <class T>
750 : m_a(0),
751 m_count(0),
752 m_capacity(0)
753{}
754
755template <class T>
757 : m_a(0),
758 m_count(0),
759 m_capacity(0)
760{
761 if ( c > 0 )
762 SetCapacity( c );
765// Copy constructor
766template <class T>
768 : m_a(0),
769 m_count(0),
770 m_capacity(0)
771{
772 *this = src; // operator= defined below
774
775template <class T>
777{
778 SetCapacity(0);
779}
780
781template <class T>
783{
784 int i;
785 if( &src != this ) {
786 if ( src.m_count <= 0 ) {
787 m_count = 0;
789 else {
790 if ( m_capacity < src.m_count ) {
791 SetCapacity( src.m_count );
793 if ( m_a ) {
794 m_count = src.m_count;
795 for ( i = 0; i < m_count; i++ ) {
796 m_a[i] = src.m_a[i];
799 }
800 }
801 return *this;
802}
804// emergency destroy ///////////////////////////////////////////////////
805
806template <class T>
808{
809 m_count = 0;
810 m_capacity = 0;
811 m_a = 0;
813
814// query ///////////////////////////////////////////////////////////////
816template <class T>
819 return m_count;
821
822template <class T>
824{
825 return m_capacity;
826}
827
828template <class T>
830{
831 return ((unsigned int)(m_capacity*sizeof(T)));
832}
834template <class T>
836{
837#if defined(ON_DEBUG)
838 ON_ASSERT( i >=0 && i < m_capacity);
839#endif
840 return m_a[i];
841}
842
843template <class T>
845{
846#if defined(ON_DEBUG)
847 ON_ASSERT( i >=0 && i < m_capacity);
848#endif
849 return m_a[i];
850}
851
852template <class T>
854{
855 return (m_count > 0) ? m_a : 0;
857
858template <class T>
860{
861 return (m_count > 0) ? m_a : 0;
863
864template <class T>
866{
867 return m_a;
868}
869
870template <class T>
872{
873 return m_a;
874}
875
876template <class T>
878{
879 T* p = m_a;
880 m_count = 0;
881 m_capacity = 0;
882 m_a = NULL;
883 return p;
884}
885
886template <class T>
888{
889 m_a = p;
890}
891
892template <class T>
894{
895 return (m_count > 0) ? m_a : 0;
896}
897
898template <class T>
900{
901 return (m_count > 0) ? m_a : 0;
903
904template <class T>
906{
907 return (i >= 0 && i < m_count) ? m_a+i : 0;
909
910template <class T>
911const T* ON_ClassArray<T>::At( int i) const
913 return (i >= 0 && i < m_count) ? m_a+i : 0;
915
916template <class T>
918{
919 return (m_count > 0) ? m_a+(m_count-1) : 0;
920}
921
922template <class T>
924{
925 return (m_count > 0) ? m_a+(m_count-1) : 0;
926}
927
928// array operations ////////////////////////////////////////////////////
929
930template <class T>
931void ON_ClassArray<T>::Move( int dest_i, int src_i, int ele_cnt )
932{
933 // private function for moving blocks of array memory
934 // caller is responsible for updating m_count and managing
935 // destruction/creation.
936 if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i ||
937 src_i + ele_cnt > m_count || dest_i > m_count )
938 return;
939
940 int capacity = dest_i + ele_cnt;
941 if ( capacity > m_capacity ) {
942 if ( capacity < 2*m_capacity )
943 capacity = 2*m_capacity;
944 SetCapacity( capacity );
945 }
947 memmove( &m_a[dest_i], &m_a[src_i], ele_cnt*sizeof(T) );
948}
950template <class T>
952{
953 // use placement ( new(size_t,void*) ) to construct
954 // T in supplied memory
955 new(p) T;
957
958template <class T>
960{
961 x.~T();
962}
963
964template <class T>
966{
967 if ( m_count == m_capacity )
968 {
969 int newcapacity = NewCapacity();
970 Reserve( newcapacity );
971 }
972 else
973 {
974 // First destroy what's there ..
975 DestroyElement(m_a[m_count]);
976 // and then get a properly initialized element
977 ConstructDefaultElement(&m_a[m_count]);
978 }
979 return m_a[m_count++];
982template <class T>
983void ON_ClassArray<T>::Append( const T& x )
984{
985 if ( m_count == m_capacity )
986 {
987 const int newcapacity = NewCapacity();
988 if (m_a)
989 {
990 const int s = (int)(&x - m_a); // (int) cast is for 64 bit pointers
991 if ( s >= 0 && s < m_capacity )
992 {
993 // 26 Sep 2005 Dale Lear
994 // User passed in an element of the m_a[]
995 // that will get reallocated by the call
996 // to Reserve(newcapacity).
997 T temp; // ON_*Array<> templates do not require robust copy constructor.
998 temp = x; // ON_*Array<> templates require a robust operator=.
999 Reserve( newcapacity );
1000 m_a[m_count++] = temp;
1001 return;
1004 Reserve(newcapacity);
1005 }
1006 m_a[m_count++] = x;
1007}
1008
1009template <class T>
1010void ON_ClassArray<T>::Append( int count, const T* p )
1012 int i;
1013 if ( count > 0 && p )
1014 {
1015 if ( count + m_count > m_capacity )
1017 int newcapacity = NewCapacity();
1018 if ( newcapacity < count + m_count )
1019 newcapacity = count + m_count;
1020 Reserve( newcapacity );
1022 for ( i = 0; i < count; i++ ) {
1023 m_a[m_count++] = p[i];
1024 }
1025 }
1026}
1027
1028// Insert called with a reference uses operator =
1029template <class T>
1030void ON_ClassArray<T>::Insert( int i, const T& x )
1031{
1032 if( i >= 0 && i <= m_count )
1033 {
1034 if ( m_count == m_capacity )
1035 {
1036 int newcapacity = NewCapacity();
1037 Reserve( newcapacity );
1038 }
1039 DestroyElement( m_a[m_count] );
1040 m_count++;
1041 if ( i < m_count-1 ) {
1042 Move( i+1, i, m_count-1-i );
1043 memset( &m_a[i], 0, sizeof(T) );
1044 ConstructDefaultElement( &m_a[i] );
1045 }
1046 else {
1047 ConstructDefaultElement( &m_a[m_count-1] );
1048 }
1049 m_a[i] = x; // uses T::operator=() to copy x to array
1050 }
1051}
1052
1053template <class T>
1055{
1056 Remove(m_count-1);
1057}
1058
1059template <class T>
1061{
1062 if ( i >= 0 && i < m_count )
1063 {
1064 DestroyElement( m_a[i] );
1065 memset( &m_a[i], 0, sizeof(T) );
1066 Move( i, i+1, m_count-1-i );
1067 memset( &m_a[m_count-1], 0, sizeof(T) );
1068 ConstructDefaultElement(&m_a[m_count-1]);
1069 m_count--;
1070 }
1071}
1072
1073template <class T>
1075{
1076 int i;
1077 for ( i = m_count-1; i >= 0; i-- ) {
1078 DestroyElement( m_a[i] );
1079 memset( &m_a[i], 0, sizeof(T) );
1080 ConstructDefaultElement( &m_a[i] );
1081 }
1082 m_count = 0;
1083}
1084
1085template <class T>
1087{
1088 // NOTE:
1089 // If anything in "T" depends on the value of this's address,
1090 // then don't call Reverse().
1091 char t[sizeof(T)];
1092 int i = 0;
1093 int j = m_count-1;
1094 for ( /*empty*/; i < j; i++, j-- ) {
1095 memcpy( t, &m_a[i], sizeof(T) );
1096 memcpy( &m_a[i], &m_a[j], sizeof(T) );
1097 memcpy( &m_a[j], t, sizeof(T) );
1098 }
1099}
1100
1101template <class T>
1102void ON_ClassArray<T>::Swap( int i, int j )
1103{
1104 if ( i != j && i >= 0 && j >= 0 && i < m_count && j < m_count ) {
1105 char t[sizeof(T)];
1106 memcpy( t, &m_a[i], sizeof(T) );
1107 memcpy( &m_a[i], &m_a[j], sizeof(T) );
1108 memcpy( &m_a[j], t, sizeof(T) );
1109 }
1110}
1111
1112template <class T>
1113int ON_ClassArray<T>::Search( const T* key, int (*compar)(const T*,const T*) ) const
1114{
1115 for ( int i = 0; i < m_count; i++ )
1116 {
1117 if (!compar(key,m_a+i))
1118 return i;
1119 }
1120 return -1;
1121}
1122
1123template <class T>
1124int ON_ClassArray<T>::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const
1125{
1126 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 ) : 0;
1127#if defined(ON_COMPILER_MSC1300)
1128 // for 32 and 64 bit compilers - the (int) converts 64 bit size_t
1129 return found ? ((int)(found - m_a)) : -1;
1130#else
1131 // for lamer 64 bit compilers
1132 return found ? ((int)((((ON__UINT64)found) - ((ON__UINT64)m_a))/sizeof(T))) : -1;
1133#endif
1134}
1135
1136template <class T>
1137bool ON_ClassArray<T>::HeapSort( int (*compar)(const T*,const T*) )
1138{
1139 bool rc = false;
1140 if ( m_a && m_count > 0 && compar )
1141 {
1142 if ( m_count > 1 )
1143 ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1144 rc = true;
1145 }
1146 return rc;
1147}
1148
1149template <class T>
1150bool ON_ClassArray<T>::QuickSort( int (*compar)(const T*,const T*) )
1151{
1152 bool rc = false;
1153 if ( m_a && m_count > 0 && compar )
1154 {
1155 if ( m_count > 1 )
1156 qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1157 rc = true;
1158 }
1159 return rc;
1160}
1161
1162
1163
1164template <class T>
1165bool ON_ObjectArray<T>::HeapSort( int (*compar)(const T*,const T*) )
1166{
1167 bool rc = false;
1168 // The "this->" in this->m_count and this->m_a
1169 // are needed for gcc 4 to compile.
1170 if ( this->m_a && this->m_count > 0 && compar )
1171 {
1172 if ( this->m_count > 1 )
1173 {
1174 ON_hsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1175
1176 // The MemoryRelocate step is required to synch userdata back pointers
1177 // so the user data destructor will work correctly.
1178 int i;
1179 for ( i = 0; i < this->m_count; i++ )
1180 {
1181 this->m_a[i].MemoryRelocate();
1182 }
1183 }
1184 rc = true;
1185 }
1186 return rc;
1187}
1188
1189template <class T>
1190bool ON_ObjectArray<T>::QuickSort( int (*compar)(const T*,const T*) )
1191{
1192 bool rc = false;
1193 // The "this->" in this->m_count and this->m_a
1194 // are needed for gcc 4 to compile.
1195 if ( this->m_a && this->m_count > 0 && compar )
1196 {
1197 if ( this->m_count > 1 )
1198 {
1199 qsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1200
1201 // The MemoryRelocate step is required to synch userdata back pointers
1202 // so the user data destructor will work correctly.
1203 int i;
1204 for ( i = 0; i < this->m_count; i++ )
1205 {
1206 this->m_a[i].MemoryRelocate();
1207 }
1208 }
1209 rc = true;
1210 }
1211 return rc;
1212}
1213
1214
1215template <class T>
1216bool ON_ClassArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const
1217{
1218 bool rc = false;
1219 if ( m_a && m_count > 0 && compar && index )
1220 {
1221 if ( m_count > 1 )
1222 ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar );
1223 else if ( m_count == 1 )
1224 index[0] = 0;
1225 rc = true;
1226 }
1227 return rc;
1228}
1229
1230template <class T>
1231bool ON_ClassArray<T>::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const
1232{
1233 bool rc = false;
1234 if ( m_a && m_count > 0 && compar && index )
1235 {
1236 if ( m_count > 1 )
1237 ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p );
1238 else if ( m_count == 1 )
1239 index[0] = 0;
1240 rc = true;
1241 }
1242 return rc;
1243}
1244
1245template <class T>
1246bool ON_ClassArray<T>::Permute( const int* index )
1247{
1248 bool rc = false;
1249 if ( m_a && m_count > 0 && index )
1250 {
1251 int i;
1252 T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0]));
1253 memcpy( buffer, m_a, m_count*sizeof(T) );
1254 for (i = 0; i < m_count; i++ )
1255 memcpy( m_a+i, buffer+index[i], sizeof(T) ); // must use memcopy and not operator=
1256 onfree(buffer);
1257 rc = true;
1258 }
1259 return rc;
1260}
1261
1262template <class T>
1264{
1265 int i;
1266 if ( m_a && m_capacity > 0 ) {
1267 for ( i = m_capacity-1; i >= 0; i-- ) {
1268 DestroyElement(m_a[i]);
1269 memset( &m_a[i], 0, sizeof(T) );
1270 ConstructDefaultElement(&m_a[i]);
1271 }
1272 }
1273}
1274
1275// memory managment ////////////////////////////////////////////////////
1276
1277template <class T>
1278void ON_ClassArray<T>::Reserve( int newcap )
1279{
1280 if( m_capacity < newcap )
1281 SetCapacity( newcap );
1282}
1283
1284template <class T>
1286{
1287 SetCapacity( m_count );
1288}
1289
1290template <class T>
1292{
1293 SetCapacity( 0 );
1294}
1295
1296// low level memory managment //////////////////////////////////////////
1297
1298template <class T>
1300{
1301 if ( count >= 0 && count <= m_capacity )
1302 m_count = count;
1303}
1304
1305template <class T>
1307{
1308 // uses "placement" for class construction/destruction
1309 int i;
1310 if ( capacity < 1 ) {
1311 if ( m_a ) {
1312 for ( i = m_capacity-1; i >= 0; i-- ) {
1313 DestroyElement(m_a[i]);
1314 }
1315 Realloc(m_a,0);
1316 m_a = 0;
1317 }
1318 m_count = 0;
1319 m_capacity = 0;
1320 }
1321 else if ( m_capacity < capacity ) {
1322 // growing
1323 m_a = Realloc( m_a, capacity );
1324 // initialize new elements with default constructor
1325 if ( 0 != m_a )
1326 {
1327 memset( m_a + m_capacity, 0, (capacity-m_capacity)*sizeof(T) );
1328 for ( i = m_capacity; i < capacity; i++ ) {
1329 ConstructDefaultElement(&m_a[i]);
1330 }
1331 m_capacity = capacity;
1332 }
1333 else
1334 {
1335 // memory allocation failed
1336 m_capacity = 0;
1337 m_count = 0;
1338 }
1339 }
1340 else if ( m_capacity > capacity ) {
1341 // shrinking
1342 for ( i = m_capacity-1; i >= capacity; i-- ) {
1343 DestroyElement(m_a[i]);
1344 }
1345 if ( m_count > capacity )
1346 m_count = capacity;
1347 m_capacity = capacity;
1348 m_a = Realloc( m_a, capacity );
1349 if ( 0 == m_a )
1350 {
1351 // memory allocation failed
1352 m_capacity = 0;
1353 m_count = 0;
1354 }
1355 }
1356}
1357
1361
1362template< class T>
1363static
1364int ON_CompareIncreasing( const T* a, const T* b)
1365{
1366 if( *a < *b )
1367 return -1;
1368 if( *b < *a )
1369 return 1;
1370 return 0;
1371}
1372
1373template< class T>
1374static
1375int ON_CompareDecreasing( const T* a, const T* b)
1376{
1377 if( *b < *a )
1378 return -1;
1379 if( *a < *b )
1380 return 1;
1381 return 0;
1382}
1383
1384#if defined(ON_COMPILER_MSC)
1385#pragma warning(pop)
1386#endif
1387
1388#endif
int i
Copyright (c) 2011-2018 by Andrew Mustun.
Definition autostart.js:32
Definition opennurbs_array.h:760
T * First()
Definition opennurbs_array_defs.h:893
void SetCapacity(int)
Definition opennurbs_array_defs.h:1306
int Count() const
Definition opennurbs_array_defs.h:817
unsigned int SizeOfArray() const
Definition opennurbs_array_defs.h:829
T & AppendNew()
Definition opennurbs_array_defs.h:965
void Shrink()
Definition opennurbs_array_defs.h:1285
T * Array()
Definition opennurbs_array_defs.h:865
int NewCapacity() const
Definition opennurbs_array_defs.h:638
void SetArray(T *)
Definition opennurbs_array_defs.h:887
void Append(const T &)
Definition opennurbs_array_defs.h:983
void Zero()
Definition opennurbs_array_defs.h:1263
T * At(int)
Definition opennurbs_array_defs.h:905
void Move(int, int, int)
Definition opennurbs_array_defs.h:931
bool Permute(const int *)
Definition opennurbs_array_defs.h:1246
T * Last()
Definition opennurbs_array_defs.h:917
virtual T * Realloc(T *, int)
Definition opennurbs_array_defs.h:730
T & operator[](int)
Definition opennurbs_array_defs.h:835
int BinarySearch(const T *, int(*)(const T *, const T *)) const
Definition opennurbs_array_defs.h:1124
ON_ClassArray()
Definition opennurbs_array_defs.h:749
void SetCount(int)
Definition opennurbs_array_defs.h:1299
int Search(const T *, int(*)(const T *, const T *)) const
Definition opennurbs_array_defs.h:1113
void ConstructDefaultElement(T *)
Definition opennurbs_array_defs.h:951
bool Sort(ON::sort_algorithm, int *, int(*)(const T *, const T *)) const
Definition opennurbs_array_defs.h:1216
void Swap(int, int)
Definition opennurbs_array_defs.h:1102
virtual bool QuickSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:1150
ON_ClassArray< T > & operator=(const ON_ClassArray< T > &)
Definition opennurbs_array_defs.h:782
void Destroy()
Definition opennurbs_array_defs.h:1291
void Remove()
Definition opennurbs_array_defs.h:1054
T * KeepArray()
Definition opennurbs_array_defs.h:877
void Empty()
Definition opennurbs_array_defs.h:1074
void DestroyElement(T &)
Definition opennurbs_array_defs.h:959
virtual ~ON_ClassArray()
Definition opennurbs_array_defs.h:776
void Reserve(int)
Definition opennurbs_array_defs.h:1278
T * m_a
Definition opennurbs_array.h:983
void Reverse()
Definition opennurbs_array_defs.h:1086
virtual bool HeapSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:1137
void EmergencyDestroy(void)
Definition opennurbs_array_defs.h:807
void Insert(int, const T &)
Definition opennurbs_array_defs.h:1030
int m_count
Definition opennurbs_array.h:984
int Capacity() const
Definition opennurbs_array_defs.h:823
Definition opennurbs_array.h:998
T * Realloc(T *, int)
Definition opennurbs_array_defs.h:706
~ON_ObjectArray()
Definition opennurbs_array_defs.h:679
ON_ObjectArray()
Definition opennurbs_array_defs.h:674
bool HeapSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:1165
bool QuickSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:1190
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const
Definition opennurbs_array_defs.h:736
ON_ObjectArray< T > & operator=(const ON_ObjectArray< T > &)
Definition opennurbs_array_defs.h:689
Definition opennurbs_array.h:46
void Shrink()
Definition opennurbs_array_defs.h:555
void Zero()
Definition opennurbs_array_defs.h:530
T * Last()
Definition opennurbs_array_defs.h:240
void Append(const T &)
Definition opennurbs_array_defs.h:285
T * At(int)
Definition opennurbs_array_defs.h:228
int m_count
Definition opennurbs_array.h:290
void SetCount(int)
Definition opennurbs_array_defs.h:569
void Insert(int, const T &)
Definition opennurbs_array_defs.h:329
void Destroy()
Definition opennurbs_array_defs.h:561
void Swap(int, int)
Definition opennurbs_array_defs.h:385
T * m_a
Definition opennurbs_array.h:289
T & operator[](int)
Definition opennurbs_array_defs.h:157
int NewCapacity() const
Definition opennurbs_array_defs.h:606
bool Sort(ON::sort_algorithm, int *, int(*)(const T *, const T *)) const
Definition opennurbs_array_defs.h:486
void SetArray(T *)
Definition opennurbs_array_defs.h:209
ON_SimpleArray()
Definition opennurbs_array_defs.h:68
unsigned int SizeOfArray() const
Definition opennurbs_array_defs.h:145
bool HeapSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:462
void EmergencyDestroy(void)
Definition opennurbs_array_defs.h:123
void Empty()
Definition opennurbs_array_defs.h:361
void Reverse()
Definition opennurbs_array_defs.h:369
bool QuickSort(int(*)(const T *, const T *))
Definition opennurbs_array_defs.h:474
void Move(int, int, int)
Definition opennurbs_array_defs.h:254
void Reserve(int)
Definition opennurbs_array_defs.h:548
void MemSet(unsigned char)
Definition opennurbs_array_defs.h:538
void SetCapacity(int)
Definition opennurbs_array_defs.h:576
ON__UINT32 DataCRC(ON__UINT32 current_remainder) const
Definition opennurbs_array_defs.h:151
int Search(const T &) const
Definition opennurbs_array_defs.h:395
void Remove()
Definition opennurbs_array_defs.h:345
virtual T * Realloc(T *, int)
Definition opennurbs_array_defs.h:62
bool Permute(const int *)
Definition opennurbs_array_defs.h:514
int Count() const
Definition opennurbs_array_defs.h:133
virtual ON_SimpleArray< T > & operator=(const ON_SimpleArray< T > &)
Definition opennurbs_array_defs.h:101
T & AppendNew()
Definition opennurbs_array_defs.h:273
T * First()
Definition opennurbs_array_defs.h:216
T * Array()
Definition opennurbs_array_defs.h:187
int BinarySearch(const T *, int(*)(const T *, const T *)) const
Definition opennurbs_array_defs.h:416
int Capacity() const
Definition opennurbs_array_defs.h:139
virtual ~ON_SimpleArray()
Definition opennurbs_array_defs.h:95
T * KeepArray()
Definition opennurbs_array_defs.h:199
static int ON_CompareDecreasing(const T *a, const T *b)
Definition opennurbs_array_defs.h:1375
static int ON_CompareIncreasing(const T *a, const T *b)
Definition opennurbs_array_defs.h:1364
ON__UINT32 ON_CRC32(ON__UINT32 current_remainder, size_t count, const void *p)
Definition opennurbs_crc.cpp:109
#define ON_ASSERT(cond)
Definition opennurbs_error.h:31
void ON_Sort(ON::sort_algorithm method, int *index, const void *data, size_t count, size_t sizeof_element, int(*compar)(const void *, const void *))
Definition opennurbs_math.cpp:2812
void ON_hsort(void *base, size_t nel, size_t width, int(*compar)(const void *, const void *))
Definition opennurbs_math.cpp:3043
ON_DECL void onfree(void *)
ON_DECL void * onrealloc(void *, size_t)
ON_DECL void * onmalloc(size_t)
char s
Definition opennurbs_string.cpp:32
#define NULL
Definition opennurbs_system.h:256
unsigned long long ON__UINT64
Definition opennurbs_system.h:356
unsigned int ON__UINT32
Definition opennurbs_system.h:326