blib.c

Go to the documentation of this file.
00001 
00030 #include "ctl/ctldef.h"
00031 #include "ctl/blib.h"
00032 
00033 #ifndef CTL_UNIT
00034 
00035 /*
00036  * Functions to access a library
00037  */
00038 
00044 uint32 BLIB_Size( const BLIB *lib )
00045 {
00046     assert( BLIB_VALID( lib ) );
00047     return BLIB_SIZE( lib );
00048 }
00049 
00055 uint32 BLIB_Count( const BLIB *lib )
00056 {
00057     assert( BLIB_VALID( lib ) );
00058     return BLIB_COUNT( lib );
00059 }
00060 
00066 uint32 BLIB_User( const BLIB *lib )
00067 {
00068     /*  */
00069     assert( BLIB_VALID( lib ) );
00070     return BLIB_USER( lib );
00071 }
00072 
00079 bool BLIB_Valid( const BLIB *lib, uint32 libSize )
00080 {
00081 
00082     /* Intended for verification of file or resource load. */
00083     if( !BLIB_VALID( lib ) )
00084         return false;
00085 
00086     /* Does first index measure out correctly according to element count? */
00087     if( lib->offsets[0] != sizeof(BLIB) + (lib->count * sizeof(uint32)) )
00088         return false;
00089     
00090     if( libSize )
00091     {
00092         uint32 curr;
00093 
00094         /* If we have a size, check it against our calculated size */
00095         if( BLIB_SIZE( lib ) != libSize )
00096             return false;
00097 
00098         /* Walk through members to see if they overlap */
00099         for( curr = lib->count; curr; --curr )
00100         {
00101             if( lib->offsets[curr] < lib->offsets[curr - 1] )
00102             {
00103                 return false;
00104             }
00105         }
00106     }
00107     return true;
00108 }
00109 
00116 uint32 BLIB_ElementSize( const BLIB *lib, int index )
00117 {
00118     assert( BLIB_VALID( lib ) );
00119     assert( BLIB_INDEX_VALID( lib, index ) );
00120     return BLIB_ELEMENT_SIZE( lib, index );
00121 }
00122 
00129 const void *BLIB_ElementPointer( const BLIB *lib, int index )
00130 {
00131     /* Return a pointer to an element in a library */
00132     assert( BLIB_VALID( lib ) );
00133     assert( BLIB_INDEX_VALID( lib, index ) );
00134     return BLIB_ELEMENT_PTR( lib, index );
00135 }
00136 
00145 uint32 BLIB_ElementCopyData( const BLIB *lib, int index, void *data, uint32 dataSize )
00146 {
00147     uint32 dwSize;
00148     const void *pElement;
00149     assert( BLIB_VALID( lib ) );
00150     assert( BLIB_INDEX_VALID( lib, index ) );
00151     assert( dataSize );
00152     assertconst( data, dataSize );
00153     dwSize = min( BLIB_ELEMENT_SIZE( lib, index ), dataSize );
00154     pElement = BLIB_ELEMENT_PTR( lib, index );
00155     memcpy( data, pElement, dwSize );
00156     return dwSize;
00157 }
00158 
00159 /*
00160  * Functions to change a mutable library
00161  */
00162 
00168 BLIB *BLIB_Create( uint32 userID )
00169 {
00170     /*  */
00171     BLIB *libRet = malloc( sizeof(BLIB) );
00172     if( libRet )
00173     {
00174         (*((uint32 *)(libRet->magic)) = *((uint32 *)BLIB_MAGIC));
00175         libRet->userID        = userID;
00176         libRet->count  = 0;
00177         libRet->offsets[0]     = sizeof(BLIB);
00178     }
00179     return libRet;
00180 }
00181 
00187 BLIB *BLIB_Copy( const BLIB *lib )
00188 {
00189     uint32 size;
00190     BLIB *pRet;
00191     assert( BLIB_VALID( lib ) );
00192     size = BLIB_SIZE( lib );
00193     pRet = (BLIB *)malloc(size);
00194     if( pRet )
00195         memcpy( pRet, lib, size );
00196     return pRet;
00197 }
00198 
00204 void BLIB_Destroy( BLIB **lib )
00205 {
00206     assert( lib );
00207     if( BLIB_VALID( *lib ) )
00208     {
00209         free( *lib );
00210         *lib = NULL;
00211     }
00212 }
00213 
00222 bool BLIB_ElementAdd( BLIB **lib, const void *data, uint32 dataSize )
00223 {
00224     assert( lib );
00225     assert( BLIB_VALID( *lib ) );
00226     assert( data );
00227     assertconst( data, dataSize );
00228     return BLIB_ElementInsert( lib, BLIB_COUNT( *lib ), data, dataSize );
00229 }
00230 
00240 bool BLIB_ElementReplace( BLIB **lib, int index, const void *data, uint32 dataSize )
00241 {
00242     assert( lib );
00243     assert( BLIB_VALID( *lib ) );
00244     assert( BLIB_INDEX_VALID( *lib, index ) );
00245     assert( data );
00246     assert( dataSize > 0 );
00247     assertconst( data, dataSize );
00248 
00249     {
00250         int32 lDiff      = dataSize - BLIB_ELEMENT_SIZE( *lib, index );
00251         /* Though it's tempting not to reallocate the return if it's smaller, that could allow memory to slowly  */
00252         /* bleed as Libraries change items. */
00253         if( lDiff )
00254         {
00255             /* Size of output will change */
00256             int curr;
00257             uint32 dwSizeIn  = BLIB_SIZE(*lib);
00258             BLIB *libIn      = *lib;
00259             uint32 dwSizeOut = dwSizeIn + lDiff;
00260             BLIB *libOut     = lDiff ? malloc( dwSizeOut ) : libIn;
00261             if( !libOut )
00262                 return false;
00263             /* Copy original data */
00264             *libOut = *libIn;
00265             dwSizeOut = sizeof( BLIB ) + (libOut->count * sizeof(uint32) );
00266 
00267             /* Copy over any unaffected items */
00268             for( curr = 0; curr < index; ++curr )
00269             {
00270                 libOut->offsets[curr] = dwSizeOut;
00271                 dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00272                 memcpy( BLIB_ELEMENT_PTR(libOut, curr), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00273             }
00274 
00275             /* Copy the new data */
00276             libOut->offsets[index] = dwSizeOut;
00277             dwSizeOut += dataSize;
00278             memcpy( BLIB_ELEMENT_PTR(libOut, index), data, dataSize );
00279 
00280             /* Copy over any unaffected items */
00281             for( curr = index + 1; curr < (int)libIn->count; ++curr )
00282             {
00283                 libOut->offsets[curr] = dwSizeOut;
00284                 dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00285                 memcpy( BLIB_ELEMENT_PTR(libOut, curr), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00286             }
00287             libOut->offsets[curr] = dwSizeOut;
00288 
00289             /* Destroy the input library */
00290             BLIB_Destroy( &libIn );
00291 
00292             /* Return the output library */
00293             *lib = libOut;
00294         }
00295         else
00296         {
00297             /* Size unchanged, just copy the data */
00298             memcpy( BLIB_ELEMENT_PTR(*lib,index), data, dataSize );
00299         }
00300     }
00301 
00302     /* Success */
00303     return true;
00304 }
00305 
00315 bool BLIB_ElementInsert( BLIB **lib, int index, const void *data, uint32 dataSize )
00316 {
00317     assert( lib );
00318     assert( BLIB_VALID( *lib ) );
00319     assert( index >= 0 && index <= (int)BLIB_COUNT( *lib ) );
00320     assert( data );
00321     assertconst( data, dataSize );
00322 
00323     {
00324         int curr;
00325         uint32 dwSizeIn  = BLIB_SIZE(*lib);
00326         BLIB *libIn      = *lib;
00327         uint32 dwSizeOut = dwSizeIn + dataSize + sizeof(uint32);
00328         BLIB *libOut     = malloc( dwSizeOut );
00329         if( !libOut )
00330             return false;
00331 
00332         /* Copy original data */
00333         *libOut = *libIn;
00334         libOut->count++;
00335         dwSizeOut = sizeof( BLIB ) + (libOut->count * sizeof(uint32) );
00336 
00337         /* Copy over any unaffected items */
00338         for( curr = 0; curr < index; ++curr )
00339         {
00340             libOut->offsets[curr] = dwSizeOut;
00341             dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00342             memcpy( BLIB_ELEMENT_PTR(libOut, curr), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00343         }
00344 
00345         /* Copy the new data */
00346         libOut->offsets[index] = dwSizeOut;
00347         dwSizeOut += dataSize;
00348         memcpy( BLIB_ELEMENT_PTR(libOut, index), data, dataSize );
00349         
00350         /* Copy over any unaffected items */
00351         for( curr = index; curr < (int)libIn->count; ++curr )
00352         {
00353             libOut->offsets[curr+1] = dwSizeOut;
00354             dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00355             memcpy( BLIB_ELEMENT_PTR(libOut, curr+1), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00356         }
00357         libOut->offsets[curr+1] = dwSizeOut;
00358 
00359         /* Destroy the input library */
00360         BLIB_Destroy( &libIn );
00361 
00362         /* Return the output library */
00363         *lib = libOut;
00364     }
00365     return true;
00366 }
00367 
00375 bool BLIB_ElementDelete( BLIB **lib, int index )
00376 {
00377     /* Remove an element from the library */
00378     assert( BLIB_VALID( *lib ) );
00379     assert( BLIB_INDEX_VALID( *lib, index ) );
00380     assert( (*lib)->count );
00381 
00382     {
00383         int curr;
00384         uint32 dwSizeIn  = BLIB_SIZE(*lib);
00385         BLIB *libIn      = *lib;
00386         uint32 dwSizeOut = dwSizeIn - (BLIB_ELEMENT_SIZE( libIn, index ) + sizeof(uint32));
00387         BLIB *libOut     = malloc( dwSizeOut );
00388         if( !libOut )
00389             return false;
00390 
00391         /* Copy original data */
00392         *libOut = *libIn;
00393         libOut->count--;
00394         dwSizeOut = sizeof( BLIB ) + (libOut->count * sizeof(uint32) );
00395 
00396         /* Copy over any unaffected items */
00397         for( curr = 0; curr < index; ++curr )
00398         {
00399             libOut->offsets[curr] = dwSizeOut;
00400             dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00401             memcpy( BLIB_ELEMENT_PTR(libOut, curr), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00402         }
00403         
00404         /* Copy over any unaffected items */
00405         for( curr = index + 1; curr < (int)libIn->count; ++curr )
00406         {
00407             libOut->offsets[curr-1] = dwSizeOut;
00408             dwSizeOut += BLIB_ELEMENT_SIZE(libIn, curr);
00409             memcpy( BLIB_ELEMENT_PTR(libOut, curr-1), BLIB_ELEMENT_PTR(libIn, curr), BLIB_ELEMENT_SIZE(libIn, curr) );
00410         }
00411         libOut->offsets[curr-1] = dwSizeOut;
00412 
00413         /* Destroy the input library */
00414         BLIB_Destroy( &libIn );
00415 
00416         /* Return the output library */
00417         *lib = libOut;
00418     }
00419     return true;
00420 }
00421 
00422 #else /* CTL_UNIT */
00423 
00424 #include "unit/unit.h"
00425 
00426 /* Just run this in the debugger to try out various  */
00427 const char *TestJunk[] = {
00428     "1SPORK",
00429     "2FOON",
00430     "3FOO",
00431     "4BAR",
00432     "5BAZ",
00433     "6NI",
00434     "76543210",
00435     NULL
00436 };
00437 
00438 void Test_BLIB(void)
00439 {
00440     {   
00441         /*
00442          * Append test
00443          */
00444         int curr, count;
00445         BLIB *lib = BLIB_Create( *((uint32 *)"SPAM") );
00446         Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00447         for( curr = 0; TestJunk[curr]; ++curr )
00448         {
00449             BLIB_ElementAdd( &lib, TestJunk[curr], strlen( TestJunk[curr] ) + 1 );
00450             Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00451         }
00452         Test_Error( BLIB_Count( lib ) == countof(TestJunk)-1 );
00453         /*
00454          * Contains what was put in?
00455          */
00456         count = BLIB_Count( lib );
00457         for( curr = 0; curr < count; ++curr )
00458         {
00459             Test_Error( !strcmp(TestJunk[curr], BLIB_ElementPointer( lib, curr ) ) );
00460         }
00461     
00462         /*
00463          * Deletion test
00464          */
00465         BLIB_ElementDelete( &lib, 2 );
00466         BLIB_ElementDelete( &lib, 1 );
00467         BLIB_ElementDelete( &lib, 0 );
00468         count = BLIB_Count( lib );
00469         for( curr = 0; curr < count; ++curr )
00470         {
00471             Test_Error( !strcmp(TestJunk[curr+3], BLIB_ElementPointer( lib, curr ) ) );
00472             Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00473         }
00474 
00475         /*
00476          * Un-delete first three members
00477          */
00478         for( curr = 0; curr < 3; ++curr )
00479         {
00480             BLIB_ElementInsert( &lib, 0, TestJunk[curr], strlen( TestJunk[curr] ) + 1 );
00481             Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00482         }
00483 
00484         /*
00485          * Replacement test
00486          */
00487 
00488         BLIB_ElementReplace( &lib, 2, "ZAP! ZAP!", strlen("ZAP! ZAP!") + 1 );
00489         Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00490         BLIB_ElementReplace( &lib, 0, "PING! PING!", strlen("PING! PING!") + 1 );
00491         Test_Error( BLIB_Valid( lib, BLIB_Size(lib) ) );
00492         count = BLIB_Count( lib );
00493         for( curr = 0; curr < count; ++curr )
00494         {
00495             if( curr == 0 )
00496             {
00497                 Test_Error( !strcmp("PING! PING!", BLIB_ElementPointer( lib, curr ) ) );
00498             }
00499             else if( curr == 2 )
00500             {
00501                 Test_Error( !strcmp("ZAP! ZAP!", BLIB_ElementPointer( lib, curr ) ) );
00502             }
00503             else
00504                 Test_Error( !strcmp(TestJunk[curr], BLIB_ElementPointer( lib, curr ) ) );
00505         }
00506         
00507         BLIB_Destroy( &lib );
00508     }
00509     {   
00510         /*
00511          * Insertion test
00512          */
00513         int curr,rcurr, count;
00514         BLIB *lib = BLIB_Create( *((uint32 *)"FOON") );
00515         for( curr = 0; TestJunk[curr]; ++curr )
00516         {
00517             BLIB_ElementInsert( &lib, 0, TestJunk[curr], strlen( TestJunk[curr] ) + 1 );
00518             Test_Error( BLIB_Valid( lib, 0 ) );
00519         }
00520         Test_Error( BLIB_Count( lib ) == countof(TestJunk)-1 );
00521         /*
00522          * Contains what was put in?
00523          */
00524         count = BLIB_Count( lib );
00525         for( curr = 0, rcurr = countof(TestJunk)-2; curr < count; ++curr, --rcurr )
00526         {
00527             Test_Error( !strcmp(TestJunk[rcurr], BLIB_ElementPointer( lib, curr ) ) );
00528         }
00529 
00530         BLIB_Destroy( &lib );
00531     }
00532     
00533 
00534 }
00535 
00536 
00537 #endif /* CTL_UNIT */
00538 

Generated on Fri Jan 2 15:28:34 2009 for Squat by  doxygen 1.5.6