123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- #ifndef BB_ARRAY_H
- #define BB_ARRAY_H
- #ifdef BB_THREADS
- #include "bbgc_mx.h"
- #else
- #include "bbgc.h"
- #endif
- template<class T,int D> struct bbArray{
- struct Rep : public bbGCNode{
-
- int _sizes[D];
- T _data[0];
-
- Rep(){
- memset( _sizes,0,sizeof(_sizes) );
- }
-
- Rep( int sizes[] ){
- bbGC::beginCtor( this );
-
- memcpy( _sizes,sizes,D*sizeof(int) );
-
- for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
- }
-
- ~Rep(){
- for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
- }
-
- virtual const char *typeName()const{
- return "bbArray::Rep";
- }
-
- virtual void gcMark(){
- for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );
- }
-
- virtual void dbEmit(){
- int n=_sizes[D-1];if( n>100 ) n=100;
- for( int i=0;i<n;++i ){
- char buf[16];
- sprintf( buf,"[%i]",i );
- bbDBEmit( buf,&_data[i] );
- }
- }
- };
-
- Rep *_rep=nullptr;
- bbArray(){
- }
-
- bbArray( const bbArray &t ){
-
- bbGC::enqueue( t._rep );
-
- _rep=t._rep;
- }
-
- template<class...Args> explicit bbArray( Args...args ){
-
- int sizes[]{ args... };
- for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
-
- if( !sizes[D-1] ) return;
-
- void *p=bbGC::malloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
-
- _rep=new( p ) Rep( sizes );
-
- bbGC::endCtor( _rep );
- }
-
- template<class...Args> explicit bbArray( std::initializer_list<T> init,Args...args ){
-
- int sizes[]{ args... };
- for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
-
- if( !sizes[D-1] ) return;
-
- void *p=bbGC::malloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
-
- _rep=new( p ) Rep( sizes );
-
- int i=0,n=sizes[D-1];
- bbDebugAssert( n==init.size(),"Incorrect number of array initializers" );
- for( auto it=init.begin();i<n; )_rep->_data[i++]=*it++;
-
- bbGC::endCtor( _rep );
- }
-
- void retain()const{
- bbGC::retain( _rep );
- }
-
- void release()const{
- bbGC::release( _rep );
- }
-
- void discard(){
- _rep=nullptr;
- }
-
- T *data(){
- return _rep->_data;
- }
-
- const T *data()const{
- return _rep->_data;
- }
-
- int length()const{
- return _rep ? _rep->_sizes[D-1] : 0;
- }
-
- int size( int q )const{
- bbDebugAssert( q>=0 && q<D,"Array dimension out of range" );
-
- return _rep ? (q ? _rep->_sizes[q]/_rep->_sizes[q-1] : _rep->_sizes[0]) : 0;
- }
-
- bbArray &operator=( const bbArray &t ){
-
- bbGC::enqueue( t._rep );
-
- _rep=t._rep;
-
- return *this;
- }
-
- T &operator[]( int index ){
- bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
-
- return data()[index];
- }
-
- T &at( int index ){
- bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
-
- return data()[index];
- }
-
- //slower N-D version
- template<class...Args> T &at( Args...args ){
-
- const int indices[]{args...};
-
- int index=indices[0];
- bbDebugAssert( index>=0 && _rep,"Array index out of range" );
-
- for( int i=1;i<D;++i ){
- bbDebugAssert( indices[i]>=0 && index<_rep->_sizes[i-1],"Array index out of range" );
-
- index+=indices[i]*_rep->_sizes[i-1];
- }
-
- bbDebugAssert( index<length(),"Array index out of range" );
-
- return data()[index];
- }
-
- operator bool()const{
-
- return _rep;
- }
-
- bbArray<T,1> slice( int from )const{
-
- return slice( from,length() );
- }
-
- bbArray<T,1> slice( int from,int term )const{
-
- int length=this->length();
-
- if( from<0 ){
- from+=length;
- if( from<0 ) from=0;
- }else if( from>length ){
- from=length;
- }
-
- if( term<0 ){
- term+=length;
- if( term<from ) term=from;
- }else if( term<from ){
- term=from;
- }else if( term>length ){
- term=length;
- }
-
- int newlen=term-from;
-
- bbArray<T,1> r{newlen};
-
- for( int i=0;i<newlen;++i ) r.data()[i]=data()[from+i];
-
- return r;
- }
-
- bbArray<T,1> resize( int newLength )const{
- bbDebugAssert( newLength>=0,"Array Resize new length must not be negative" );
-
- int ncopy=length();
- if( ncopy>newLength ) ncopy=newLength;
-
- auto r=bbArray<T,1>( newLength );
-
- for( int i=0;i<ncopy;++i ) r.data()[i]=data()[i];
-
- return r;
- }
-
- void copyTo( bbArray<T,1> dst,int offset,int dstOffset,int count )const{
- bbDebugAssert( offset>=0 && dstOffset>=0 && count>=0 && offset+count<=length() && dstOffset+count<=dst.length(),"Array CopyTo parameters out of range" );
-
- if( dst._rep==_rep && dstOffset>offset ){
- for( int i=count-1;i>=0;--i ) dst.data()[dstOffset+i]=data()[offset+i];
- }else{
- for( int i=0;i<count;++i ) dst.data()[dstOffset+i]=data()[offset+i];
- }
- }
- };
- template<class T,int D> bbString bbDBType( bbArray<T,D> *p ){
- return bbDBType<T>()+"[]";
- }
- template<class T,int D> bbString bbDBValue( bbArray<T,D> *p ){
- char buf[64];
- sprintf( buf,"@%p",*(void**)(&p->_rep) );
- return bbString( buf )+"["+bbString( p->length() )+"]";
- }
- template<class T,int D> void bbGCMark( bbArray<T,D> arr ){
- bbGC::enqueue( arr._rep );
- }
- #endif
|