diff options
Diffstat (limited to '')
| -rw-r--r-- | src/array.h | 245 |
1 files changed, 167 insertions, 78 deletions
diff --git a/src/array.h b/src/array.h index 6279382..af41c33 100644 --- a/src/array.h +++ b/src/array.h | |||
| @@ -11,10 +11,95 @@ | |||
| 11 | #include <memory> | 11 | #include <memory> |
| 12 | #include "bu/exceptionbase.h" | 12 | #include "bu/exceptionbase.h" |
| 13 | #include "bu/archivebase.h" | 13 | #include "bu/archivebase.h" |
| 14 | #include "bu/sharedcore.h" | ||
| 14 | 15 | ||
| 15 | namespace Bu | 16 | namespace Bu |
| 16 | { | 17 | { |
| 17 | subExceptionDecl( ArrayException ) | 18 | subExceptionDecl( ArrayException ) |
| 19 | |||
| 20 | template<typename value, int inc, typename valuealloc> | ||
| 21 | class ArrayCore | ||
| 22 | { | ||
| 23 | public: | ||
| 24 | ArrayCore() : | ||
| 25 | pData( NULL ), | ||
| 26 | iSize( 0 ), | ||
| 27 | iCapacity( 0 ) | ||
| 28 | { } | ||
| 29 | |||
| 30 | void setCapacity( int iNewLen ) | ||
| 31 | { | ||
| 32 | //clear(); | ||
| 33 | //iCapacity = iCapacity; | ||
| 34 | //pData = va.allocate( iCapacity ); | ||
| 35 | if( iNewLen <= iCapacity ) return; | ||
| 36 | value *pNewData = va.allocate( iNewLen ); | ||
| 37 | if( pData ) | ||
| 38 | { | ||
| 39 | for( int j = 0; j < iSize; j++ ) | ||
| 40 | { | ||
| 41 | va.construct( &pNewData[j], pData[j] ); | ||
| 42 | va.destroy( &pData[j] ); | ||
| 43 | } | ||
| 44 | va.deallocate( pData, iCapacity ); | ||
| 45 | } | ||
| 46 | pData = pNewData; | ||
| 47 | iCapacity = iNewLen; | ||
| 48 | } | ||
| 49 | |||
| 50 | virtual ~ArrayCore() | ||
| 51 | { | ||
| 52 | clear(); | ||
| 53 | } | ||
| 54 | |||
| 55 | void clear() | ||
| 56 | { | ||
| 57 | if( pData ) | ||
| 58 | { | ||
| 59 | for( int j = 0; j < iSize; j++ ) | ||
| 60 | { | ||
| 61 | va.destroy( &pData[j] ); | ||
| 62 | } | ||
| 63 | va.deallocate( pData, iCapacity ); | ||
| 64 | pData = NULL; | ||
| 65 | } | ||
| 66 | iSize = 0; | ||
| 67 | iCapacity = 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | void erase( int iPos ) | ||
| 71 | { | ||
| 72 | for( int j = iPos; j < iSize; j++ ) | ||
| 73 | { | ||
| 74 | va.destroy( &pData[j] ); | ||
| 75 | if( j == iSize-1 ) | ||
| 76 | { | ||
| 77 | iSize--; | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | va.construct( &pData[j], pData[j+1] ); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void swapErase( int iPos ) | ||
| 85 | { | ||
| 86 | if( iPos == iSize-1 ) | ||
| 87 | { | ||
| 88 | erase( iPos ); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | va.destroy( &pData[iPos] ); | ||
| 92 | va.construct( &pData[iPos], pData[iSize-1] ); | ||
| 93 | va.destroy( &pData[iSize-1] ); | ||
| 94 | iSize--; | ||
| 95 | } | ||
| 96 | |||
| 97 | valuealloc va; | ||
| 98 | value *pData; | ||
| 99 | long iSize; | ||
| 100 | long iCapacity; | ||
| 101 | }; | ||
| 102 | |||
| 18 | /** | 103 | /** |
| 19 | * Array type container, just like a normal array only flexible and keeps | 104 | * Array type container, just like a normal array only flexible and keeps |
| 20 | * track of your memory for you. | 105 | * track of your memory for you. |
| @@ -25,51 +110,57 @@ namespace Bu | |||
| 25 | *@ingroup Containers | 110 | *@ingroup Containers |
| 26 | */ | 111 | */ |
| 27 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > | 112 | template<typename value, int inc=10, typename valuealloc=std::allocator<value> > |
| 28 | class Array | 113 | class Array : public SharedCore<ArrayCore<value, inc, valuealloc> > |
| 29 | { | 114 | { |
| 30 | private: | 115 | private: |
| 31 | typedef class Array<value, inc, valuealloc> MyType; | 116 | typedef class Array<value, inc, valuealloc> MyType; |
| 117 | typedef class ArrayCore<value, inc, valuealloc> Core; | ||
| 118 | |||
| 119 | protected: | ||
| 120 | using SharedCore< Core >::core; | ||
| 121 | using SharedCore< Core >::_hardCopy; | ||
| 122 | using SharedCore< Core >::_allocateCore; | ||
| 32 | 123 | ||
| 33 | public: | 124 | public: |
| 34 | Array() : | 125 | struct const_iterator; |
| 35 | pData( NULL ), | 126 | struct iterator; |
| 36 | iSize( 0 ), | 127 | |
| 37 | iCapacity( 0 ) | 128 | Array() |
| 38 | { | 129 | { |
| 39 | } | 130 | } |
| 40 | 131 | ||
| 41 | Array( const MyType &src ) : | 132 | Array( const MyType &src ) : |
| 42 | pData( NULL ), | 133 | SharedCore< Core >( src ) |
| 43 | iSize( 0 ), | ||
| 44 | iCapacity( 0 ) | ||
| 45 | { | 134 | { |
| 46 | *this = src; | ||
| 47 | } | 135 | } |
| 48 | 136 | ||
| 49 | Array( long iSetCap ) : | 137 | Array( long iSetCap ) |
| 50 | pData( NULL ), | ||
| 51 | iSize( 0 ), | ||
| 52 | iCapacity( 0 ) | ||
| 53 | { | 138 | { |
| 54 | setCapacity( iSetCap ); | 139 | setCapacity( iSetCap ); |
| 55 | } | 140 | } |
| 56 | 141 | ||
| 57 | ~Array() | 142 | ~Array() |
| 58 | { | 143 | { |
| 59 | clear(); | ||
| 60 | } | 144 | } |
| 61 | 145 | ||
| 62 | MyType &operator=( const MyType &src ) | 146 | bool operator==( const MyType &src ) const |
| 63 | { | 147 | { |
| 64 | clear(); | 148 | if( core == src.core ) |
| 65 | setCapacity( src.iCapacity ); | 149 | return true; |
| 150 | if( core->iSize != src.core->iSize ) | ||
| 151 | return false; | ||
| 66 | 152 | ||
| 67 | long iTop = src.getSize(); | 153 | for( int j = 0; j < core->iSize; j++ ) |
| 68 | for( long i = 0; i < iTop; ++i ) | ||
| 69 | { | 154 | { |
| 70 | append( src[i] ); | 155 | if( core->pData[j] != src.core->pData[j] ) |
| 156 | return false; | ||
| 71 | } | 157 | } |
| 72 | return *this; | 158 | return true; |
| 159 | } | ||
| 160 | |||
| 161 | bool operator!=( const MyType &src ) const | ||
| 162 | { | ||
| 163 | return !(*this == src); | ||
| 73 | } | 164 | } |
| 74 | 165 | ||
| 75 | /** | 166 | /** |
| @@ -77,46 +168,61 @@ namespace Bu | |||
| 77 | */ | 168 | */ |
| 78 | void clear() | 169 | void clear() |
| 79 | { | 170 | { |
| 80 | if( pData ) | 171 | _hardCopy(); |
| 81 | { | 172 | core->clear(); |
| 82 | for( int j = 0; j < iSize; j++ ) | ||
| 83 | { | ||
| 84 | va.destroy( &pData[j] ); | ||
| 85 | } | ||
| 86 | va.deallocate( pData, iCapacity ); | ||
| 87 | pData = NULL; | ||
| 88 | } | ||
| 89 | iSize = 0; | ||
| 90 | iCapacity = 0; | ||
| 91 | } | 173 | } |
| 92 | 174 | ||
| 93 | void append( const value &rVal ) | 175 | void append( const value &rVal ) |
| 94 | { | 176 | { |
| 95 | if( iSize == iCapacity ) | 177 | _hardCopy(); |
| 178 | if( core->iSize == core->iCapacity ) | ||
| 96 | { | 179 | { |
| 97 | setCapacity( iCapacity + inc ); | 180 | core->setCapacity( core->iCapacity + inc ); |
| 98 | } | 181 | } |
| 99 | 182 | ||
| 100 | va.construct( &pData[iSize++], rVal ); | 183 | core->va.construct( &core->pData[core->iSize++], rVal ); |
| 101 | } | 184 | } |
| 102 | 185 | ||
| 103 | //operator | 186 | //operator |
| 104 | value &operator[]( long iIndex ) | 187 | value &operator[]( long iIndex ) |
| 105 | { | 188 | { |
| 106 | if( iIndex < 0 || iIndex >= iSize ) | 189 | _hardCopy(); |
| 190 | if( iIndex < 0 || iIndex >= core->iSize ) | ||
| 107 | throw ArrayException( | 191 | throw ArrayException( |
| 108 | "Index %d out of range 0:%d", iIndex, iSize ); | 192 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
| 109 | 193 | ||
| 110 | return pData[iIndex]; | 194 | return core->pData[iIndex]; |
| 111 | } | 195 | } |
| 112 | 196 | ||
| 113 | const value &operator[]( long iIndex ) const | 197 | const value &operator[]( long iIndex ) const |
| 114 | { | 198 | { |
| 115 | if( iIndex < 0 || iIndex >= iSize ) | 199 | if( iIndex < 0 || iIndex >= core->iSize ) |
| 116 | throw ArrayException( | 200 | throw ArrayException( |
| 117 | "Index %d out of range 0:%d", iIndex, iSize ); | 201 | "Index %d out of range 0:%d", iIndex, core->iSize ); |
| 202 | |||
| 203 | return core->pData[iIndex]; | ||
| 204 | } | ||
| 205 | |||
| 206 | value &first() | ||
| 207 | { | ||
| 208 | _hardCopy(); | ||
| 209 | return core->pData[0]; | ||
| 210 | } | ||
| 211 | |||
| 212 | const value &first() const | ||
| 213 | { | ||
| 214 | return core->pData[0]; | ||
| 215 | } | ||
| 216 | |||
| 217 | value &last() | ||
| 218 | { | ||
| 219 | _hardCopy(); | ||
| 220 | return core->pData[core->iSize-1]; | ||
| 221 | } | ||
| 118 | 222 | ||
| 119 | return pData[iIndex]; | 223 | const value &last() const |
| 224 | { | ||
| 225 | return core->pData[core->iSize-1]; | ||
| 120 | } | 226 | } |
| 121 | 227 | ||
| 122 | /** | 228 | /** |
| @@ -125,7 +231,7 @@ namespace Bu | |||
| 125 | */ | 231 | */ |
| 126 | long getSize() const | 232 | long getSize() const |
| 127 | { | 233 | { |
| 128 | return iSize; | 234 | return core->iSize; |
| 129 | } | 235 | } |
| 130 | 236 | ||
| 131 | /** | 237 | /** |
| @@ -136,7 +242,7 @@ namespace Bu | |||
| 136 | */ | 242 | */ |
| 137 | long getCapacity() const | 243 | long getCapacity() const |
| 138 | { | 244 | { |
| 139 | return iCapacity; | 245 | return core->iCapacity; |
| 140 | } | 246 | } |
| 141 | 247 | ||
| 142 | /** | 248 | /** |
| @@ -149,19 +255,8 @@ namespace Bu | |||
| 149 | */ | 255 | */ |
| 150 | void setCapacity( long iNewLen ) | 256 | void setCapacity( long iNewLen ) |
| 151 | { | 257 | { |
| 152 | if( iNewLen <= iCapacity ) return; | 258 | _hardCopy(); |
| 153 | value *pNewData = va.allocate( iNewLen ); | 259 | core->setCapacity( iNewLen ); |
| 154 | if( pData ) | ||
| 155 | { | ||
| 156 | for( int j = 0; j < iSize; j++ ) | ||
| 157 | { | ||
| 158 | va.construct( &pNewData[j], pData[j] ); | ||
| 159 | va.destroy( &pData[j] ); | ||
| 160 | } | ||
| 161 | va.deallocate( pData, iCapacity ); | ||
| 162 | } | ||
| 163 | pData = pNewData; | ||
| 164 | iCapacity = iNewLen; | ||
| 165 | } | 260 | } |
| 166 | 261 | ||
| 167 | typedef struct iterator | 262 | typedef struct iterator |
| @@ -387,16 +482,8 @@ namespace Bu | |||
| 387 | */ | 482 | */ |
| 388 | void erase( iterator i ) | 483 | void erase( iterator i ) |
| 389 | { | 484 | { |
| 390 | for( int j = i.iPos; j < iSize; j++ ) | 485 | _hardCopy(); |
| 391 | { | 486 | core->erase( i.iPos ); |
| 392 | va.destroy( &pData[j] ); | ||
| 393 | if( j == iSize-1 ) | ||
| 394 | { | ||
| 395 | iSize--; | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | va.construct( &pData[j], pData[j+1] ); | ||
| 399 | } | ||
| 400 | } | 487 | } |
| 401 | 488 | ||
| 402 | /** | 489 | /** |
| @@ -408,22 +495,24 @@ namespace Bu | |||
| 408 | */ | 495 | */ |
| 409 | void swapErase( iterator i ) | 496 | void swapErase( iterator i ) |
| 410 | { | 497 | { |
| 411 | if( i.iPos == iSize-1 ) | 498 | _hardCopy(); |
| 412 | { | 499 | swapErase( i.iPos ); |
| 413 | erase( i ); | 500 | } |
| 414 | return; | 501 | |
| 502 | protected: | ||
| 503 | virtual Core *_copyCore( Core *src ) | ||
| 504 | { | ||
| 505 | Core *pRet = _allocateCore(); | ||
| 506 | pRet->setCapacity( src->iCapacity ); | ||
| 507 | pRet->iSize = src->iSize; | ||
| 508 | for( int j = 0; j < src->iSize; j++ ) | ||
| 509 | { | ||
| 510 | pRet->va.construct( &pRet->pData[j], src->pData[j] ); | ||
| 415 | } | 511 | } |
| 416 | va.destroy( &pData[i.iPos] ); | 512 | return pRet; |
| 417 | va.construct( &pData[i.iPos], pData[iSize-1] ); | ||
| 418 | va.destroy( &pData[iSize-1] ); | ||
| 419 | iSize--; | ||
| 420 | } | 513 | } |
| 421 | 514 | ||
| 422 | private: | 515 | private: |
| 423 | valuealloc va; | ||
| 424 | value *pData; | ||
| 425 | long iSize; | ||
| 426 | long iCapacity; | ||
| 427 | }; | 516 | }; |
| 428 | 517 | ||
| 429 | class Formatter; | 518 | class Formatter; |
