bbarray.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #ifndef BB_ARRAY_H
  2. #define BB_ARRAY_H
  3. #ifdef BB_THREADS
  4. #include "bbgc_mx.h"
  5. #else
  6. #include "bbgc.h"
  7. #endif
  8. template<class T,int D> struct bbArray{
  9. struct Rep : public bbGCNode{
  10. int _sizes[D];
  11. T _data[0];
  12. Rep(){
  13. memset( _sizes,0,sizeof(_sizes) );
  14. }
  15. Rep( int sizes[] ){
  16. bbGC::beginCtor( this );
  17. memcpy( _sizes,sizes,D*sizeof(int) );
  18. for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
  19. }
  20. ~Rep(){
  21. for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
  22. }
  23. virtual const char *typeName()const{
  24. return "bbArray::Rep";
  25. }
  26. virtual void gcMark(){
  27. for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );
  28. }
  29. virtual void dbEmit(){
  30. int n=_sizes[D-1];if( n>100 ) n=100;
  31. for( int i=0;i<n;++i ){
  32. char buf[16];
  33. sprintf( buf,"[%i]",i );
  34. bbDBEmit( buf,&_data[i] );
  35. }
  36. }
  37. };
  38. Rep *_rep=nullptr;
  39. bbArray(){
  40. }
  41. bbArray( const bbArray &t ){
  42. bbGC::enqueue( t._rep );
  43. _rep=t._rep;
  44. }
  45. template<class...Args> explicit bbArray( Args...args ){
  46. int sizes[]{ args... };
  47. for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
  48. if( !sizes[D-1] ) return;
  49. void *p=bbGC::malloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
  50. _rep=new( p ) Rep( sizes );
  51. bbGC::endCtor( _rep );
  52. }
  53. template<class...Args> explicit bbArray( std::initializer_list<T> init,Args...args ){
  54. int sizes[]{ args... };
  55. for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
  56. if( !sizes[D-1] ) return;
  57. void *p=bbGC::malloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
  58. _rep=new( p ) Rep( sizes );
  59. int i=0,n=sizes[D-1];
  60. bbDebugAssert( n==init.size(),"Incorrect number of array initializers" );
  61. for( auto it=init.begin();i<n; )_rep->_data[i++]=*it++;
  62. bbGC::endCtor( _rep );
  63. }
  64. void retain()const{
  65. bbGC::retain( _rep );
  66. }
  67. void release()const{
  68. bbGC::release( _rep );
  69. }
  70. void discard(){
  71. _rep=nullptr;
  72. }
  73. T *data(){
  74. return _rep->_data;
  75. }
  76. const T *data()const{
  77. return _rep->_data;
  78. }
  79. int length()const{
  80. return _rep ? _rep->_sizes[D-1] : 0;
  81. }
  82. int size( int q )const{
  83. bbDebugAssert( q>=0 && q<D,"Array dimension out of range" );
  84. return _rep ? (q ? _rep->_sizes[q]/_rep->_sizes[q-1] : _rep->_sizes[0]) : 0;
  85. }
  86. bbArray &operator=( const bbArray &t ){
  87. bbGC::enqueue( t._rep );
  88. _rep=t._rep;
  89. return *this;
  90. }
  91. T &operator[]( int index ){
  92. bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
  93. return data()[index];
  94. }
  95. T &at( int index ){
  96. bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
  97. return data()[index];
  98. }
  99. //slower N-D version
  100. template<class...Args> T &at( Args...args ){
  101. const int indices[]{args...};
  102. int index=indices[0];
  103. bbDebugAssert( index>=0 && _rep,"Array index out of range" );
  104. for( int i=1;i<D;++i ){
  105. bbDebugAssert( indices[i]>=0 && index<_rep->_sizes[i-1],"Array index out of range" );
  106. index+=indices[i]*_rep->_sizes[i-1];
  107. }
  108. bbDebugAssert( index<length(),"Array index out of range" );
  109. return data()[index];
  110. }
  111. operator bool()const{
  112. return _rep;
  113. }
  114. bbArray<T,1> slice( int from )const{
  115. return slice( from,length() );
  116. }
  117. bbArray<T,1> slice( int from,int term )const{
  118. int length=this->length();
  119. if( from<0 ){
  120. from+=length;
  121. if( from<0 ) from=0;
  122. }else if( from>length ){
  123. from=length;
  124. }
  125. if( term<0 ){
  126. term+=length;
  127. if( term<from ) term=from;
  128. }else if( term<from ){
  129. term=from;
  130. }else if( term>length ){
  131. term=length;
  132. }
  133. int newlen=term-from;
  134. bbArray<T,1> r{newlen};
  135. for( int i=0;i<newlen;++i ) r.data()[i]=data()[from+i];
  136. return r;
  137. }
  138. bbArray<T,1> resize( int newLength )const{
  139. bbDebugAssert( newLength>=0,"Array Resize new length must not be negative" );
  140. int ncopy=length();
  141. if( ncopy>newLength ) ncopy=newLength;
  142. auto r=bbArray<T,1>( newLength );
  143. for( int i=0;i<ncopy;++i ) r.data()[i]=data()[i];
  144. return r;
  145. }
  146. void copyTo( bbArray<T,1> dst,int offset,int dstOffset,int count )const{
  147. bbDebugAssert( offset>=0 && dstOffset>=0 && count>=0 && offset+count<=length() && dstOffset+count<=dst.length(),"Array CopyTo parameters out of range" );
  148. if( dst._rep==_rep && dstOffset>offset ){
  149. for( int i=count-1;i>=0;--i ) dst.data()[dstOffset+i]=data()[offset+i];
  150. }else{
  151. for( int i=0;i<count;++i ) dst.data()[dstOffset+i]=data()[offset+i];
  152. }
  153. }
  154. };
  155. template<class T,int D> bbString bbDBType( bbArray<T,D> *p ){
  156. return bbDBType<T>()+"[]";
  157. }
  158. template<class T,int D> bbString bbDBValue( bbArray<T,D> *p ){
  159. char buf[64];
  160. sprintf( buf,"@%p",*(void**)(&p->_rep) );
  161. return bbString( buf )+"["+bbString( p->length() )+"]";
  162. }
  163. template<class T,int D> void bbGCMark( bbArray<T,D> arr ){
  164. bbGC::enqueue( arr._rep );
  165. }
  166. #endif