karrayul.h

Go to the documentation of this file.
00001 
00004 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KARRAYUL_H
00005 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KARRAYUL_H
00006 
00007 /**************************************************************************************
00008 
00009  Copyright (C) 1994 - 2010 Autodesk, Inc. and/or its licensors.
00010  All Rights Reserved.
00011 
00012  The coded instructions, statements, computer programs, and/or related material 
00013  (collectively the "Data") in these files contain unpublished information 
00014  proprietary to Autodesk, Inc. and/or its licensors, which is protected by 
00015  Canada and United States of America federal copyright law and by international 
00016  treaties. 
00017  
00018  The Data may not be disclosed or distributed to third parties, in whole or in
00019  part, without the prior written consent of Autodesk, Inc. ("Autodesk").
00020 
00021  THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY.
00022  ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED. AUTODESK MAKES NO
00023  WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING
00024  BY CUSTOM OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, 
00025  NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR USE. 
00026  WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT THE OPERATION
00027  OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE. 
00028  
00029  IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS
00030  OR SUPPLIERS ("AUTODESK GROUP") BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES
00031  OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR MULTIPLE DAMAGES OR OTHER
00032  SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE
00033  OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND),
00034  HOWEVER CAUSED, AND REGARDLESS OF THE THEORY OF LIABILITY, WHETHER DERIVED
00035  FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE), OR OTHERWISE,
00036  ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE,
00037  WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS
00038  OR DAMAGE. 
00039 
00040 **************************************************************************************/
00041 #include <fbxfilesdk/fbxfilesdk_def.h>
00042 
00043 #include <fbxfilesdk/components/kbaselib/klib/kdebug.h>
00044 
00045 #define KFBX_ARRAYUL_BLOCKSIZE 4
00046 
00047 #include <fbxfilesdk/fbxfilesdk_nsbegin.h> // namespace
00048 
00049     /***********************************************************************
00050         CLASS KStaticArray
00051     ************************************************************************/
00052     template< class Type > class KBaseStaticArray
00053     {
00054         protected:
00055         int  mCount;
00056         Type *mArrayBuf;
00057 
00058         public:
00059         inline int GetCount() { return mCount; }
00060 
00062         inline Type &operator[](int pIndex)
00063         {
00064         #ifdef KFBX_PRIVATE
00065             K_ASSERT_MSG( pIndex >= 0   , "Buffer underflow");
00066             K_ASSERT_MSG( pIndex < mCount,"Buffer overflow.");
00067         #endif
00068             return mArrayBuf[pIndex];
00069         }
00070     };
00071 
00072     // Static Array
00073     template< class Type, int Count > class KStaticArray : public KBaseStaticArray<Type>
00074     {
00075         public:
00076         Type mArray[Count];
00077             inline KStaticArray(){ this->mArrayBuf = mArray; this->mCount = Count;}
00078     };
00079 
00080     template< class Type, int Count1, int Count2 > class KStaticArray2d
00081     {
00082         public:
00083             KStaticArray<Type,Count2> mArray[Count1];
00084 
00085             // Access pointer at given index.
00086             inline KStaticArray< Type, Count2 > &operator[](int pIndex)
00087             {
00088             #ifdef KFBX_PRIVATE
00089                 K_ASSERT_MSG( pIndex >= 0   , "Buffer underflow.");
00090                 K_ASSERT_MSG( pIndex < Count1,"Buffer overflow.");
00091             #endif
00092                 return mArray[pIndex];
00093             }
00094     };
00095 
00096     /***********************************************************************
00097         CLASS KArrayTemplate
00098     ************************************************************************/
00099     class  KBaseArraySize {
00100         public:
00101             KBaseArraySize( int pItemSize)
00102                 : mItemSize(pItemSize)
00103             {
00104             }
00105             inline int GetTypeSize() const { return mItemSize; }
00106         private:
00107             int mItemSize;
00108     };
00109 
00110     // Helpers
00111     KFBX_DLL void KBaseArrayFree(char*);
00112     KFBX_DLL char* KBaseArrayRealloc(char*, size_t);
00113     
00115     //
00116     //  WARNING!
00117     //
00118     //  Anything beyond these lines may not be documented accurately and is
00119     //  subject to change without notice.
00120     //
00122     #ifndef DOXYGEN_SHOULD_SKIP_THIS
00123         KFBX_DLL void* KBaseArrayGetAlloc();
00124     #endif
00125 
00129     template <class TypeSize>
00130     class KBaseArray
00131     {
00133     //
00134     //  WARNING!
00135     //
00136     //  Anything beyond these lines may not be documented accurately and is
00137     //  subject to change without notice.
00138     //
00140     #ifndef DOXYGEN_SHOULD_SKIP_THIS
00141     
00142     protected:
00143         struct KHeader
00144         {
00145             int mArrayCount;
00146             int mBlockCount;
00147         };
00148 
00152         inline KBaseArray(TypeSize pTypeSize)
00153             : mTypeSize(pTypeSize)
00154         {
00155             mBaseArray  = NULL;
00156         }
00157 
00159         inline ~KBaseArray()
00160         {
00161             Clear();
00162         }
00163 
00164         inline int GetTypeSize() const { return mTypeSize.GetTypeSize(); }
00165 
00169         inline int GetCount() const { return GetArrayCount(); }
00170 
00174         inline void Clear()
00175         {
00176             if (mBaseArray!=NULL)
00177             {
00178                 KBaseArrayFree(mBaseArray);
00179                 mBaseArray = NULL;
00180             }
00181         }
00182 
00186         inline void Empty()
00187         {
00188             #ifdef KFBX_PRIVATE
00189             #ifdef _DEBUG
00190                 memset(mBaseArray+ GetHeaderOffset(), 0, GetArrayCount()*GetTypeSize());
00191             #endif
00192             #endif
00193 
00194             SetArrayCount(0);
00195         }
00196 
00202         inline int Reserve(int pCapacity)
00203         {
00204             #ifdef KFBX_PRIVATE
00205                 K_ASSERT( pCapacity > 0 );
00206             #endif
00207 
00208             if( pCapacity )
00209             {
00210                 const kUInt lTempNewBlockCount = ( (kUInt) (pCapacity + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00211                 const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00212 
00213                 int         lArrayCount   = GetArrayCount();
00214                 int         lBlockCount   = GetBlockCount();
00215 
00216                 const kUInt lOldArraySize = lArrayCount*GetTypeSize();
00217                 const kUInt lNewArraySize = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*GetTypeSize();
00218 
00219                 if (lNewBlockCount != (kUInt) lBlockCount)
00220                 {
00221                     char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00222                     if (!lBaseArray)
00223                         return GetBlockCount()*KFBX_ARRAYUL_BLOCKSIZE;
00224                     mBaseArray = lBaseArray;
00225                 }
00226 
00227                 if( lNewBlockCount > (kUInt) lBlockCount ) {
00228                     memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00229                     SetArrayCount(lArrayCount);
00230                 } else if (pCapacity < lArrayCount)
00231                 {
00232                     memset( ((char*)mBaseArray+ GetHeaderOffset() ) + pCapacity*GetTypeSize(), 0, (size_t) (lNewArraySize-pCapacity*GetTypeSize()) );
00233                     SetArrayCount(pCapacity);
00234                 }
00235 
00236                 SetBlockCount(lNewBlockCount);
00237             }
00238 
00239             return GetBlockCount()*KFBX_ARRAYUL_BLOCKSIZE;
00240         }
00241 
00248         inline void SetCount(int pCount)
00249         {
00250         #ifdef KFBX_PRIVATE
00251         #ifdef _DEBUG
00252             if (pCount<0)
00253             {
00254                 K_ASSERT_MSG_NOW (_T("ArrayUL : Item count can't be negative"));
00255                 return ;
00256             }
00257         #endif
00258         #endif
00259             int lArrayCount = GetArrayCount();
00260             if (pCount > lArrayCount)
00261             {
00262                 AddMultiple( pCount-lArrayCount);
00263             } else
00264             {
00265                 SetArrayCount(pCount);
00266             }
00267         }
00268 
00275         inline void Resize(int pItemCount)
00276         {
00277             #ifdef KFBX_PRIVATE
00278                 K_ASSERT( pItemCount >= 0 );
00279             #endif
00280 
00281             const kUInt lTempNewBlockCount = ( (kUInt) (pItemCount + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00282             const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00283 
00284             int         lArrayCount     = GetArrayCount();
00285             int         lBlockCount   = GetBlockCount();
00286 
00287             const kUInt lOldArraySize   = lArrayCount*GetTypeSize();
00288             const kUInt lNewArraySize   = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*GetTypeSize();
00289 
00290             if (lNewBlockCount != (kUInt) lBlockCount)
00291             {
00292                 char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00293                 if (!lBaseArray)
00294                     return;
00295                 mBaseArray = lBaseArray;
00296             }
00297 
00298             if( lNewBlockCount > (kUInt) lBlockCount )
00299                 memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00300             else if (pItemCount < lArrayCount)
00301                 memset( ((char*)mBaseArray+ GetHeaderOffset() ) + pItemCount*GetTypeSize(), 0, (size_t) (lNewArraySize-pItemCount*GetTypeSize()) );
00302 
00303             SetBlockCount(lNewBlockCount);
00304             SetArrayCount(pItemCount);
00305         }
00306 
00313         inline void AddMultiple(int pItemCount)
00314         {
00315             #ifdef KFBX_PRIVATE
00316                 K_ASSERT( pItemCount > 0 );
00317             #endif
00318 
00319             if( pItemCount )
00320             {
00321                 int         lArrayCount = GetArrayCount();
00322                 int         lBlockCount = GetBlockCount();
00323                 const kUInt lTempNewBlockCount = ( (kUInt) (lArrayCount+pItemCount + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00324                 const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00325 
00326                 const kUInt lOldArraySize = lArrayCount*GetTypeSize();
00327                 const kUInt lNewArraySize = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*GetTypeSize();
00328 
00329                 #ifdef KFBX_PRIVATE
00330                     K_ASSERT( lOldArraySize < lNewArraySize );
00331                 #endif
00332 
00333                 if( lNewBlockCount > (kUInt) lBlockCount )
00334                 {
00335                     char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00336                     if (!lBaseArray)
00337                         return;
00338                     mBaseArray = lBaseArray;
00339                     lBlockCount = lNewBlockCount;
00340                 }
00341 
00342                 memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00343                 SetArrayCount ( lArrayCount + pItemCount );
00344                 SetBlockCount (lBlockCount);
00345             }
00346         }
00347 
00355         inline int InsertAt(int pIndex, void *pItem)
00356         {
00357           int lArrayCount = GetArrayCount();
00358           int lBlockCount = GetBlockCount();
00359 
00360             #ifdef KFBX_PRIVATE
00361                 K_ASSERT( pIndex >= 0 );
00362             #endif
00363 
00364             if (pIndex>lArrayCount) {
00365                 pIndex = GetArrayCount();
00366             }
00367 
00368             if (lArrayCount>= lBlockCount*KFBX_ARRAYUL_BLOCKSIZE)
00369             {
00370                 // must Alloc.Realloc some new space
00371 
00372                 // double the number of blocks.
00373                 lBlockCount = ( 0 == lBlockCount ) ? 1 : lBlockCount * 2;
00374                 char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) (lBlockCount*KFBX_ARRAYUL_BLOCKSIZE*GetTypeSize()) + GetHeaderOffset() );
00375                 if(!lBaseArray)
00376                     return -1;
00377                 mBaseArray = lBaseArray;
00378             }
00379 
00380             if (pIndex<lArrayCount)
00381             {
00382                 // This is an insert
00383                 memmove (&(mBaseArray[(pIndex+1)*GetTypeSize()+ GetHeaderOffset() ]), &(mBaseArray[(pIndex)*GetTypeSize()+ GetHeaderOffset()] ), GetTypeSize()*(lArrayCount-pIndex));
00384             }
00385 
00386             memmove (&(mBaseArray[(pIndex)*GetTypeSize()+ GetHeaderOffset() ]), pItem, GetTypeSize());
00387 
00388             SetArrayCount(lArrayCount+1);
00389             SetBlockCount(lBlockCount);
00390 
00391             return pIndex;
00392         }
00393 
00394 
00401         inline void* GetAt(int pIndex) { return &(mBaseArray[(pIndex)*GetTypeSize()+ GetHeaderOffset() ]); }
00402 
00409         inline void RemoveAt(int pIndex)
00410         {
00411         #if defined(_DEBUG) && !defined(KARCH_ENV_MACOSX)
00412             if (!ValidateIndex( pIndex ))
00413             {
00414                 return;
00415             }
00416         #endif
00417             int lArrayCount = GetArrayCount();
00418             if (pIndex+1<lArrayCount)
00419             {
00420                 memmove (&(mBaseArray[(pIndex)*GetTypeSize()+ GetHeaderOffset() ]), &(mBaseArray[(pIndex+1)*GetTypeSize()+ GetHeaderOffset() ]), GetTypeSize()*(lArrayCount-pIndex-1));
00421             }
00422 
00423             SetArrayCount( lArrayCount-1 );
00424 
00425         #ifdef _DEBUG
00426             memset( &(mBaseArray[(GetArrayCount())*GetTypeSize()+ GetHeaderOffset() ]),0,GetTypeSize());
00427         #endif
00428         }
00429 
00435         inline bool ValidateIndex( int pIndex ) const
00436         {
00437             int lArrayCount = GetArrayCount();
00438             if (pIndex>=0 && pIndex<lArrayCount)
00439             {
00440                 return true;
00441             }
00442             else
00443             {
00444                 #ifdef KFBX_PRIVATE
00445                     K_ASSERT_MSG_NOW(_T("ArrayTemplate : Index out of range"));
00446                 #endif
00447                 return false;
00448             }
00449         }
00450 
00451         inline const KHeader* GetHeader() const
00452         {
00453             return (const KHeader *)mBaseArray;
00454         }
00455         inline KHeader* GetHeader()
00456         {
00457             return (KHeader*)mBaseArray;
00458         }
00459         inline int GetHeaderOffset() const
00460         {
00461             return sizeof(KHeader);
00462         }
00463         inline int GetArrayCount() const
00464         {
00465             return GetHeader() ? GetHeader()->mArrayCount : 0;
00466         }
00467         inline void SetArrayCount(int pArrayCount)
00468         {
00469             if (GetHeader()) GetHeader()->mArrayCount = pArrayCount;
00470         }
00471         inline int GetBlockCount() const
00472         {
00473             return GetHeader() ? GetHeader()->mBlockCount : 0;
00474         }
00475         inline void SetBlockCount(int pArrayCount)
00476         {
00477             if (GetHeader()) GetHeader()->mBlockCount=pArrayCount;
00478         }
00479 
00480         char*           mBaseArray;
00481         TypeSize        mTypeSize;
00482 
00483     #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
00484     };
00485 
00490     template <size_t TypeSize> class  KBaseArrayFast
00491     {
00492         public:
00496             inline int GetCount() const { return GetArrayCount(); }
00497 
00499             inline void Clear()
00500             {
00501                 if (mBaseArray!=NULL)
00502                 {
00503                     KBaseArrayFree(mBaseArray);
00504                     mArrayCount = 0;
00505                     mBaseArray = NULL;
00506                 }
00507             }
00508 
00509 
00511             inline void Empty()
00512             {
00513                 #ifdef KFBX_PRIVATE
00514                 #ifdef _DEBUG
00515                     memset( mBaseArray+ GetHeaderOffset() ,0,GetArrayCount()*TypeSize);
00516                 #endif
00517             #endif
00518                 SetArrayCount(0);
00519             }
00520 
00521 
00527             inline int      Reserve(int pCapacity)
00528             {
00529                 #ifdef KFBX_PRIVATE
00530                     K_ASSERT( pCapacity > 0 );
00531                 #endif
00532 
00533                 if( pCapacity )
00534                 {
00535                     const kUInt lTempNewBlockCount = ( (kUInt) (pCapacity + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00536                     const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00537 
00538                     int         lArrayCount   = GetArrayCount();
00539                     int         lBlockCount   = GetBlockCount();
00540 
00541                     const kUInt lOldArraySize = lArrayCount*TypeSize;
00542                     const kUInt lNewArraySize = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*TypeSize;
00543 
00544                     if (lNewBlockCount != (kUInt) lBlockCount)
00545                     {
00546                         char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00547                         if (!lBaseArray)
00548                             return GetBlockCount()*KFBX_ARRAYUL_BLOCKSIZE;
00549                         mBaseArray = lBaseArray;
00550                     }
00551 
00552                     if( lNewBlockCount > (kUInt) lBlockCount ) {
00553                         memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00554                         SetArrayCount(lArrayCount);
00555                     } else if (pCapacity < lArrayCount)
00556                     {
00557                         memset( ((char*)mBaseArray+ GetHeaderOffset() ) + pCapacity*TypeSize, 0, (size_t) (lNewArraySize-pCapacity*TypeSize) );
00558                         SetArrayCount(pCapacity);
00559                     }
00560 
00561                     SetBlockCount(lNewBlockCount);
00562                 }
00563 
00564                 return GetBlockCount()*KFBX_ARRAYUL_BLOCKSIZE;
00565             }
00566 
00567 
00569             //  Differ from SetCount because array capacity can be lowered.
00570 
00576             inline void     SetCount (int pCount)
00577             {
00578             #ifdef KFBX_PRIVATE
00579             #ifdef _DEBUG
00580                 if (pCount<0)
00581                 {
00582                     K_ASSERT_MSG_NOW (_T("ArrayUL : Item count can't be negative"));
00583                     return ;
00584                 }
00585             #endif
00586             #endif
00587                 int lArrayCount = GetArrayCount();
00588                 if (pCount > lArrayCount)
00589                 {
00590                     AddMultiple( pCount-lArrayCount);
00591                 } else
00592                 {
00593                     SetArrayCount(pCount);
00594                 }
00595             }
00596 
00597             inline void     Resize(int pItemCount)
00598             {
00599                 #ifdef KFBX_PRIVATE
00600                     K_ASSERT( pItemCount >= 0 );
00601                 #endif
00602 
00603                 const kUInt lTempNewBlockCount = ( (kUInt) (pItemCount + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00604                 const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00605 
00606                 int         lArrayCount     = GetArrayCount();
00607                 int         lBlockCount   = GetBlockCount();
00608 
00609                 const kUInt lOldArraySize   = lArrayCount*TypeSize;
00610                 const kUInt lNewArraySize   = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*TypeSize;
00611 
00612                 if (lNewBlockCount != (kUInt) lBlockCount)
00613                 {
00614                     char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00615                     if (!lBaseArray)
00616                         return;
00617                     mBaseArray = lBaseArray;
00618                 }
00619 
00620                 if( lNewBlockCount > (kUInt) lBlockCount )
00621                     memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00622                 else if (pItemCount < lArrayCount)
00623                     memset( ((char*)mBaseArray+ GetHeaderOffset() ) + pItemCount*TypeSize, 0, (size_t) (lNewArraySize-pItemCount*TypeSize) );
00624 
00625                 SetBlockCount(lNewBlockCount);
00626                 SetArrayCount(pItemCount);
00627             }
00628 
00629             inline void     AddMultiple(int pItemCount)
00630             {
00631                 #ifdef KFBX_PRIVATE
00632                     K_ASSERT( pItemCount > 0 );
00633                 #endif
00634 
00635                 if( pItemCount )
00636                 {
00637                     int         lArrayCount = GetArrayCount();
00638                     int         lBlockCount = GetBlockCount();
00639                     const kUInt lTempNewBlockCount = ( (kUInt) (lArrayCount+pItemCount + KFBX_ARRAYUL_BLOCKSIZE - 1 ) / KFBX_ARRAYUL_BLOCKSIZE );
00640                     const kUInt lNewBlockCount = (lTempNewBlockCount > 1 ? lTempNewBlockCount : 1);
00641 
00642                     const kUInt lOldArraySize = lArrayCount*TypeSize;
00643                     const kUInt lNewArraySize = lNewBlockCount*KFBX_ARRAYUL_BLOCKSIZE*TypeSize;
00644 
00645                     #ifdef KFBX_PRIVATE
00646                         K_ASSERT( lOldArraySize < lNewArraySize );
00647                     #endif
00648 
00649                     if( lNewBlockCount > (kUInt) lBlockCount )
00650                     {
00651                         char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) lNewArraySize+ GetHeaderOffset()  );
00652                         if (!lBaseArray)
00653                             return;
00654                         mBaseArray = lBaseArray;
00655                         lBlockCount = lNewBlockCount;
00656                     }
00657 
00658                     memset( ((char*)mBaseArray+ GetHeaderOffset() ) + lOldArraySize, 0, (size_t) (lNewArraySize-lOldArraySize) );
00659                     SetArrayCount ( lArrayCount + pItemCount );
00660                     SetBlockCount (lBlockCount);
00661                 }
00662             }
00663 
00665         //
00666         //  WARNING!
00667         //
00668         //  Anything beyond these lines may not be documented accurately and is
00669         //  subject to change without notice.
00670         //
00672         #ifndef DOXYGEN_SHOULD_SKIP_THIS
00673 
00674         
00675         protected:
00676             struct KHeader {
00677                 int mBlockCount;
00678             };
00679 
00680 
00681         protected:
00683             inline KBaseArrayFast()
00684                 :mArrayCount(0), mBaseArray(NULL)
00685             {
00686             }
00687 
00688 
00690             inline ~KBaseArrayFast(){
00691                 Clear ();
00692             }
00693 
00701             inline int      InsertAt(int pIndex, void *pItem)
00702             {
00703               int lArrayCount = GetArrayCount();
00704               int lBlockCount = GetBlockCount();
00705 
00706                 #ifdef KFBX_PRIVATE
00707                     K_ASSERT( pIndex >= 0 );
00708                 #endif
00709 
00710                 if (pIndex>lArrayCount) {
00711                     pIndex = GetArrayCount();
00712                 }
00713 
00714                 if (lArrayCount>= lBlockCount*KFBX_ARRAYUL_BLOCKSIZE)
00715                 {
00716                     // must Alloc.Realloc some new space
00717 
00718                     // double the number of blocks.
00719                     lBlockCount = ( 0 == lBlockCount ) ? 1 : lBlockCount * 2;
00720                     char* lBaseArray = KBaseArrayRealloc(mBaseArray, (size_t) (lBlockCount*KFBX_ARRAYUL_BLOCKSIZE*TypeSize) + GetHeaderOffset() );
00721                     if(!lBaseArray)
00722                         return -1;
00723                     mBaseArray = lBaseArray;
00724                 }
00725 
00726                 if (pIndex<lArrayCount)
00727                 {
00728                     // This is an insert
00729                     memmove (&(mBaseArray[(pIndex+1)*TypeSize+ GetHeaderOffset() ]), &(mBaseArray[(pIndex)*TypeSize+ GetHeaderOffset()] ), TypeSize*(lArrayCount-pIndex));
00730                 }
00731 
00732                 memmove (&(mBaseArray[(pIndex)*TypeSize+ GetHeaderOffset() ]), pItem, TypeSize);
00733 
00734                 SetArrayCount(lArrayCount+1);
00735                 SetBlockCount(lBlockCount);
00736 
00737                 return pIndex;
00738             }
00739 
00740 
00747             inline void*    GetAt(int pIndex)                           { return &(mBaseArray[(pIndex)*TypeSize+ GetHeaderOffset() ]); }
00748 
00755             inline void RemoveAt(int pIndex)
00756             {
00757 
00758             #if defined(_DEBUG) && !defined(KARCH_ENV_MACOSX)
00759                 if (!ValidateIndex( pIndex ))
00760                 {
00761                     return;
00762                 }
00763             #endif
00764                 int lArrayCount = GetArrayCount();
00765                 if (pIndex+1<lArrayCount)
00766                 {
00767                     memmove (&(mBaseArray[(pIndex)*TypeSize+ GetHeaderOffset() ]), &(mBaseArray[(pIndex+1)*TypeSize+ GetHeaderOffset() ]), TypeSize*(lArrayCount-pIndex-1));
00768                 }
00769 
00770                 SetArrayCount( lArrayCount-1 );
00771 
00772             #ifdef _DEBUG
00773                 memset( &(mBaseArray[(GetArrayCount())*TypeSize+ GetHeaderOffset() ]),0,TypeSize);
00774             #endif
00775             }
00776 
00777 
00783             inline bool ValidateIndex( int pIndex ) const
00784             {
00785                 int lArrayCount = GetArrayCount();
00786                 if (pIndex>=0 && pIndex<lArrayCount)
00787                 {
00788                     return true;
00789                 } else
00790                 {
00791                     #ifdef KFBX_PRIVATE
00792                         K_ASSERT_MSG_NOW(_T("ArrayTemplate : Index out of range"));
00793                     #endif
00794                     return false;
00795                 }
00796             }
00797 
00798         protected:
00799             inline KHeader* const   GetHeader() const
00800             {
00801                 return (KHeader* const)mBaseArray;
00802             }
00803             inline KHeader*     GetHeader()
00804             {
00805                 return (KHeader*)mBaseArray;
00806             }
00807             inline int GetHeaderOffset() const
00808             {
00809                 return sizeof(KHeader);
00810             }
00811             inline int GetArrayCount() const
00812             {
00813                 return mArrayCount;
00814             }
00815             inline void SetArrayCount(int pArrayCount)
00816             {
00817                 mArrayCount = pArrayCount;
00818             }
00819             inline int GetBlockCount() const
00820             {
00821                 return GetHeader() ? GetHeader()->mBlockCount : 0;
00822             }
00823             inline void SetBlockCount(int pArrayCount)
00824             {
00825                 if (GetHeader()) GetHeader()->mBlockCount = pArrayCount;
00826             }
00827 
00828         protected:
00829             int             mArrayCount;
00830             char*           mBaseArray;
00831 
00832         #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
00833     };
00834 
00838     template < class Type >
00839     class KArrayTemplate : public KBaseArrayFast< sizeof(Type) >
00840     {
00841         typedef KBaseArrayFast< sizeof(Type) > ParentClass;
00842 
00843 #ifdef _MSC_VER
00844         // Previously class KArrayTemplate is for pointers. Somehow, it's used to store other types.
00845         // Here's a compile-time checking for known incompatible classes.
00846         // If it happens you find new incompatible ones, declare them with macro KFBX_INCOMPATIBLE_WITH_KARRAYTEMPLATE
00847         // Also see file string.h
00848         K_STATIC_ASSERT(
00849             KFBX_IS_SIMPLE_TYPE(Type)
00850             || __is_enum(Type)
00851             || (__has_trivial_constructor(Type)&&__has_trivial_destructor(Type))
00852             || !KFBX_IS_INCOMPATIBLE_WITH_KARRAYTEMPLATE(Type)
00853         );
00854 #endif
00855 
00856     public:
00858         inline KArrayTemplate()
00859             : ParentClass ()
00860         {
00861         }
00862 
00864         inline KArrayTemplate(const KArrayTemplate& pArrayTemplate)
00865             : ParentClass ()
00866         {
00867             *this = pArrayTemplate;
00868         }
00869 
00871         inline ~KArrayTemplate() {}
00872 
00879         inline int InsertAt(int pIndex, Type pItem)
00880         {
00881             return ParentClass::InsertAt( pIndex,&pItem );
00882         }
00883 
00889         inline Type RemoveAt(int pIndex)
00890         {
00891             Type tmpItem = GetAt(pIndex);
00892             ParentClass::RemoveAt( pIndex );
00893             return tmpItem;
00894         }
00895 
00900         inline Type RemoveLast()
00901         {
00902             return RemoveAt(ParentClass::GetArrayCount()-1);
00903         }
00904 
00909         inline bool RemoveIt(Type pItem)
00910         {
00911             int Index = Find (pItem);
00912             if (Index>=0)
00913             {
00914                 RemoveAt (Index);
00915                 return true;
00916             }
00917             return false;
00918         }
00919 
00925         inline Type &operator[](int pIndex) const
00926         {
00927         #if defined(_DEBUG) && !defined(KARCH_ENV_MACOSX)
00928             if (!ParentClass::ValidateIndex( pIndex ))
00929             {
00930                 return (Type &)(ParentClass::mBaseArray[(0)*sizeof(Type)+ ParentClass::GetHeaderOffset() ]);
00931             }
00932         #endif
00933             return (Type &)(ParentClass::mBaseArray[(pIndex)*sizeof(Type)+ ParentClass::GetHeaderOffset() ]);
00934         }
00935 
00941         inline void SetAt(int pIndex, Type pItem)
00942         {
00943         #if defined(_DEBUG) && !defined(KARCH_ENV_MACOSX)
00944             if (!ParentClass::ValidateIndex( pIndex ))
00945             {
00946                 return;
00947             }
00948         #endif
00949             GetArray()[pIndex] = pItem;
00950         }
00951 
00956         inline void SetLast(Type pItem)
00957         {
00958             SetAt (ParentClass::GetArrayCount()-1, pItem);
00959         }
00960 
00966         inline Type GetAt(int pIndex) const
00967         {
00968         #if defined(_DEBUG) && !defined(KARCH_ENV_MACOSX)
00969             if (!ParentClass::ValidateIndex( pIndex ))
00970             {
00971                 return (Type &)(ParentClass::mBaseArray[(0)*sizeof(Type)+ ParentClass::GetHeaderOffset() ]);
00972             }
00973         #endif
00974             return (Type &)(ParentClass::mBaseArray[(pIndex)*sizeof(Type)+ ParentClass::GetHeaderOffset() ]);
00975         }
00976 
00981         inline Type GetFirst() const
00982         {
00983         #ifdef KFBX_PRIVATE
00984             K_ASSERT( ParentClass::GetArrayCount() >= 1 );
00985         #endif
00986             return GetAt(0);
00987         }
00988 
00993         inline Type GetLast() const
00994         {
00995         #ifdef KFBX_PRIVATE
00996             K_ASSERT( ParentClass::GetArrayCount() >= 1 );
00997         #endif
00998             return GetAt(ParentClass::GetArrayCount()-1);
00999         }
01000 
01005         inline int Find(Type pItem) const
01006         {
01007             return FindAfter( -1, pItem );
01008         }
01009 
01016         inline int FindAfter(int pAfterIndex, Type pItem) const
01017         {
01018         #ifdef KFBX_PRIVATE
01019         #ifdef _DEBUG
01020             if ( pAfterIndex > ParentClass::GetArrayCount() || pAfterIndex < -1 )
01021             {
01022                 K_ASSERT_MSG_NOW (_T("ArrayUL : Search Begin Index out of range"));
01023                 return -1;
01024             }
01025         #endif
01026         #endif
01027             int Count;
01028             for ( Count=pAfterIndex+1; Count<ParentClass::GetArrayCount(); Count++)
01029             {
01030                 if (GetAt(Count)==pItem)
01031                 {
01032                     return Count;
01033                 }
01034             }
01035             return -1;
01036         }
01037 
01044         inline int FindBefore(int pBeforeIndex, Type pItem) const
01045         {
01046         #ifdef KFBX_PRIVATE
01047         #ifdef _DEBUG
01048             if ( pBeforeIndex > ParentClass::GetArrayCount() || pBeforeIndex <= 0 )
01049             {
01050                 K_ASSERT_MSG_NOW (_T("ArrayUL : Search Begin Index out of range"));
01051                 return -1;
01052             }
01053         #endif
01054         #endif
01055             int Count;
01056             for ( Count=pBeforeIndex-1; Count>=0; Count--)
01057             {
01058                 if (GetAt(Count)==pItem)
01059                 {
01060                     return Count;
01061                 }
01062             }
01063             return -1;
01064         }
01065 
01070         inline int Add(Type pItem)
01071         {
01072             return InsertAt(ParentClass::GetArrayCount(), pItem);
01073         }
01074 
01079         inline int AddUnique(Type pItem)
01080         {
01081             int lReturnIndex = Find(pItem);
01082             if (lReturnIndex == -1)
01083             {
01084                 lReturnIndex = Add(pItem);
01085             }
01086             return lReturnIndex;
01087         }
01088 
01092         inline void AddMultiple(kUInt pItemCount)
01093         {
01094             ParentClass::AddMultiple(pItemCount);
01095         }
01096 
01100         inline void AddArray(const KArrayTemplate<Type> &pArray)
01101         {
01102             int lSourceIndex, lCount = pArray.GetCount();
01103             if( lCount == 0 ) return;
01104             int lDestinationIndex = ParentClass::GetCount();
01105             AddMultiple(lCount);
01106             for( lSourceIndex = 0; lSourceIndex < lCount; lSourceIndex++)
01107             {
01108                 SetAt(lDestinationIndex++, pArray[lSourceIndex]);
01109             }
01110         }
01111 
01115         inline void AddArrayNoDuplicate(const KArrayTemplate<Type> &pArray)
01116         {
01117             int i, lCount = pArray.GetCount();
01118             for( i = 0; i < lCount; i++)
01119             {
01120                 Type lItem = pArray[i];
01121                 if (Find(lItem) == -1)
01122                 {
01123                     Add(lItem);
01124                 }
01125             }
01126         }
01127 
01131         inline void RemoveArray(const KArrayTemplate<Type> &pArray)
01132         {
01133             int lRemoveIndex, lRemoveCount = pArray.GetCount();
01134             for( lRemoveIndex = 0; lRemoveIndex < lRemoveCount; lRemoveIndex++)
01135             {
01136                 RemoveIt(pArray[lRemoveIndex]);
01137             }
01138         }
01139 
01141         inline Type* GetArray() const
01142         {
01143             if (ParentClass::mBaseArray == NULL)
01144                 return NULL;
01145 
01146             return (Type*)(ParentClass::mBaseArray+ ParentClass::GetHeaderOffset()) ;
01147         }
01148 
01150         inline KArrayTemplate<Type>& operator=(const KArrayTemplate<Type>& pArrayTemplate)
01151         {
01152             if ( this != &pArrayTemplate )
01153             {
01154                 ParentClass::Clear();
01155 
01156                 int i, lCount = pArrayTemplate.GetCount();
01157 
01158                 for (i = 0; i < lCount; i++)
01159                 {
01160                     Add(pArrayTemplate[i]);
01161                 }
01162             }
01163 
01164             return (*this);
01165         }
01166 
01168         inline operator Type* ()
01169         {
01170             return GetArray();
01171         }
01172     };
01173 
01175     //
01176     //  WARNING!
01177     //
01178     //  Anything beyond these lines may not be documented accurately and is
01179     //  subject to change without notice.
01180     //
01182 
01183     // KArrayTemplate<KArrayTemplate<T> > is not supported.
01184     template < class Type > KFBX_INCOMPATIBLE_WITH_KARRAYTEMPLATE_TEMPLATE(KArrayTemplate<Type>);
01185 
01186     #ifndef DOXYGEN_SHOULD_SKIP_THIS
01187     template <class Type> inline void FbxSdkDeleteAndClear(KArrayTemplate<Type>& Array)
01188     {
01189         kUInt lItemCount = Array.GetCount();
01190         while( lItemCount )
01191         {
01192             lItemCount--;
01193             Type& Item = (Array.operator[](lItemCount));
01194             FbxSdkDelete(Item);
01195             Item = NULL;
01196         }
01197         Array.Clear();
01198     }
01199 
01200     template <class Type> inline void DeleteAndClear(KArrayTemplate<Type>& Array)
01201     {
01202         kUInt lItemCount = Array.GetCount();
01203         while( lItemCount )
01204         {
01205             lItemCount--;
01206             Type& Item = (Array.operator[](lItemCount));
01207             delete Item;
01208             Item = NULL;
01209         }
01210         Array.Clear();
01211     }
01212 /*    template <class Type> inline void DeleteAndClear(KArrayTemplate<Type>& Array)
01213     {
01214         kUInt lItemCount = Array.GetCount();
01215         while( lItemCount )
01216         {
01217             lItemCount--;
01218             Type& Item = (Array.operator[](lItemCount));
01219             delete Item;
01220             Item = NULL;
01221         }
01222         Array.Clear();
01223     }
01224 */
01225     typedef class KFBX_DLL KArrayTemplate<int *>    KArrayHkInt;
01226     typedef class KFBX_DLL KArrayTemplate<kUInt *>  KArrayHkUInt;
01227     typedef class KFBX_DLL KArrayTemplate<double *> KArrayHkDouble;
01228     typedef class KFBX_DLL KArrayTemplate<float *>  KArrayHkFloat;
01229     typedef class KFBX_DLL KArrayTemplate<void *>   KArrayVoid;
01230     typedef class KFBX_DLL KArrayTemplate<char *>   KArrayChar;
01231     typedef class KFBX_DLL KArrayTemplate<int>      KIntArray;
01232     typedef class KFBX_DLL KArrayTemplate<kUInt>    KUIntArray;
01233     typedef class KFBX_DLL KArrayTemplate<float>    KFloatArray;
01234     typedef class KFBX_DLL KArrayTemplate<double>   KDoubleArray;
01235 
01236     typedef class KFBX_DLL KArrayTemplate<kReference>   KArrayUL;
01237 
01238     #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
01239 
01240 #include <fbxfilesdk/fbxfilesdk_nsend.h>
01241 
01242 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KARRAYUL_H
01243