asstorage.c

Go to the documentation of this file.
00001 /* This file contains code for memopry management for image data    */
00002 /********************************************************************/
00003 /* Copyright (c) 2004 Sasha Vasko <sasha at aftercode.net>          */
00004 /********************************************************************/
00005 /*
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #undef LOCAL_DEBUG
00023 /* #undef NO_DEBUG_OUTPUT */
00024 #ifndef NO_DEBUG_OUTPUT
00025 #undef DEBUG_COMPRESS
00026 #undef DEBUG_THRESHOLD
00027 #endif
00028 #define DO_CLOCKING
00029 
00030 #ifdef _WIN32
00031 #include "win32/config.h"
00032 #else
00033 #include "config.h"
00034 #endif
00035 
00036 #if TIME_WITH_SYS_TIME
00037 # include <sys/time.h>
00038 # include <time.h>
00039 #else
00040 # if HAVE_SYS_TIME_H
00041 #  include <sys/time.h>
00042 # else
00043 #  include <time.h>
00044 # endif
00045 #endif
00046 #ifdef HAVE_UNISTD_H
00047 #include <unistd.h>
00048 #endif
00049 #ifdef HAVE_STDLIB_H
00050 #include <stdlib.h>
00051 #endif
00052 #include <memory.h>
00053 
00054 #ifndef HAVE_ZLIB_H
00055 #include "zlib/zlib.h"
00056 #else
00057 #include <zlib.h>
00058 #endif
00059 
00060 #ifdef _WIN32
00061 # include "win32/afterbase.h"
00062 #else
00063 # include "afterbase.h"
00064 #endif
00065 
00066 #include "asstorage.h"
00067 
00068 /* default storage : */
00069 
00070 ASStorage *_as_default_storage = NULL ;
00071 
00072 #define get_default_asstorage()   (_as_default_storage?_as_default_storage:(_as_default_storage=create_asstorage()))
00073 
00074 
00075 /************************************************************************/
00076 /* Private Functions :                                                                                                  */
00077 /************************************************************************/
00078 
00079 #define StorageID2BlockIdx(id)          (((((CARD32)(id))>>14)&0x0003FFFF)-1)
00080 #define StorageID2SlotIdx(id)            ((((CARD32)(id))&0x00003FFF)-1)
00081 
00082 static size_t UsedMemory = 0 ;
00083 static size_t UncompressedSize = 0, CompressedSize = 0 ;
00084 
00085 static inline ASStorageID 
00086 make_asstorage_id( int block_id, int slot_id )
00087 {
00088         ASStorageID id = 0 ;
00089         if( block_id > 0 && block_id < (0x01<<18)&& slot_id > 0 && slot_id < (0x01<<14)) 
00090                 id = ((CARD32)block_id<<14)|(CARD32)slot_id ;
00091         return id;
00092 }
00093 
00094 static int 
00095 rlediff_compress_bitmap8( CARD8 *buffer,  CARD8* data, int size, CARD32 bitmap_threshold )
00096 {       
00097         int i = 0, comp_size = 0, last_val = 0 ;
00098         while( i < size ) 
00099         {
00100                 int count = 0 ;
00101                 do{     
00102 /*                      LOCAL_DEBUG_OUT( "data[%d] = %d, threshold = %d\n", i, data[i], bitmap_threshold); */
00103                         if( (( data[i] >= bitmap_threshold )?1:0) != last_val )           
00104                                 break; 
00105                         ++i ;
00106                 }while( ++count < 255 && i < size );     
00107                 last_val = (last_val == 1)?0:1 ;
00108                 buffer[comp_size++] = count ;
00109         }
00110         return comp_size;       
00111 }        
00112 
00113 static int 
00114 rlediff_compress_bitmap32( CARD8 *buffer,  CARD8* data, int size, CARD32 bitmap_threshold )
00115 {       
00116         int i = 0, comp_size = 0, last_val = 0 ;
00117         CARD32 *data32 = (CARD32*)data ;
00118         while( i < size ) 
00119         {
00120                 int count = 0 ;
00121                 do{     
00122                         if( (( data32[i] >= bitmap_threshold )?1:0) != last_val )         
00123                                 break; 
00124                         ++i ;
00125                 }while( ++count < 255 && i < size );     
00126                 last_val = (last_val == 1)?0:1 ;
00127                 buffer[comp_size++] = count ;
00128         }
00129         return comp_size;       
00130 }        
00131 
00132 
00133 static void
00134 compute_diff8( register ASStorageDiff *diff, register CARD8 *data, int size ) 
00135 {
00136         register int i = 0;     
00137         diff[0] = data[0] ;
00138 /*      fprintf( stderr, "%d(%4.4X) ", diff[0], diff[0] ); */
00139         while( ++i < size ) 
00140         {       
00141                 diff[i] = (ASStorageDiff)data[i] - (ASStorageDiff)data[i-1] ;
00142 /*              fprintf( stderr, "%d(%4.4X) ", diff[i], diff[i] ); */
00143         }
00144 /*      fprintf( stderr, "\n" ); */
00145 }          
00146 
00147 static void
00148 compute_diff32( register ASStorageDiff *diff, CARD8 *data, int size ) 
00149 {
00150         register int i = 0;     
00151         register CARD32 *data32 = (CARD32*)data ;
00152         diff[0] = data32[0] ;
00153 /*      fprintf( stderr, "\n0:%d(%4.4X) ", diff[0], diff[0] ); */
00154         while( ++i < size ) 
00155         {       
00156                 diff[i] = (ASStorageDiff)data32[i] - (ASStorageDiff)data32[i-1] ;
00157 /*              fprintf( stderr, "%d:%d(%4.4X) ", i, diff[i], diff[i] ); */
00158         }
00159 /*      fprintf( stderr, "\n" ); */
00160 }          
00161 
00162 static void
00163 compute_diff32_8bitshift( register ASStorageDiff *diff, CARD8 *data, int size ) 
00164 {
00165         register int i = 0;     
00166         register CARD32 *data32 = (CARD32*)data ;
00167         register ASStorageDiff dp = data32[0]>>8;
00168         diff[0] = dp ;
00169         while( ++i < size ) 
00170         {
00171                 register ASStorageDiff d = data32[i]>>8;
00172                 diff[i] = d - dp ;
00173                 dp = d;
00174         }
00175 }          
00176 
00177 static void
00178 compute_diff32_16bitshift( register ASStorageDiff *diff, CARD8 *data, int size ) 
00179 {
00180         register int i = 0;     
00181         register CARD32 *data32 = (CARD32*)data ;
00182         register ASStorageDiff dp = data32[0]>>16;
00183         diff[0] = dp ;
00184         while( ++i < size ) 
00185         {
00186                 register ASStorageDiff d = data32[i]>>16;
00187                 diff[i] = d - dp ;
00188                 dp = d;
00189         }
00190 }          
00191 
00192 static void
00193 compute_diff32_masked( register ASStorageDiff *diff, CARD8 *data, int size ) 
00194 {
00195         register int i = 0;     
00196         register CARD32 *data32 = (CARD32*)data ;
00197         register ASStorageDiff dp = data32[0]&0x0ff;
00198         diff[0] = dp ;
00199         while( ++i < size ) 
00200         {
00201                 register ASStorageDiff d = data32[i]&0x0ff;
00202                 diff[i] = d - dp ;
00203                 dp = d;
00204         }
00205 }          
00206 
00207 static void
00208 compute_diff32_8bitshift_masked( register ASStorageDiff *diff, CARD8 *data, int size ) 
00209 {
00210         register int i = 0;     
00211         register CARD32 *data32 = (CARD32*)data ;
00212         register ASStorageDiff dp = (data32[0]>>8)&0x0ff;
00213         diff[0] = dp ;
00214         while( ++i < size ) 
00215         {
00216                 register ASStorageDiff d = (data32[i]>>8)&0x0ff;
00217                 diff[i] = d - dp ;
00218                 dp = d;
00219         }
00220 }          
00221 
00222 static void
00223 compute_diff32_16bitshift_masked( register ASStorageDiff *diff, CARD8 *data, int size ) 
00224 {
00225         register int i = 0;     
00226         register CARD32 *data32 = (CARD32*)data ;
00227         register ASStorageDiff dp = (data32[0]>>16)&0x0ff;
00228         diff[0] = dp ;
00229         while( ++i < size ) 
00230         {
00231                 register ASStorageDiff d = (data32[i]>>16)&0x0ff;
00232                 diff[i] = d - dp ;
00233                 dp = d;
00234         }
00235 }          
00236 
00237 static void
00238 compute_diff32_24bitshift_masked( register ASStorageDiff *diff, CARD8 *data, int size ) 
00239 {
00240         register int i = 0;     
00241         register CARD32 *data32 = (CARD32*)data ;
00242         register ASStorageDiff dp = (data32[0]>>24)&0x0ff;
00243         diff[0] = dp ;
00244         while( ++i < size ) 
00245         {
00246                 register ASStorageDiff d = (data32[i]>>24)&0x0ff;
00247                 diff[i] = d - dp ;
00248                 dp = d;
00249         }
00250 }          
00251 
00252 static int 
00253 rlediff_compress( CARD8 *buffer,  ASStorageDiff *diff, int size )
00254 {
00255         int comp_size = 1 ;
00256         int i = 1;
00257         
00258         buffer[0] = (CARD8)diff[0] ; 
00259 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00260         fprintf(stderr, "first byte: 0x%2.2X \n", buffer[0] );
00261 #endif                          
00262         while( i < size ) 
00263         {
00264                 int run_step = 0;
00265                 int run_size2 = 0;
00266                 int d = diff[i] ; 
00267                 
00268                 if( d == 0 ) 
00269                 {
00270                         int zero_size = 0 ;  /* intentionally ! */ 
00271                         while( ++i < size && zero_size < 127 )   
00272                         {       
00273                                 if( diff[i] != 0 ) 
00274                                         break;
00275                                 ++zero_size ;
00276                         }
00277 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00278                         fprintf( stderr, "comp_size = %d at line %d\n", comp_size, __LINE__ );
00279 #endif
00280                         if( comp_size + 1 > size )
00281                                 return 0; 
00282 
00283                         buffer[comp_size] = RLE_ZERO_SIG | zero_size ;
00284 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00285                         fprintf(stderr, "in %d out %d: 0x%2.2X  - %d zeros\n", i, comp_size, buffer[comp_size], zero_size+1 );
00286 #endif
00287                         ++comp_size ;
00288                 }else 
00289                 {       
00290                         if( d < 0) d = -d ;
00291                         
00292                         if( d <= 8 )  
00293                         { /* see if we can pack everything into 2 or 4 bit string */
00294                                 do
00295                                 {
00296                                         if( (d = diff[i]) == 0 ) 
00297                                                 break;
00298                                         if( d < 0) d = -d ;
00299                                         if( d > 8 ) 
00300                                                 break;
00301                                         if( run_size2 == run_step ) 
00302                                         {       
00303                                                 if( d > 2 )
00304                                                 {
00305                                                         if( run_size2 >= 4 )
00306                                                                 break;
00307                                                 }else if( ++run_size2  >= 16 ) 
00308                                                 {
00309                                                         ++i ;     
00310                                                         break; 
00311                                                 }
00312                                         }
00313                                         ++run_step ;
00314                                         ++i ;
00315                                 }while( i < size && run_step < 64 );    
00316                                 
00317                                 if( run_step > run_size2 ) 
00318                                 {                  /* encoding as 4 bit values */
00319                                         int k = i - run_step;
00320 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00321                                         fprintf( stderr, "comp_size = %d, run_step = %d at line %d\n", comp_size, run_step, __LINE__ );
00322 #endif
00323                                         if( comp_size + 1 + run_step/2 > size )
00324                                                 return 0; 
00325  
00326 
00327                                         buffer[comp_size] = RLE_NOZERO_SHORT_SIG | (run_step-1) ;                                                                                          
00328 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00329                                         fprintf(stderr, "in %d out %d: 0x%2.2X  - %d 4bits things\n", i, comp_size, buffer[comp_size], run_step );
00330 #endif                          
00331                                         ++comp_size;
00332                                         do
00333                                         {
00334                                                 if( (d = diff[k]) < 0 ) buffer[comp_size] = 0x80|((-d-1)<<4) ;
00335                                                 else                                    buffer[comp_size] =      ((d-1)<<4) ;
00336                                                 
00337                                                 if( ++k < i )
00338                                                 {       
00339                                                         if( (d = diff[k]) < 0 ) buffer[comp_size] |= 0x08|(-d-1) ;
00340                                                         else                                    buffer[comp_size] |=      (d-1) ;
00341                                                         ++k ;
00342                                                 }
00343 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00344                                                 fprintf(stderr, "0x%2.2X ", buffer[comp_size] );
00345 #endif
00346                                                 ++comp_size ;
00347                                         }while( k < i );
00348                                 }else    
00349                                 {                                       /* encoding as 2 bit values */
00350                                         int k = i - run_size2;
00351 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00352                                         fprintf( stderr, "comp_size = %d, run_step = %d at line %d\n", comp_size, run_size2, __LINE__ );
00353 #endif
00354                                         if( comp_size + 1 + run_size2/4 > size )
00355                                                 return 0; 
00356  
00357 
00358                                         buffer[comp_size] = RLE_NOZERO_LONG1_SIG | (run_size2-1) ;                                                                                         
00359 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00360                                         fprintf(stderr, "in %d out %d: 0x%2.2X  - %d 2bits things\n", i, comp_size, buffer[comp_size], run_size2 );
00361 #endif                          
00362                                         ++comp_size;
00363                                         do
00364                                         {
00365                                                 if( (d = diff[k]) < 0 ) buffer[comp_size] = 0x80|((-d-1)<<6) ;
00366                                                 else                                    buffer[comp_size] =      ((d-1)<<6) ;
00367 
00368                                                 if( ++k < i )
00369                                                 {       
00370                                                         if( (d = diff[k]) < 0 ) buffer[comp_size] |= 0x20|((-d-1)<<4) ;
00371                                                         else                                    buffer[comp_size] |=      ((d-1)<<4) ;
00372                                                         if( ++k < i )
00373                                                         {
00374                                                                 if( (d = diff[k]) < 0 ) buffer[comp_size] |= 0x08|((-d-1)<<2) ;
00375                                                                 else                                    buffer[comp_size] |=      ((d-1)<<2) ;
00376                                                                 if( ++k < i )
00377                                                                 {       
00378                                                                         if( (d = diff[k]) < 0 ) buffer[comp_size] |= 0x02|(-d-1) ;
00379                                                                         else                                    buffer[comp_size] |=      (d-1) ;
00380                                                                         ++k ;
00381                                                                 }
00382                                                         }
00383                                                 }
00384 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00385                                                 fprintf(stderr, "0x%2.2X ", buffer[comp_size] );
00386 #endif
00387                                                 ++comp_size ;
00388                                         }while( k  < i );
00389                                 }        
00390                         }else if( d <= 135 )  
00391                         {                      /* 8 bit strings */
00392                                 int k = 0;
00393                                 do
00394                                 {
00395                                         if( (d = diff[i]) == 0 ) 
00396                                                 break;
00397                                         if( d < 0) d = -d ;
00398                                         if( d > 135 || d <= 8 ) 
00399                                                 break;
00400                                         ++run_step ;
00401                                 }while( ++i < size && run_step < 16 );  
00402                         
00403 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00404                                 fprintf( stderr, "comp_size = %d, run_step = %d, size = %d at line %d\n", comp_size, run_step, size, __LINE__ );
00405 #endif
00406                                 if( comp_size + 1 + run_step > size )
00407                                         return 0; 
00408 
00409 
00410                                 buffer[comp_size] = RLE_NOZERO_LONG2_SIG | (run_step-1) ;                                                                                          
00411 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00412                                 fprintf(stderr, "in %d out %d: 0x%2.2X  - %d 8bits things\n", i, comp_size, buffer[comp_size], run_step );
00413 #endif                          
00414                                 ++comp_size;
00415                                 k = i - run_step ;
00416                                 do
00417                                 {
00418                                         if( (d = diff[k]) < 0 ) buffer[comp_size] = 0x80|(-d-8) ;
00419                                         else                                    buffer[comp_size] =      (d-8) ;
00420 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00421                                         fprintf(stderr, "0x%2.2X ", buffer[comp_size] );
00422 #endif
00423                                         ++comp_size ;
00424                                 }while( ++k < i );
00425                         }else            
00426                         {       
00427                                 int k = 0;              /* 9 bit strings */
00428                                 do
00429                                 {
00430                                         if( (d = diff[i]) == 0 ) 
00431                                                 break;
00432                                         if( d < 0) d = -d ;
00433                                         if( d <= 135 ) 
00434                                                 break;
00435                                         ++run_step ;
00436                                 }while( ++i < size && run_step < 16 );  
00437 
00438 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00439                                         fprintf( stderr, "comp_size = %d, run_step = %d at line %d\n", comp_size, run_step, __LINE__ );
00440 #endif
00441                                 if( comp_size + 1 + run_step > size )
00442                                         return 0; 
00443  
00444                                 
00445                                 k = i - run_step ;
00446                                 if( diff[k] > 0 ) 
00447                                         buffer[comp_size] = RLE_9BIT_SIG | (run_step-1) ;                                                                                          
00448                                 else
00449                                         buffer[comp_size] = RLE_9BIT_NEG_SIG | (run_step-1) ;                                                                                      
00450 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00451                                 fprintf(stderr, "in %d out %d: 0x%2.2X  - %d 9bit things\n", i, comp_size, buffer[comp_size], run_step );
00452 #endif                          
00453                                 ++comp_size;
00454                                 do
00455                                 {
00456                                         if( (d = diff[k]) < 0 ) buffer[comp_size] = -d ;
00457                                         else                                    buffer[comp_size] =  d ;
00458                                         
00459 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00460                                         fprintf(stderr, "0x%2.2X ", buffer[comp_size] );
00461 #endif
00462                                         ++comp_size ;
00463                                 }while( ++k  < i );
00464                         } 
00465                 }
00466 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00467                 fprintf(stderr, "\n");
00468 #endif
00469         }        
00470         /* fprintf( stderr, "compressed from %d to %d\n", size, comp_size ); */
00471         /* its better to do it here from performance point of view since most of
00472          * the data will be well compressed */
00473         if( comp_size > size ) 
00474                 return 0;
00475         return comp_size ;
00476 }        
00477 
00478 static int
00479 rlediff_decompress_bitmap( CARD8 *buffer,  CARD8* data, int size, CARD8 bitmap_value )
00480 {
00481         unsigned int count ;
00482         int out_bytes = 0 ;
00483         int in_bytes = 0 ;
00484         CARD8 curr_val = 0;
00485 
00486         while( in_bytes < size ) 
00487         {
00488                 count = ((unsigned int)(data[in_bytes++])+1) ;
00489                 while( --count > 0 ) 
00490                         buffer[out_bytes++] = curr_val ;
00491                 curr_val = (curr_val == bitmap_value)? 0 : bitmap_value ;
00492         }
00493         
00494         LOCAL_DEBUG_OUT( "in_bytes = %d, out_bytes = %d, size = %d", in_bytes, out_bytes, size );
00495         return out_bytes;
00496 }
00497 
00498 static int
00499 rlediff_decompress( CARD8 *buffer,  CARD8* data, int size )
00500 {
00501         int count ;
00502         int out_bytes = 1 ;
00503         int in_bytes = 1 ;
00504         CARD8 last_val;
00505 
00506         buffer[0] = last_val = data[0] ; 
00507 
00508         while( in_bytes < size ) 
00509         {
00510                 CARD8 c = data[in_bytes++] ;
00511 #if defined(DEBUG_COMPRESS) && !defined(NO_DEBUG_OUTPUT)
00512                 fprintf(stderr, "in %d out %d: 0x%2.2X \n", in_bytes, out_bytes, c);
00513 #endif                          
00514 
00515                 if( (c & RLE_ZERO_MASK) == 0 )                     
00516                 {
00517                         count = (int)c  + 1 ;
00518                         while( --count >= 0 )     
00519                                 buffer[out_bytes++] = last_val ;
00520                 }else if( (c & RLE_NOZERO_SHORT_MASK ) == RLE_NOZERO_SHORT_SIG ) 
00521                 {
00522                         count = c & RLE_NOZERO_SHORT_LENGTH ;
00523                         ++count ;
00524                         while( --count >= 0 ) 
00525                         {
00526                                 CARD8 mod = ((data[in_bytes]>>4)&0x07)+1;
00527                                 last_val = (data[in_bytes]&0x80)?last_val - mod : last_val + mod ;
00528                                 buffer[out_bytes++] = last_val ;
00529                                 if( --count >= 0 )
00530                                 {
00531                                         mod = (data[in_bytes]&0x07)+1;
00532                                         last_val = (data[in_bytes]&0x08)?last_val - mod : last_val + mod ;
00533                                         buffer[out_bytes++] = last_val ;
00534                                 }
00535                                 ++in_bytes ;
00536                         }
00537                 }else
00538                 {
00539                         count = c & RLE_NOZERO_LONG_LENGTH ;
00540                         ++count ;
00541                         if( (c & RLE_NOZERO_LONG_MASK ) == RLE_NOZERO_LONG1_SIG ) 
00542                         {
00543                                 while( --count >= 0 ) 
00544                                 {
00545                                         CARD8 mod = ((data[in_bytes]>>6)&0x01)+1;
00546                                         last_val = (data[in_bytes]&0x80)?last_val - mod : last_val + mod ;
00547                                         buffer[out_bytes++] = last_val ;
00548                                         if( --count >= 0 )
00549                                         {
00550                                                 mod = ((data[in_bytes]>>4)&0x01)+1;
00551                                                 last_val = (data[in_bytes]&0x20)?last_val - mod : last_val + mod ;
00552                                                 buffer[out_bytes++] = last_val ;
00553                                                 if( --count >= 0 )
00554                                                 {
00555                                                         mod = ((data[in_bytes]>>2)&0x01)+1;
00556                                                         last_val = (data[in_bytes]&0x08)?last_val - mod : last_val + mod ;
00557                                                         buffer[out_bytes++] = last_val ;
00558                                                         if( --count >= 0 )
00559                                                         {
00560                                                                 mod = (data[in_bytes]&0x01)+1;
00561                                                                 last_val = (data[in_bytes]&0x02)?last_val - mod : last_val + mod ;
00562                                                                 buffer[out_bytes++] = last_val ;
00563                                                         }
00564                                                 }
00565 
00566                                         }
00567                                         ++in_bytes ;
00568                                 }
00569                         }else if( (c & RLE_NOZERO_LONG_MASK ) == RLE_NOZERO_LONG2_SIG ) 
00570                         {
00571                                 while( --count >= 0 ) 
00572                                 {
00573                                         CARD8 mod = (data[in_bytes]&0x7F)+8;
00574                                         last_val = (data[in_bytes]&0x80)?last_val - mod : last_val + mod ;
00575                                         buffer[out_bytes++] = last_val ;
00576                                         ++in_bytes ;
00577                                 }
00578                         }else
00579                         {
00580                                 Bool sign = ((c & RLE_NOZERO_LONG_MASK ) == RLE_9BIT_NEG_SIG);
00581                                 while( --count >= 0 ) 
00582                                 {
00583                                         CARD8 mod = data[in_bytes];
00584                                         last_val = sign? last_val - mod : last_val + mod ;
00585                                         sign = !sign ;
00586                                         buffer[out_bytes++] = last_val ;
00587                                         ++in_bytes ;
00588                                 }
00589                         }
00590                 }        
00591         }        
00592         LOCAL_DEBUG_OUT( "in_bytes = %d, out_bytes = %d, size = %d", in_bytes, out_bytes, size );
00593         return out_bytes;
00594 }        
00595 
00596 
00597 static int
00598 copy_data_tinted (CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00599 {
00600         int comp_size = 0;
00601         do{     buffer[comp_size] = (data32[comp_size]*tint)>>8;}while (++comp_size < size);
00602         return comp_size;
00603 }
00604 
00605 static int
00606 copy_data_tinted_8bitshift (CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00607 {
00608         int comp_size = 0;
00609         do{     buffer[comp_size] = (data32[comp_size]*tint)>>16;}while (++comp_size < size);
00610         return comp_size;
00611 }
00612 
00613 static int
00614 copy_data_tinted_16bitshift (CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00615 {
00616         int comp_size = 0;
00617         do{     buffer[comp_size] = (data32[comp_size]*tint)>>24;}while (++comp_size < size);
00618         return comp_size;
00619 }
00620 
00621 static int
00622 copy_data_tinted_masked ( CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00623 {
00624         int comp_size = 0;
00625         do{     buffer[comp_size] = ((data32[comp_size]&0x0FF)*tint)>>8;}while (++comp_size < size);
00626         return comp_size;
00627 }
00628 
00629 static int
00630 copy_data_tinted_8bitshift_masked (CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00631 {
00632         int comp_size = 0;
00633         do{     buffer[comp_size] = (((data32[comp_size]>>8)&0x0FF)*tint)>>8;}while (++comp_size < size);
00634         return comp_size;
00635 }
00636 
00637 
00638 static int
00639 copy_data_tinted_16bitshift_masked (CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00640 {
00641         int comp_size = 0;
00642         do{     buffer[comp_size] = (((data32[comp_size]>>16)&0x0FF)*tint)>>8;}while (++comp_size < size);
00643         return comp_size;
00644 }
00645 
00646 static int
00647 copy_data_tinted_24bitshift_masked( CARD8 *buffer, CARD32 *data32, int size, CARD32 tint)
00648 {
00649         int comp_size = 0;
00650         do{     buffer[comp_size] = (((data32[comp_size]>>24)&0x0FF)*tint)>>8;}while (++comp_size < size);
00651         return comp_size;
00652 }
00653 
00654 static int
00655 copy_data32 (CARD8 *buffer, CARD32 *data32, int size)
00656 {
00657         int comp_size = 0;
00658         do{     buffer[comp_size] = data32[comp_size];}while (++comp_size < size);
00659         return comp_size;
00660 }
00661 
00662 static int
00663 copy_data32_8bitshift (CARD8 *buffer, CARD32 *data32, int size)
00664 {
00665         int comp_size = 0;
00666         do{     buffer[comp_size] = data32[comp_size]>>8;}while (++comp_size < size);
00667         return comp_size;
00668 }
00669 
00670 static int
00671 copy_data32_16bitshift (CARD8 *buffer, CARD32 *data32, int size)
00672 {
00673         int comp_size = 0;
00674         do{     buffer[comp_size] = data32[comp_size]>>16;}while (++comp_size < size);
00675         return comp_size;
00676 }
00677 
00678 static int
00679 copy_data32_masked ( CARD8 *buffer, CARD32 *data32, int size)
00680 {
00681         int comp_size = 0;
00682         do{     buffer[comp_size] = data32[comp_size]&0x0FF;}while (++comp_size < size);
00683         return comp_size;
00684 }
00685 
00686 static int
00687 copy_data32_8bitshift_masked (CARD8 *buffer, CARD32 *data32, int size)
00688 {
00689         int comp_size = 0;
00690         do{     buffer[comp_size] = (data32[comp_size]>>8)&0x0FF;}while (++comp_size < size);
00691         return comp_size;
00692 }
00693 
00694 
00695 static int
00696 copy_data32_16bitshift_masked (CARD8 *buffer, CARD32 *data32, int size)
00697 {
00698         int comp_size = 0;
00699         do{     buffer[comp_size] = (data32[comp_size]>>16)&0x0FF;}while (++comp_size < size);
00700         return comp_size;
00701 }
00702 
00703 static int
00704 copy_data32_24bitshift_masked( CARD8 *buffer, CARD32 *data32, int size)
00705 {
00706         int comp_size = 0;
00707         do{     buffer[comp_size] = (data32[comp_size]>>24)&0x0FF;}while (++comp_size < size);
00708         return comp_size;
00709 }
00710 
00711 
00712 static CARD8* 
00713 compress_stored_data( ASStorage *storage, CARD8 *data, int size, ASFlagType *flags, int *compressed_size,
00714                                           CARD32 bitmap_threshold )
00715 {
00716         /* TODO: just a stub for now - need to implement compression */
00717         int comp_size = size ;
00718         CARD8  *buffer = data ;
00719         size_t  buf_size = size ; 
00720 
00721         static compute_diff_func_type compute_diff_func[2][4] = 
00722         {       {
00723                         compute_diff32,
00724                         compute_diff32_8bitshift,
00725                         compute_diff32_16bitshift,
00726                         compute_diff32_24bitshift_masked /* to clear the sign bit ! */
00727                 },
00728                 {
00729                         compute_diff32_masked,
00730                         compute_diff32_8bitshift_masked,
00731                         compute_diff32_16bitshift_masked,
00732                         compute_diff32_24bitshift_masked
00733                 }
00734         };
00735 
00736         static copy_data32_tinted_func_type copy_data32_tinted_func[2][4] = 
00737         {       {
00738                         copy_data_tinted,
00739                         copy_data_tinted_8bitshift,
00740                         copy_data_tinted_16bitshift,
00741                         copy_data_tinted_24bitshift_masked /* to clear the sign bit ! */
00742                 },
00743                 {
00744                         copy_data_tinted_masked,
00745                         copy_data_tinted_8bitshift_masked,
00746                         copy_data_tinted_16bitshift_masked,
00747                         copy_data_tinted_24bitshift_masked
00748                 }
00749         };
00750 
00751         static copy_data32_func_type copy_data32_func[2][4] = 
00752         {       {
00753                         copy_data32,
00754                         copy_data32_8bitshift,
00755                         copy_data32_16bitshift,
00756                         copy_data32_24bitshift_masked /* to clear the sign bit ! */
00757                 },
00758                 {
00759                         copy_data32_masked,
00760                         copy_data32_8bitshift_masked,
00761                         copy_data32_16bitshift_masked,
00762                         copy_data32_24bitshift_masked
00763                 }
00764         };
00765 
00766         if( size < ASStorageSlot_SIZE ) 
00767                 clear_flags( *flags, ASStorage_RLEDiffCompress );
00768 
00769         if (get_flags( *flags, ASStorage_Bitmap )) /* always compress bitmaps !!!! */
00770                 set_flags( *flags, ASStorage_RLEDiffCompress );
00771 
00772         if( get_flags( *flags, ASStorage_RLEDiffCompress ) )
00773         {
00774                 int uncompressed_size = size ;
00775 
00776                 clear_flags( *flags, ASStorage_RLEDiffCompress );
00777                 if( (int)storage->comp_buf_size < size ) 
00778                 {       
00779                         storage->comp_buf_size = ((size/AS_STORAGE_PAGE_SIZE)+1)*AS_STORAGE_PAGE_SIZE ;
00780                         storage->comp_buf = realloc( storage->comp_buf, storage->comp_buf_size );
00781                         storage->diff_buf = realloc( storage->diff_buf, storage->comp_buf_size*sizeof(ASStorageDiff) );
00782 #ifdef DEBUG_ALLOCS
00783                         show_debug( __FILE__,"compress_stored_data",__LINE__," realloced compression buffer to %d+%d*%d",storage->comp_buf_size, storage->comp_buf_size, sizeof(ASStorageDiff) );
00784 #endif 
00785                 }
00786                 buffer = storage->comp_buf ;
00787                 buf_size = storage->comp_buf_size ;
00788                 if( buffer ) 
00789                 {
00790                         if( get_flags( *flags, ASStorage_Bitmap ) )
00791                         {       
00792                                 if( get_flags( *flags, ASStorage_32Bit ) ) 
00793                                 {
00794                                         uncompressed_size = size / 4 ;
00795                                         if( get_flags( *flags, ASStorage_BitShift ) )
00796                                                 bitmap_threshold = bitmap_threshold<<ASStorage_Flags2Shift(*flags) ;
00797                                         comp_size = rlediff_compress_bitmap32( buffer, data, uncompressed_size, bitmap_threshold );
00798                                 }else
00799                                         comp_size = rlediff_compress_bitmap8( buffer, data, uncompressed_size, bitmap_threshold );
00800                         }else 
00801                         {
00802                                 ASStorageDiff tint = bitmap_threshold ;
00803                                 if( get_flags( *flags, ASStorage_32Bit ) ) 
00804                                 {       
00805                                         uncompressed_size = size / 4 ;
00806                                         compute_diff_func[get_flags(*flags,ASStorage_Masked)?1:0]
00807                                                          [ASStorage_Flags2ShiftIdx(*flags)](storage->diff_buf, data, uncompressed_size );
00808                                 }else
00809                                         compute_diff8( storage->diff_buf, data, uncompressed_size );      
00810                                 
00811                                 if( tint != 255 )
00812                                 {
00813                                         int i;
00814                                         ASStorageDiff *diff = storage->diff_buf ; 
00815                                         for( i = 0 ; i < uncompressed_size ; ++i ) 
00816                                                 diff[i] = (diff[i]*tint)/256 ;
00817                                 }        
00818                                 comp_size = rlediff_compress( buffer, storage->diff_buf, uncompressed_size );
00819                         }
00820 
00821                         if( comp_size == 0 )     
00822                         {       
00823                                 buffer = data ;
00824                                 comp_size = size ;
00825                         }else
00826                         {       
00827                                 set_flags( *flags, ASStorage_RLEDiffCompress );
00828                                 UncompressedSize += size ;
00829                                 CompressedSize += comp_size ;
00830                         }
00831                 }else
00832                         buffer = data ;  
00833                 
00834                 LOCAL_DEBUG_OUT( "size = %d, compressed_size = %d, flags = 0x%lX", size, comp_size, *flags );
00835         }        
00836 
00837         if( buffer == data )
00838         {
00839                 CARD32 tint = get_flags( *flags, ASStorage_Bitmap )? 0x00FF : bitmap_threshold ;
00840                 if( get_flags( *flags, ASStorage_32Bit ) )
00841                 {
00842                         CARD32 *data32 = (CARD32*)data ;
00843                         size /= 4;
00844                         if( (int)(storage->comp_buf_size) < size ) 
00845                         {       
00846                                 storage->comp_buf_size = ((size/AS_STORAGE_PAGE_SIZE)+1)*AS_STORAGE_PAGE_SIZE ;
00847                                 storage->comp_buf = realloc( storage->comp_buf, storage->comp_buf_size );
00848                                 storage->diff_buf = realloc( storage->diff_buf, storage->comp_buf_size*sizeof(ASStorageDiff) );
00849 #ifdef DEBUG_ALLOCS
00850                         show_debug( __FILE__,"compress_stored_data",__LINE__," realloced compression buffer to %d+%d*%d",storage->comp_buf_size, storage->comp_buf_size, sizeof(ASStorageDiff) );
00851 #endif 
00852 
00853                         }
00854                         buffer = storage->comp_buf ;
00855                         if( tint != 0x000000FF ) 
00856                         {       
00857                                 copy_data32_tinted_func [get_flags(*flags,ASStorage_Masked)?1:0]
00858                                                                 [ASStorage_Flags2ShiftIdx(*flags)](buffer, data32, size, tint);
00859                         }else
00860                         {
00861                                 copy_data32_func [get_flags(*flags,ASStorage_Masked)?1:0]
00862                                                          [ASStorage_Flags2ShiftIdx(*flags)](buffer, data32, size);
00863 
00864                         }        
00865                 }else if( tint != 0x000000FF ) 
00866                 {
00867                         if( (int)storage->comp_buf_size < size ) 
00868                         {       
00869                                 storage->comp_buf_size = ((size/AS_STORAGE_PAGE_SIZE)+1)*AS_STORAGE_PAGE_SIZE ;
00870                                 storage->comp_buf = realloc( storage->comp_buf, storage->comp_buf_size );
00871                                 storage->diff_buf = realloc( storage->diff_buf, storage->comp_buf_size*sizeof(ASStorageDiff) );
00872 #ifdef DEBUG_ALLOCS
00873                         show_debug( __FILE__,"compress_stored_data",__LINE__," realloced compression buffer to %d+%d*%d",storage->comp_buf_size, storage->comp_buf_size, sizeof(ASStorageDiff) );
00874 #endif 
00875                         }
00876                         buffer = storage->comp_buf ;
00877                         for( comp_size = 0 ; comp_size < size ; ++comp_size )
00878                                 buffer[comp_size] = (((CARD32)data[comp_size])*tint)>>8 ;
00879                 }        
00880         }       
00881         if( compressed_size ) 
00882                 *compressed_size = comp_size ;
00883         return buffer;
00884 }
00885 
00886 static CARD8 *
00887 decompress_stored_data( ASStorage *storage, CARD8 *data, int size, int uncompressed_size, 
00888                                                 ASFlagType flags, CARD8 bitmap_value )
00889 {
00890         CARD8  *buffer = data ;
00891 
00892         LOCAL_DEBUG_OUT( "size = %d, uncompressed_size = %d, flags = 0x%lX", size, uncompressed_size, flags );
00893         if( get_flags( flags, ASStorage_RLEDiffCompress ))
00894         {
00895                 buffer = storage->comp_buf ;
00896                 if( get_flags( flags, ASStorage_Bitmap ) )
00897                         rlediff_decompress_bitmap( buffer, data, size, bitmap_value );   
00898                 else                    
00899                         rlediff_decompress( buffer, data, size );        
00900                 /* need to check decompressed size */
00901         }
00902         
00903         return buffer;
00904 }
00905 
00906 static void
00907 add_storage_slots( ASStorageBlock *block )
00908 {
00909         int i = block->slots_count ;
00910         int size ;
00911         int count = AS_STORAGE_SLOTS_BATCH ;  
00912         LOCAL_DEBUG_OUT( "block = %p, block->slots = %p", block, block->slots );
00913         if( block->slots_count + count  >= AS_STORAGE_MAX_SLOTS_CNT ) 
00914         {
00915                 count = (int)AS_STORAGE_MAX_SLOTS_CNT - block->slots_count ; 
00916                 if( count < 0 ) 
00917                         return;
00918         }
00919         block->slots_count += count ; 
00920         size = block->slots_count*sizeof(ASStorageSlot*)  ;
00921         LOCAL_DEBUG_OUT( "block->slots_count = %d", block->slots_count );
00922 #ifndef DEBUG_ALLOCS
00923         LOCAL_DEBUG_OUT( "reallocing %d slots pointers (%d)", block->slots_count, size );
00924         block->slots = realloc( block->slots, size);
00925         LOCAL_DEBUG_OUT( "reallocated %d slots pointers", block->slots_count );
00926 #else
00927         if( block->slots == NULL ) 
00928                 show_debug( __FILE__,"add_storage_slots",__LINE__,"allocating %d slots pointers", block->slots_count );
00929         else
00930                 show_debug( __FILE__,"add_storage_slots",__LINE__,"reallocating %d slots pointers", block->slots_count );
00931         block->slots = guarded_realloc( block->slots, block->slots_count*sizeof(ASStorageSlot*));
00932 #endif
00933         UsedMemory += count*sizeof(ASStorageSlot*) ;
00934         memset( &(block->slots[i]),     0x00, count*sizeof(ASStorageSlot*) );
00935 }
00936 
00937 
00938 
00939 static ASStorageBlock *
00940 create_asstorage_block( int useable_size )
00941 {
00942         int allocate_size = (sizeof(ASStorageBlock)+ ASStorageSlot_SIZE + useable_size) ; 
00943         void *ptr ;     
00944         ASStorageBlock *block ;
00945 
00946         if( allocate_size%AS_STORAGE_PAGE_SIZE > 0 ) 
00947                 allocate_size = ((allocate_size/AS_STORAGE_PAGE_SIZE)+1)*AS_STORAGE_PAGE_SIZE ;
00948 #ifndef DEBUG_ALLOCS
00949         ptr = calloc(1,allocate_size);
00950 #else
00951         {
00952                 char msg[256];
00953                 ptr = guarded_calloc(1,allocate_size);
00954                 sprintf( msg, "allocated %d bytes, block = %p, total used = %d", allocate_size, ptr, UsedMemory + allocate_size );
00955                 PRINT_MEM_STATS(msg);
00956         }
00957 #endif
00958         UsedMemory += allocate_size ;
00959         if( ptr == NULL ) 
00960                 return NULL;
00961         block = ptr ;
00962         block->size = allocate_size - sizeof(ASStorageBlock) ;
00963         block->total_free = block->size - ASStorageSlot_SIZE ;
00964 
00965         block->slots_count = 0 ;
00966         add_storage_slots( block ) ;   
00967         
00968         if( block->slots == NULL ) 
00969         {       
00970                 free( ptr ); 
00971                 UsedMemory -= allocate_size ;
00972 #ifdef DEBUG_ALLOCS
00973                 show_debug( __FILE__,"create_asstorage_block",__LINE__,"freeing block %p, size = %d, total used = %d", ptr, allocate_size, UsedMemory );
00974 #endif
00975                 return NULL;
00976         }
00977         block->start = (ASStorageSlot*)((unsigned char*)ptr+((sizeof(ASStorageBlock)/ASStorageSlot_SIZE)+1)*ASStorageSlot_SIZE);
00978         block->end = (ASStorageSlot*)((unsigned char*)ptr+(allocate_size-ASStorageSlot_SIZE));
00979         block->slots[0] = block->start ;
00980         block->slots[0]->flags = 0 ;  /* slot of the free memory */ 
00981         block->slots[0]->ref_count = 0 ;
00982         block->slots[0]->size = ((CARD8*)(block->end) - (CARD8*)(block->start))-ASStorageSlot_SIZE ;
00983         block->slots[0]->uncompressed_size = block->slots[0]->size ;
00984         block->slots[0]->index = 0 ;
00985         block->last_used = 0;
00986         block->first_free = 0 ;
00987         
00988         LOCAL_DEBUG_OUT("Storage block created : block ptr = %p, slots ptr = %p", block, block->slots );
00989         
00990         return block;
00991 }
00992 
00993 static void
00994 destroy_asstorage_block( ASStorageBlock *block )
00995 {
00996         UsedMemory -= block->slots_count * sizeof(ASStorageSlot*) ;
00997         UsedMemory -= block->size + sizeof(ASStorageBlock) ;
00998 
00999 #ifndef DEBUG_ALLOCS
01000         free( block->slots );
01001         free( block );    
01002 #else   
01003         {
01004                 char msg[256];
01005                 sprintf( msg, "freeing block %p, size = %d, total used = %d", block, block->size, UsedMemory );
01006                 guarded_free( block->slots );
01007                 guarded_free( block );
01008                 PRINT_MEM_STATS(msg);
01009         }
01010 #endif
01011 
01012 }
01013 
01014 static int
01015 select_storage_block( ASStorage *storage, int compressed_size, ASFlagType flags, int block_id_start )
01016 {
01017         int i ;
01018         int new_block = -1 ; 
01019         compressed_size += ASStorageSlot_SIZE;
01020         i = block_id_start - 1 ;
01021         if( i < 0 ) 
01022                 i = 0 ;
01023         for( ; i < storage->blocks_count ; ++i ) 
01024         {
01025                 ASStorageBlock *block = storage->blocks[i];
01026                 if( block )
01027                 {       
01028                         if( block->total_free > compressed_size && 
01029                                 block->total_free > AS_STORAGE_NOUSE_THRESHOLD && 
01030                                 block->last_used+2 < AS_STORAGE_MAX_SLOTS_CNT  )
01031                                 return i+1;
01032                 }else if( new_block < 0 ) 
01033                         new_block = i ;
01034         }               
01035         /* no available blocks found - need to allocate a new block */
01036         if( new_block  < 0 ) 
01037         {
01038                 i = new_block = storage->blocks_count ;
01039                 storage->blocks_count += 16 ;
01040 #ifndef DEBUG_ALLOCS
01041                 storage->blocks = realloc( storage->blocks, storage->blocks_count*sizeof(ASStorageBlock*));
01042 #else
01043                 storage->blocks = guarded_realloc( storage->blocks, storage->blocks_count*sizeof(ASStorageBlock*));
01044                 show_debug( __FILE__,"select_storage_block",__LINE__,"reallocated %d blocks pointers", storage->blocks_count );
01045 #endif             
01046                 UsedMemory += 16*sizeof(ASStorageBlock*) ;
01047 
01048                 while( ++i < storage->blocks_count )
01049                         storage->blocks[i] = NULL ;
01050         }        
01051         storage->blocks[new_block] = create_asstorage_block( max(storage->default_block_size, compressed_size) );               
01052         if( storage->blocks[new_block] == NULL )  /* memory allocation failed ! */ 
01053                 new_block = -1 ;
01054         return new_block+1;
01055 }
01056 
01057 static inline void
01058 destroy_storage_slot( ASStorageBlock *block, int index )
01059 {
01060         ASStorageSlot **slots = block->slots ;
01061         int i = index;
01062         
01063 /*      if( i < block->first_free ) 
01064                 block->first_free = i ;
01065  */
01066         slots[i] = NULL ; 
01067         if( block->last_used == index ) 
01068         {       
01069                 while( --i > 0 ) 
01070                 {       
01071                         if( slots[i] != NULL ) 
01072                                 break;
01073                         --(block->unused_count);
01074                 }
01075                 block->last_used = i<0?0:i;      
01076         }else if( index < block->last_used ) 
01077                 ++(block->unused_count);
01078 }
01079 
01080 static inline void 
01081 join_storage_slots( ASStorageBlock *block, ASStorageSlot *from_slot, ASStorageSlot *to_slot )
01082 {
01083         ASStorageSlot *s, *next = AS_STORAGE_GetNextSlot(from_slot);
01084 
01085         from_slot->size = ASStorageSlot_USABLE_SIZE(from_slot); 
01086         do
01087         {
01088                 s = next ;
01089                 next = AS_STORAGE_GetNextSlot(s);
01090                 from_slot->size += ASStorageSlot_FULL_SIZE(s) ; 
01091                 LOCAL_DEBUG_OUT( "from  = %p, s = %p, next = %p, to = %p, from->size = %ld", from_slot, s, next, to_slot, from_slot->size );
01092                 destroy_storage_slot( block, s->index );
01093         }while( s < to_slot );  
01094 }
01095 
01096 
01097 static inline void
01098 defragment_storage_block( ASStorageBlock *block )
01099 {
01100         ASStorageSlot *brk, *next_used, **slots = block->slots ;
01101         int i, first_free = -1;
01102         unsigned long total_free = 0 ;
01103         brk = next_used = block->start ; 
01104         
01105         
01106         for( i = 0 ; i <= block->last_used ; ++i ) 
01107         {
01108                 if( slots[i] ) 
01109                         if( slots[i]->flags == 0 ) 
01110                                 slots[i] = NULL ;
01111                 if( slots[i] == NULL ) 
01112                 {
01113                         if( first_free < 0 ) 
01114                                 first_free = i ;
01115                 }
01116         }
01117         while( --i > 0 ) 
01118                 if( slots[i] != NULL ) 
01119                         break;
01120         block->last_used = i ;
01121                                                                 
01122         while( brk < block->end ) 
01123         {       
01124                 ASStorageSlot *used = next_used;
01125                 while( used < block->end && used->flags == 0 ) 
01126                         used = AS_STORAGE_GetNextSlot(used);
01127                 LOCAL_DEBUG_OUT("brk = %p, used = %p, end = %p", brk, used, block->end );
01128                 if( used >= block->end || next_used > block->end) 
01129                 {
01130                         total_free = (unsigned long)((CARD8*)block->end - (CARD8*)brk);
01131                         if( total_free < ASStorageSlot_SIZE ) 
01132                                 total_free = 0 ;
01133                         else
01134                                 total_free -= ASStorageSlot_SIZE ;      
01135                         break;
01136                 }else
01137                         next_used = AS_STORAGE_GetNextSlot(used);
01138 
01139                 LOCAL_DEBUG_OUT("used = %p, used->size = %ld", used,used->size );
01140                 if( next_used < block->end ) 
01141                 {
01142                         LOCAL_DEBUG_OUT("next_used = %p, next_used->size = %ld", 
01143                                                         next_used, next_used->size );
01144                 }
01145                 if( used != brk )
01146                 {/* can't use memcpy as regions may overlap */
01147                         int size = (ASStorageSlot_FULL_SIZE(used))/4;
01148                         register CARD32 *from = (CARD32*)used ;
01149                         register CARD32 *to = (CARD32*)brk ;
01150                         for( i = 0 ; i < size ; ++i ) 
01151                                 to[i] = from[i];
01152                 }       
01153                 /* updating pointer : */        
01154                 slots[brk->index] = brk ;
01155                 LOCAL_DEBUG_OUT("brk = %p, brk->size = %ld, index = %d", brk, brk->size, brk->index );
01156                 brk = AS_STORAGE_GetNextSlot(brk);
01157         }
01158         
01159         if( total_free > 0 )
01160         {
01161                 if( first_free < 0  ) 
01162                 {
01163                         if( ++block->last_used >= block->slots_count ) 
01164                                 add_storage_slots( block );     
01165                         first_free = block->last_used ;
01166                 }
01167                 brk->flags = 0 ;
01168                 brk->size = total_free ; 
01169                 brk->uncompressed_size = total_free ;
01170                 brk->ref_count = 0 ;
01171                 brk->index = first_free ; 
01172                 block->first_free = first_free ;
01173                 
01174                 LOCAL_DEBUG_OUT("brk = %p, brk->size = %ld, index = %d, first_free = %d", 
01175                                                  brk, brk->size, brk->index, first_free );
01176                 
01177                 block->slots[first_free] = brk ;
01178                 if( block->last_used < first_free ) 
01179                         block->last_used = first_free ;
01180         }
01181         
01182         block->total_free = total_free ;
01183         LOCAL_DEBUG_OUT( "total_free after defrag = %ld, first_free = %d, last_used = %d", total_free, block->first_free, block->last_used );
01184         
01185         slots = block->slots ;
01186         for( i = 0 ; i <= block->last_used ; ++i ) 
01187                 if( slots[i] )
01188                         if( slots[i]->index != i ) 
01189                         {
01190                                 LOCAL_DEBUG_OUT( "Storage Integrity check failed - block = %p, index = %d", block, i ) ;        
01191                                 exit(0);
01192                         }
01193         block->unused_count = 0 ;
01194         for( i = 0 ; i < block->last_used ; ++i ) 
01195         {
01196                 if( slots[i] == NULL ) 
01197                         ++(block->unused_count);
01198         }
01199 }
01200 
01201 static ASStorageSlot *
01202 select_storage_slot( ASStorageBlock *block, int size )
01203 {
01204         int i = block->first_free ;
01205         LOCAL_DEBUG_OUT( "first_free = %d, last_used = %d, long_searches = %d", block->first_free, block->last_used, block->long_searches );
01206         if( block->long_searches < 5 ) 
01207         {       
01208                 int max_i = block->last_used ;
01209                 ASStorageSlot **slots = block->slots ;
01210                 int empty_slots_checked = 0 ;
01211 
01212                 if( max_i > i + 50 ) 
01213                         max_i = i+50 ; 
01214                 
01215                 while( i <= max_i )
01216                 {
01217                         ASStorageSlot *slot = slots[i] ;
01218                         LOCAL_DEBUG_OUT( "block = %p, max_i = %d, slots[%d] = %p", block, max_i, i, slot );
01219                         if( slot != NULL )
01220                         {
01221                                 if( slot->flags == 0 )
01222                                 {         
01223                                         int single_slot_size = size+ASStorageSlot_SIZE ; 
01224                                         int size_to_match = single_slot_size+ASStorageSlot_SIZE ;
01225                                         ++empty_slots_checked ;
01226                                         
01227                                         do
01228                                         {
01229                                                 ASStorageSlot *next_slot = AS_STORAGE_GetNextSlot(slot);                   
01230                                                 if( next_slot > block->end )
01231                                                         break;
01232 
01233                                                 LOCAL_DEBUG_OUT( "start = %p, slot = %p, slot->size = %ld, end = %p, size = %d, size_to_match = %d", block->start, slot, slot->size, block->end, size, size_to_match );
01234                                                 if((int)ASStorageSlot_USABLE_SIZE(slot) >= single_slot_size )
01235                                                 {       
01236                                                         if( empty_slots_checked > 50 ) ++(block->long_searches);
01237                                                         return slot;
01238                                                 }
01239                                                 if( (int)ASStorageSlot_FULL_SIZE(slot)  >= size_to_match )
01240                                                 {
01241                                                         join_storage_slots( block, slots[i], slot );
01242                                                         if( empty_slots_checked > 50 ) ++(block->long_searches);
01243                                                         return slots[i];
01244                                                 }       
01245                                                 size_to_match -= ASStorageSlot_FULL_SIZE(slot);
01246                                                 slot = next_slot;               
01247                                                 /* make sure we has not exceeded boundaries of the block */                                                                        
01248                                         }while( slot->flags == 0 );
01249                                 }
01250                         }
01251                         ++i ;
01252                 }
01253         }
01254                 
01255         /* no free slots of sufficient size - need to do defragmentation */
01256         defragment_storage_block( block );
01257         block->long_searches = 0 ;
01258         i = block->first_free;
01259         if( i >= block->slots_count ) 
01260                 return NULL;
01261     if( block->slots[i] == NULL || (int)block->slots[i]->size < size ) 
01262                 return NULL;
01263         return block->slots[i];            
01264 }
01265 
01266 static inline Bool
01267 split_storage_slot( ASStorageBlock *block, ASStorageSlot *slot, int to_size )
01268 {
01269         int old_size = ASStorageSlot_USABLE_SIZE(slot) ;
01270         ASStorageSlot *new_slot ;
01271 
01272         LOCAL_DEBUG_OUT( "slot->size = %ld", slot->size );
01273         
01274         slot->size = to_size ; 
01275         
01276         if( old_size <= (int)ASStorageSlot_USABLE_SIZE(slot) )
01277                 return True;
01278 
01279         new_slot = AS_STORAGE_GetNextSlot(slot);
01280 
01281         LOCAL_DEBUG_OUT( "new_slot = %p, slot = %p, slot->size = %ld", new_slot, slot, slot->size );
01282 
01283         if( new_slot >=  block->end )
01284                 return True;
01285 
01286         new_slot->flags = 0 ;
01287         new_slot->ref_count = 0 ;
01288         LOCAL_DEBUG_OUT( "old_size = %d, full_size = %ld", old_size, ASStorageSlot_FULL_SIZE(slot) );
01289         new_slot->size = old_size - ASStorageSlot_FULL_SIZE(slot) ;                                                                                        
01290         new_slot->uncompressed_size = 0 ;
01291         
01292         new_slot->index = 0 ;
01293         /* now we need to find where this slot's pointer we should store */                
01294         if( block->unused_count < block->slots_count/10 && block->last_used < block->slots_count-1 )
01295         {       
01296                 new_slot->index = ++(block->last_used) ;
01297         }else
01298         {
01299                 register int i, max_i = block->slots_count ;
01300                 register ASStorageSlot **slots = block->slots ;
01301                 LOCAL_DEBUG_OUT( "max_i = %d", max_i );
01302                 
01303                 for( i = 0 ; i < max_i ; ++i ) 
01304                         if( slots[i] == NULL ) 
01305                                 break;
01306                 LOCAL_DEBUG_OUT( "i = %d", i );
01307                 if( i >= max_i ) 
01308                 {
01309                         if( block->slots_count >= AS_STORAGE_MAX_SLOTS_CNT )
01310                                 return False;
01311                         else
01312                         {
01313                                 i = block->slots_count ;
01314                                 block->last_used = i ;
01315                                 add_storage_slots( block );
01316                                 slots = block->slots ;
01317                         }        
01318                 }
01319                 LOCAL_DEBUG_OUT( "i = %d", i );
01320                 new_slot->index = i ;           
01321                 if( i < block->last_used )
01322                 {
01323                         if( block->unused_count <= 0 ) 
01324                                 show_warning( "Storage error : unused_count out of range (%d )", block->unused_count );
01325                         else                                      
01326                                 --(block->unused_count);
01327                 }
01328         }       
01329         LOCAL_DEBUG_OUT( "new_slot = %p, new_slot->index = %d, new_slot->size = %ld", new_slot, new_slot->index, new_slot->size );
01330         block->slots[new_slot->index] = new_slot ;
01331         return True;
01332 }
01333 
01334 static int
01335 store_data_in_block( ASStorageBlock *block, CARD8 *data, int size, int compressed_size, int ref_count, ASFlagType flags )
01336 {
01337         ASStorageSlot *slot ;
01338         CARD8 *dst ;
01339         Bool bad_slot = True ;
01340         slot = select_storage_slot( block, compressed_size );
01341         LOCAL_DEBUG_OUT( "selected slot %p for size %d (compressed %d) and flags %lX", slot, size, compressed_size, flags );
01342         
01343         if( slot == NULL ) 
01344                 return 0;           /* not a error condition */
01345         else if( slot > block->end || slot < block->start) 
01346                 show_error( "storage slot selected falls outside of allocated memory. Slot = %p, start = %p, end = %p", slot, block->start, block->end );
01347         else if( &(ASStorage_Data(slot)[slot->size]) > ((CARD8*)(block->start)) + block->size) 
01348                 show_error( "storage slot's size falls outside of allocated memory. Slot->data[slot->size] = %p, end = %p, size = %d", &(ASStorage_Data(slot)[slot->size]), ((CARD8*)(block->start)) + block->size, slot->size );
01349         else if( slot->index >= block->slots_count ) 
01350                 show_error( "storage slot index falls out of range. Index = %d, slots_count = %d", slot->index, block->slots_count );
01351         else
01352                 bad_slot = False ;
01353         
01354         if( bad_slot )
01355         {
01356                 show_error( "\t data = %p, size = %d, compressed_size = %d, ref_count = %d, flags = 0x%lX", block, data, size, compressed_size, ref_count, flags        );
01357                 show_error( "\t block = %p, : {size:%d, total_free:%d, slots_count:%d, unused_count:%d, first_free:%d, last_used:%d}", block, block->size, block->total_free, block->slots_count, block->unused_count, block->first_free, block->last_used );
01358                 if( slot ) 
01359                         show_error( "\t slot = %p : {flags:0x%X, ref_count:%u, size:%lu, uncompr_size:%lu, index:%u}", slot,
01360                                                 slot->flags, slot->ref_count, slot->size, slot->uncompressed_size, slot->index );
01361                 return 0;
01362         }                         
01363                 
01364         LOCAL_DEBUG_OUT( "block = %p", block );
01365         if( !split_storage_slot( block, slot, compressed_size ) ) 
01366         {
01367                 show_error( "failed to split storage to store data in block. Usable size = %d, desired size = %d", ASStorageSlot_USABLE_SIZE(slot), compressed_size+ASStorageSlot_SIZE );
01368                 return 0 ;
01369         }
01370         LOCAL_DEBUG_OUT( "block = %p", block );
01371         block->total_free -= ASStorageSlot_FULL_SIZE(slot);
01372         
01373         dst = ASStorage_Data(slot);
01374         LOCAL_DEBUG_OUT( "dst = %p, compressed_size = %d", dst, compressed_size );
01375         memcpy( dst, data, compressed_size );
01376         slot->flags = (unsigned short)(flags | ASStorage_Used) ;
01377         slot->ref_count = ref_count;
01378         slot->size = compressed_size ;
01379         slot->uncompressed_size = size ;
01380 
01381         if( slot->index == block->first_free ) 
01382         {
01383                 int i = block->first_free ;
01384                 while( ++i <= block->last_used ) 
01385                         if( block->slots[i] && 
01386                                 block->slots[i]->flags == 0 && block->slots[i]->size > 0 ) 
01387                                 break;
01388                 block->first_free = i ;
01389         }
01390 
01391         LOCAL_DEBUG_OUT( "slot index = %d", slot->index );
01392  
01393         return slot->index+1 ;
01394 }
01395 
01396 
01397 static ASStorageID 
01398 store_compressed_data( ASStorage *storage, CARD8* data, int size, int compressed_size, int ref_count, ASFlagType flags )
01399 {
01400         int id = 0 ;
01401         int block_id = 0;
01402         
01403         do
01404         {       
01405                 block_id = select_storage_block( storage, compressed_size, flags, block_id );
01406                 LOCAL_DEBUG_OUT( "selected block %d", block_id );
01407                 if( block_id > 0 ) 
01408                 {
01409                         int slot_id = store_data_in_block(  storage->blocks[block_id-1], 
01410                                                                                                 data, size, 
01411                                                                                                 compressed_size, ref_count, flags );
01412 
01413                         LOCAL_DEBUG_OUT( "slot id %X", slot_id );
01414                         if( slot_id > 0 )       
01415                                 id = make_asstorage_id( block_id, slot_id );
01416                         else
01417                                 if( storage->blocks[block_id-1]->total_free >= compressed_size+ASStorageSlot_SIZE  ) 
01418                                 {
01419                                         show_error( "failed to store data in block. Total free size = %d, desired size = %d", storage->blocks[block_id-1]->total_free, compressed_size+ASStorageSlot_SIZE );
01420                                         break;
01421                                 }
01422                 }
01423         }while( block_id != 0 && id == 0 );
01424         return id ;             
01425 }         
01426 
01427 
01428 
01429 
01430 static inline ASStorageBlock *
01431 find_storage_block( ASStorage *storage, ASStorageID id )
01432 {       
01433         int block_idx = StorageID2BlockIdx(id);
01434         if( block_idx >= 0 && block_idx < storage->blocks_count )  
01435                 return storage->blocks[block_idx];
01436         return NULL ;
01437 }
01438 
01439 static inline ASStorageSlot *
01440 find_storage_slot( ASStorageBlock *block, ASStorageID id )
01441 {       
01442         if( block != NULL ) 
01443         {
01444                 int slot_idx = StorageID2SlotIdx(id);
01445                 if( slot_idx >= 0 && slot_idx < block->slots_count ) 
01446                 {
01447                         if( block->slots[slot_idx] && block->slots[slot_idx]->flags != 0 )
01448                                 return block->slots[slot_idx];
01449                 }
01450         }       
01451         return NULL ;
01452 }
01453 
01454 static inline void 
01455 free_storage_slot( ASStorageBlock *block, ASStorageSlot *slot)
01456 {
01457         slot->flags = 0 ;
01458         block->total_free += ASStorageSlot_USABLE_SIZE(slot) ;
01459 }        
01460 
01461 static Bool 
01462 is_block_empty( ASStorageBlock *block)
01463 {
01464         int i = block->last_used+1;
01465         ASStorageSlot **slots = block->slots ;
01466         while( --i >= 0 ) 
01467         {
01468                 if( slots[i] )
01469                         if( slots[i]->flags != 0 ) 
01470                                 return False;    
01471         }       
01472         return True;    
01473 }        
01474 
01475 static void 
01476 free_storage_block( ASStorage *storage, int block_idx  )
01477 {
01478         ASStorageBlock *block = storage->blocks[block_idx] ;
01479         storage->blocks[block_idx] = NULL ;
01480         destroy_asstorage_block( block );
01481 }        
01482 
01483 static ASStorageSlot *
01484 convert_slot_to_ref( ASStorage *storage, ASStorageID id )       
01485 {
01486         int block_idx = StorageID2BlockIdx(id);
01487         ASStorageBlock *block;
01488         ASStorageID target_id = 0;
01489         int slot_id = 0 ;
01490         int ref_index, body_index ;
01491         ASStorageSlot *ref_slot, *body_slot ;
01492         
01493         block = find_storage_block(storage, id);
01494         
01495         LOCAL_DEBUG_OUT( "block = %p, block->total_free = %d", block, block->total_free );
01496         /* Two strategies here - 1 - the fast one - we try to allocate new slot 
01497          * and avoid copying the body of the data over - we can do that only if
01498          * there is enough space in its block, otherwise we have to relocate it 
01499          * into different block, which is slower.
01500          */
01501         if( block->total_free > sizeof(ASStorageID))
01502         {       
01503                 slot_id = store_data_in_block(  block, (CARD8*)&target_id, 
01504                                                                                 sizeof(ASStorageID), sizeof(ASStorageID), 0, 
01505                                                                                 ASStorage_Reference );
01506         }
01507         LOCAL_DEBUG_OUT( "block = %p, block->total_free = %d, slot_id = 0x%X", block, block->total_free, slot_id );
01508         
01509         if( slot_id > 0 )
01510         {       /* We can use fast strategy : now we need to swap contents of the slots */
01511                 ref_index = slot_id-1 ;
01512                 ref_slot = block->slots[ref_index] ;
01513         
01514                 body_index = StorageID2SlotIdx(id) ; 
01515                 body_slot = block->slots[body_index] ;
01516         
01517                 block->slots[ref_index] = body_slot ;
01518                 body_slot->index = ref_index ;
01519 
01520                 block->slots[body_index] = ref_slot ; 
01521                 ref_slot->index = body_index ;
01522 
01523                 target_id = make_asstorage_id( block_idx+1, slot_id );
01524                 if( target_id == id ) 
01525                 {
01526                         show_error( "Reference ID is the same as target_id: id = %lX, slot_id = %d", id, slot_id );
01527 #ifndef NO_DEBUG_OUTPUT
01528                         {       int *a = NULL ; *a = 0 ;}
01529 #endif                                             
01530                 }
01531                 /* don't increment refcount, becouse we oonly have one published reference to it so far */
01532                 /* ++(body_slot->ref_count); */
01533         }else
01534         {/* otherwise we have to relocate the actuall body into a different block, 
01535           * which is somewhat tricky : */
01536                 ref_index = StorageID2SlotIdx(id); ;
01537                 ref_slot = block->slots[ref_index] ;
01538                 
01539                 if( block->total_free > (int)ref_slot->size )
01540                 {
01541                         /* there is a danger of us trying to reuse same block and defragmented it in between,
01542                          * which will screw up the data */
01543 #ifndef NO_DEBUG_OUTPUT
01544                         fprintf( stderr, "\t\t %s:%d DANGEROUS RELOCATION! size = %ld",  __FILE__, __LINE__, ref_slot->size );
01545 #endif                                             
01546                         memcpy( storage->comp_buf, ASStorage_Data(ref_slot), ref_slot->size );
01547                         target_id = store_compressed_data(  storage, storage->comp_buf, 
01548                                                                                                 ref_slot->uncompressed_size, 
01549                                                                                                 ref_slot->size, ref_slot->ref_count, ref_slot->flags );
01550                 }else    
01551                         target_id = store_compressed_data( storage, ASStorage_Data(ref_slot), 
01552                                                                                         ref_slot->uncompressed_size, 
01553                                                                                         ref_slot->size, ref_slot->ref_count, ref_slot->flags );
01554                 /* lets do this again, in case block was defragmented */
01555                 ref_slot = block->slots[ref_index] ;
01556 
01557                 if( target_id == 0 ) 
01558                         return NULL;            
01559                 if( target_id == id ) 
01560                 {       
01561                         show_error( "Reference ID is the same as target_id: id = %lX" );
01562 #ifndef NO_DEBUG_OUTPUT
01563                         {       int *a = NULL ; *a = 0 ;}
01564 #endif                                             
01565                 }
01566                 
01567                 split_storage_slot( block, ref_slot, sizeof(ASStorageID));
01568                 ref_slot->uncompressed_size = sizeof(ASStorageID) ; 
01569                 set_flags( ref_slot->flags, ASStorage_Reference );
01570                 clear_flags( ref_slot->flags, ASStorage_CompressionType );
01571         }        
01572         memcpy( ASStorage_Data(ref_slot), (CARD8*)&target_id, sizeof(ASStorageID));                              
01573 
01574         return ref_slot;
01575 }
01576 
01577 typedef struct 
01578 {
01579         int offset ; 
01580         void *buffer ;
01581         
01582         unsigned int threshold ;
01583         int start, end, runs_count ;
01584 }ASStorageDstBuffer;
01585 
01586 typedef void (*data_cpy_func_type)(ASStorageDstBuffer *, void *, size_t);
01587 
01588 static void card8_card8_cpy( ASStorageDstBuffer *dst, void *src, size_t size)
01589 {
01590         register CARD8 *dst8 = (CARD8*)dst->buffer ;
01591         dst8 += dst->offset ;
01592         memcpy( dst8, src, size );
01593 }        
01594 
01595 
01596 static void card8_card32_cpy( ASStorageDstBuffer *dst, void *src, size_t size)
01597 {
01598         register CARD32 *dst32 = (CARD32*)dst->buffer + dst->offset ;
01599         register CARD8  *src8  = (CARD8*)src ;
01600         register int i;
01601         for( i = 0 ;  i < (int)size ; ++i ) 
01602                 dst32[i] = src8[i] ;
01603 }        
01604 
01605 static void 
01606 card8_threshold( ASStorageDstBuffer *dst, void *src, size_t size)
01607 {
01608         CARD8 *src8 = src ;
01609         unsigned int *runs = (unsigned int*)(dst->buffer) ;
01610         int runs_count = dst->runs_count ;
01611         unsigned int threshold = dst->threshold ;
01612         int start = dst->start, end = dst->end;
01613         int i = 0;
01614 
01615 #ifdef DEBUG_THRESHOLD    
01616         fprintf( stderr, "card8_threshold:enter: start = %d, end = %d, runs_count = %d, size = %d\n", 
01617                          start, end, runs_count, size );
01618 #endif
01619 
01620         while( i < (int)size ) 
01621         {
01622                 if( end < start ) 
01623                 {
01624                         while( i < (int)size && src8[i] < threshold ) 
01625                                 ++i ;
01626                         start = i ;
01627                 }        
01628 #ifdef DEBUG_THRESHOLD    
01629                 fprintf( stderr, "card8_threshold:1: start = %d, end = %d, i = %d\n", start, end, i );
01630 #endif
01631                 
01632                 if( i < (int)size ) 
01633                 {       
01634                         while( i < (int)size && src8[i] >= threshold ) 
01635                                 ++i ;
01636                         end = i-1 ;
01637                 }
01638 #ifdef DEBUG_THRESHOLD    
01639                 fprintf( stderr, "card8_threshold:2: start = %d, end = %d, i = %d\n", start, end, i );
01640 #endif
01641                 
01642                 if( start >= 0 && end >= start )
01643                 {
01644                         runs[runs_count] = start ;
01645                         ++runs_count;
01646                         runs[runs_count] = end ;
01647                         ++runs_count ;
01648 #ifdef DEBUG_THRESHOLD    
01649                         fprintf( stderr, "card8_threshold:3: runs_count = %d\n", runs_count );
01650 #endif
01651                         end = -1 ;
01652                 }
01653         }
01654 #ifdef DEBUG_THRESHOLD    
01655         fprintf( stderr, "card8_threshold:exit: start = %d, end = %d, runs_count = %d, size = %d\n", 
01656                          start, end, runs_count, size );
01657 #endif
01658         dst->runs_count = runs_count ;
01659         dst->start = start ; 
01660         dst->end = end ;
01661 }        
01662 
01663 static int  
01664 fetch_data_int( ASStorage *storage, ASStorageID id, ASStorageDstBuffer *buffer, int offset, int buf_size, CARD8 bitmap_value, 
01665                                 data_cpy_func_type cpy_func, int *original_size)
01666 {
01667         ASStorageSlot *slot = find_storage_slot( find_storage_block( storage, id ), id );
01668         LOCAL_DEBUG_OUT( "slot = %p", slot );
01669         if( slot && buffer && buf_size > 0 )
01670         {
01671                 int uncomp_size = slot->uncompressed_size ;
01672                 *original_size = uncomp_size ;
01673                 if( get_flags( slot->flags, ASStorage_Reference) )
01674                 {
01675                         ASStorageID target_id = 0;
01676                         memcpy( &target_id, ASStorage_Data(slot), sizeof( ASStorageID ));                                  
01677                         LOCAL_DEBUG_OUT( "target_id = %lX", target_id );
01678                         if( target_id != 0 ) 
01679                                 return fetch_data_int(storage, target_id, buffer, offset, buf_size, bitmap_value, cpy_func, original_size);
01680                         else
01681                                 return 0;
01682                 }        
01683 
01684                 LOCAL_DEBUG_OUT( "flags = %X, index = %d, size = %ld, uncompressed_size = %d", 
01685                                                         slot->flags, slot->index, slot->size, uncomp_size );
01686                 if( bitmap_value == 0 ) 
01687                         bitmap_value = AS_STORAGE_DEFAULT_BMAP_VALUE ;
01688 
01689                 {
01690                         CARD8 *tmp = decompress_stored_data( storage, ASStorage_Data(slot), slot->size,
01691                                                                                                         uncomp_size, slot->flags, bitmap_value );
01692                         while( offset > uncomp_size ) offset -= uncomp_size ; 
01693                         while( offset < 0 ) offset += uncomp_size ; 
01694                         
01695                         if( get_flags( slot->flags, ASStorage_NotTileable ) )
01696                                 if( buf_size > uncomp_size - offset ) 
01697                                         buf_size = uncomp_size - offset ;
01698                         if( offset > 0 ) 
01699                         {
01700                                 int to_copy = uncomp_size-offset ; 
01701                                 if( to_copy > buf_size ) 
01702                                         to_copy = buf_size ;
01703                                 cpy_func( buffer, tmp+offset, to_copy );                                                                                                                        
01704                                 buffer->offset = to_copy ;
01705                         }
01706                         LOCAL_DEBUG_OUT( "offset = %d", buffer->offset );
01707                         while( buffer->offset < buf_size ) 
01708                         {
01709                                 int to_copy = buf_size - buffer->offset ; 
01710                                 if( to_copy > uncomp_size ) 
01711                                         to_copy = uncomp_size ;
01712                                 cpy_func( buffer, tmp, to_copy );                                                                                                                       
01713                                 buffer->offset += to_copy;
01714                         }
01715                 }
01716                 LOCAL_DEBUG_OUT( "uncompressed_size = %d", buffer->offset );
01717                 return buffer->offset ;
01718         }
01719         return 0;
01720 }
01721 
01722 /************************************************************************/
01723 /* Public Functions :                                                                                                   */
01724 /************************************************************************/
01725 ASStorage *
01726 create_asstorage()
01727 {
01728 #ifndef DEBUG_ALLOCS
01729         ASStorage *storage = calloc(1, sizeof(ASStorage));
01730 #else
01731         ASStorage *storage = guarded_calloc(1, sizeof(ASStorage));
01732 #endif
01733         UsedMemory += sizeof(ASStorage) ;
01734         if( storage )
01735                 storage->default_block_size = AS_STORAGE_DEF_BLOCK_SIZE ;
01736         return storage ;
01737 }
01738 
01739 int 
01740 set_asstorage_block_size( ASStorage *storage, int new_size )
01741 {
01742         int old_size ;
01743         
01744         if( storage == NULL ) 
01745                 storage = get_default_asstorage();
01746         
01747         old_size = storage->default_block_size ; 
01748 #if 1
01749         if( new_size > AS_STORAGE_DEF_BLOCK_SIZE ) 
01750                 storage->default_block_size = new_size; 
01751         else
01752                 storage->default_block_size = AS_STORAGE_DEF_BLOCK_SIZE; 
01753 #endif
01754         return old_size;
01755 }
01756 
01757 void 
01758 destroy_asstorage(ASStorage **pstorage)
01759 {
01760         ASStorage *storage = *pstorage ;
01761         
01762         if( storage ) 
01763         {       
01764                 if( storage->blocks != NULL && storage->blocks_count  > 0 )
01765                 {
01766                         int i ;
01767                         for( i = 0 ; i < storage->blocks_count ; ++i ) 
01768                                 if( storage->blocks[i] ) 
01769                                         destroy_asstorage_block( storage->blocks[i] );
01770                         UsedMemory -= storage->blocks_count * sizeof(ASStorageBlock*) ;
01771 #ifndef DEBUG_ALLOCS
01772                         free( storage->blocks );
01773 #else   
01774                         guarded_free( storage->blocks );
01775 #endif
01776 
01777                 }       
01778                 if( storage->comp_buf )
01779                         free( storage->comp_buf);
01780                 if( storage->diff_buf )
01781                         free( storage->diff_buf);
01782 
01783                 UsedMemory -= sizeof(ASStorage) ;
01784 #ifndef DEBUG_ALLOCS
01785                 free( storage );
01786 #else   
01787                 guarded_free( storage );
01788 #endif
01789                 *pstorage = NULL;
01790         }
01791 }
01792 
01793 void 
01794 flush_default_asstorage()
01795 {
01796         if( _as_default_storage != NULL )
01797                 destroy_asstorage(&_as_default_storage);
01798 }
01799 
01800 ASStorageID 
01801 store_data(ASStorage *storage, CARD8 *data, int size, ASFlagType flags, CARD8 bitmap_threshold)
01802 {
01803         int compressed_size = size ;
01804         CARD8 *buffer = data;
01805         CARD32 bitmap_threshold32 = bitmap_threshold ;
01806 
01807         if( storage == NULL ) 
01808                 storage = get_default_asstorage();
01809 
01810         LOCAL_DEBUG_CALLER_OUT( "data = %p, size = %d, flags = %lX", data, size, flags );
01811         if( size <= 0 || data == NULL || storage == NULL ) 
01812                 return 0;
01813         if( get_flags( flags, ASStorage_Bitmap ) )
01814         {
01815                 if( bitmap_threshold32 == 0 ) 
01816                         bitmap_threshold32 = AS_STORAGE_DEFAULT_BMAP_THRESHOLD ;
01817         }else
01818                 bitmap_threshold32 = 0x000000FF ;  /* to disable the tint ! */ 
01819                          
01820         if( !get_flags(flags, ASStorage_Reference))
01821                 if( get_flags( flags, ASStorage_CompressionType ) || get_flags( flags, ASStorage_32Bit ) )
01822                         buffer = compress_stored_data( storage, data, size, &flags, &compressed_size, bitmap_threshold32 );
01823         
01824         return store_compressed_data( storage, buffer, 
01825                                                                   get_flags( flags, ASStorage_32Bit )?size/4:size, 
01826                                                                   compressed_size, 0, flags );
01827 }
01828 
01829 ASStorageID 
01830 store_data_tinted(ASStorage *storage, CARD8 *data, int size, ASFlagType flags, CARD16 tint)
01831 {
01832         int compressed_size = size ;
01833         CARD8 *buffer = data;
01834         CARD32 tint32 = tint ;
01835 
01836         if( storage == NULL ) 
01837                 storage = get_default_asstorage();
01838 
01839         LOCAL_DEBUG_CALLER_OUT( "data = %p, size = %d, flags = %lX", data, size, flags );
01840         if( size <= 0 || data == NULL || storage == NULL ) 
01841                 return 0;
01842         
01843         if( get_flags( flags, ASStorage_Bitmap ) )
01844         {
01845                 if( tint32 == 0 ) 
01846                         tint32 = 0x000000FF ;
01847                 else
01848                         tint32 = (tint32 * AS_STORAGE_DEFAULT_BMAP_THRESHOLD) >>8 ;
01849         }
01850         
01851         if( !get_flags(flags, ASStorage_Reference))
01852                 if( get_flags( flags, ASStorage_CompressionType ) || get_flags( flags, ASStorage_32Bit ) )
01853                         buffer = compress_stored_data( storage, data, size, &flags, &compressed_size, tint32 );
01854         
01855         return store_compressed_data( storage, buffer, 
01856                                                                   get_flags( flags, ASStorage_32Bit )?size/4:size, 
01857                                                                   compressed_size, 0, flags );
01858 }
01859 
01860 
01861 int  
01862 fetch_data(ASStorage *storage, ASStorageID id, CARD8 *buffer, int offset, int buf_size, CARD8 bitmap_value, int *original_size)
01863 {
01864         int dumm ; 
01865         if( storage == NULL ) 
01866                 storage = get_default_asstorage();
01867 
01868         if( original_size == NULL ) 
01869                 original_size = &dumm ;
01870         *original_size = 0;
01871         if( storage != NULL && id != 0 )
01872         {       
01873                 ASStorageDstBuffer buf ; 
01874                 buf.offset = 0 ; 
01875                 buf.buffer = buffer ;
01876                 return fetch_data_int( storage, id, &buf, offset, buf_size, bitmap_value, card8_card8_cpy, original_size );
01877         }
01878         return 0 ;       
01879 }
01880 
01881 int  
01882 fetch_data32(ASStorage *storage, ASStorageID id, CARD32 *buffer, int offset, int buf_size, CARD8 bitmap_value, int *original_size)
01883 {
01884         int dumm ;
01885         if( storage == NULL ) 
01886                 storage = get_default_asstorage();
01887         
01888         if( original_size == NULL ) 
01889                 original_size = &dumm ;
01890         *original_size = 0;
01891         if( storage != NULL && id != 0 )
01892         {
01893                 ASStorageDstBuffer buf ; 
01894                 buf.offset = 0 ; 
01895                 buf.buffer = buffer ;
01896                 
01897                 return fetch_data_int( storage, id, &buf, offset, buf_size, bitmap_value, card8_card32_cpy, original_size );
01898         }
01899         return 0 ;      
01900 }
01901 
01902 int  
01903 threshold_stored_data(ASStorage *storage, ASStorageID id, unsigned int *runs, int width, unsigned int threshold)
01904 {
01905         if( storage == NULL ) 
01906                 storage = get_default_asstorage();
01907         
01908         if( storage != NULL && id != 0 )
01909         {
01910                 ASStorageDstBuffer buf ; 
01911                 int dumm = 0 ;
01912                 buf.offset = 0 ; 
01913                 buf.buffer = runs ;
01914 
01915                 buf.threshold = threshold ; 
01916                 buf.start = 0 ;
01917                 buf.end = -1 ;
01918                 buf.runs_count = 0 ;
01919 #ifdef DEBUG_THRESHOLD    
01920                 fprintf( stderr, "threshold_stored_data: id = 0x%lX, width = %d, threshold = %d\n", id, width, threshold );
01921 #endif
01922                 if( fetch_data_int( storage, id, &buf, 0, width, (CARD8)threshold, card8_threshold, &dumm) > 0 ) 
01923                 {
01924                         if( buf.start >= 0 && buf.end >= buf.start )
01925                         {
01926                                 runs[buf.runs_count] = buf.start ;
01927                                 ++buf.runs_count;
01928                                 runs[buf.runs_count] = buf.end ;
01929                                 ++buf.runs_count ;
01930                         }        
01931                         return buf.runs_count;
01932                 }
01933         }
01934         return 0 ;      
01935 }
01936 
01937 
01938 Bool 
01939 query_storage_slot(ASStorage *storage, ASStorageID id, ASStorageSlot *dst )
01940 {
01941         if( storage == NULL ) 
01942                 storage = get_default_asstorage();
01943         
01944         if( storage != NULL && id != 0 && dst != NULL )
01945         {       
01946                 ASStorageSlot *slot = find_storage_slot( find_storage_block( storage, id ), id );
01947                 LOCAL_DEBUG_OUT( "slot = %p", slot );
01948                 if( slot )
01949                 {
01950                         if( get_flags( slot->flags, ASStorage_Reference) )
01951                         {
01952                                 ASStorageID target_id = 0;
01953                                 memcpy( &target_id, ASStorage_Data(slot), sizeof( ASStorageID ));                                  
01954                                 LOCAL_DEBUG_OUT( "target_id = %lX", target_id );
01955                                 if( target_id == id ) 
01956                                 {
01957                                         show_error( "reference refering to self id = %lX", id );
01958                                         return False;
01959                                 }
01960                                 return query_storage_slot(storage, target_id, dst);
01961                         }        
01962                         *dst = *slot ;
01963                         return True ;
01964                 }
01965         }
01966         return False;     
01967 }
01968 
01969 int 
01970 print_storage_slot(ASStorage *storage, ASStorageID id)
01971 {
01972         if( storage == NULL ) 
01973                 storage = get_default_asstorage();
01974         
01975         if( storage != NULL && id != 0 )
01976         {       
01977                 ASStorageSlot *slot = find_storage_slot( find_storage_block( storage, id ), id );
01978                 fprintf (stderr, "Storage ID 0x%lX-> slot %p", (unsigned long)id, slot);
01979                 if( slot )
01980                 {
01981                         int i ;
01982                         if( get_flags( slot->flags, ASStorage_Reference) )
01983                         {
01984                                 ASStorageID target_id = 0;
01985                                 memcpy( &target_id, ASStorage_Data(slot), sizeof( ASStorageID ));                                  
01986                                 fprintf (stderr, " : References storage ID 0x%lX\n\t>", (unsigned long)target_id);
01987                                 if( target_id == id ) 
01988                                 {       
01989                                         show_error( "reference refering to self id = %lX", id );
01990                                         return 0;
01991                                 }
01992                                 return print_storage_slot(storage, target_id);
01993                         }        
01994                         fprintf( stderr, " : {0x%X, %u, %lu, %lu, %u, {", 
01995                                          slot->flags, slot->ref_count, (unsigned long)slot->size, (unsigned long)slot->uncompressed_size, slot->index );
01996 
01997                         for( i = 0 ; i < (int)slot->size ; ++i)
01998                                 fprintf( stderr, "%2.2X ", ASStorage_Data(slot)[i] ) ;
01999                         fprintf (stderr, "}}");
02000                         return slot->size + ASStorageSlot_SIZE ;
02001                 }
02002                 fprintf (stderr, "\n");
02003         }
02004         return 0;         
02005 }        
02006 
02007 void  
02008 print_storage(ASStorage *storage)
02009 {
02010         int i ;
02011         if( storage == NULL ) 
02012                 storage = get_default_asstorage();
02013         fprintf( stderr, " Printing Storage %p : \n\tblock_count = %d;\n", storage, storage->blocks_count );
02014 
02015         for( i = 0 ; i < storage->blocks_count ; ++i ) 
02016         {
02017                 fprintf( stderr, "\tBlock %d = %p;\n", i, storage->blocks[i] );                 
02018                 if( storage->blocks[i] )
02019                 {
02020                         fprintf( stderr, "\t\tBlock[%d].size = %d;\n", i, storage->blocks[i]->size );                      
02021                         fprintf( stderr, "\t\tBlock[%d].slots_count = %d;\n", i, storage->blocks[i]->slots_count );                        
02022                         fprintf( stderr, "\t\tBlock[%d].last_used = %d;\n", i, storage->blocks[i]->last_used );                    
02023                 }        
02024         }        
02025 }
02026 
02027 void 
02028 forget_data(ASStorage *storage, ASStorageID id)
02029 {
02030         if( storage == NULL ) 
02031                 storage = get_default_asstorage();
02032         
02033         if( storage != NULL && id != 0 ) 
02034         {
02035                 ASStorageBlock *block = find_storage_block( storage, id );
02036                 ASStorageSlot  *slot  = find_storage_slot( block, id );                         
02037                 if( block && slot ) 
02038                 {
02039                         if( get_flags( slot->flags, ASStorage_Reference) )
02040                         {
02041                                 ASStorageID target_id = 0;
02042                                 memcpy( &target_id, ASStorage_Data(slot), sizeof( ASStorageID ));                                  
02043                                 if( target_id != id ) 
02044                                         forget_data( storage, target_id );                                      
02045                                 else
02046                                         show_error( "reference refering to self id = %lX", id );
02047                         }        
02048                         LOCAL_DEBUG_OUT( "id = %lX, ref_count = %d;", id, slot->ref_count );
02049                         if( slot->ref_count >= 1 ) 
02050                                 --(slot->ref_count);
02051                         else
02052                         {       
02053                                 free_storage_slot(block, slot);
02054                                 if( is_block_empty(block) ) 
02055                                         free_storage_block( storage, StorageID2BlockIdx(id) );
02056                         }
02057                 }        
02058         }                         
02059 }
02060 
02061 ASStorageID 
02062 dup_data(ASStorage *storage, ASStorageID id)
02063 {
02064         ASStorageID new_id = 0 ;
02065 
02066         if( storage == NULL ) 
02067                 storage = get_default_asstorage();
02068            
02069         if( storage != NULL && id != 0 )
02070         {       
02071                 ASStorageSlot *slot = find_storage_slot( find_storage_block( storage, id ), id );
02072                 LOCAL_DEBUG_OUT( "slot = %p, slot->index = %d, index(id) = %ld", slot, slot?slot->index:-1, StorageID2SlotIdx(id) );
02073                 if( slot )
02074                 {
02075                         ASStorageSlot *target_slot = NULL;
02076                         ASStorageID target_id = id ;
02077                         if( !get_flags( slot->flags, ASStorage_Reference )) 
02078                         {       
02079                                 ASStorageSlot *new_slot = convert_slot_to_ref( storage, id );
02080                                 if( new_slot != NULL ) 
02081                                         slot = new_slot;
02082                         }
02083                                 
02084                         if( get_flags( slot->flags, ASStorage_Reference )) 
02085                         {   
02086                                 memcpy( &target_id, ASStorage_Data(slot), sizeof( ASStorageID ));
02087                                 /* from now on - slot is a reference slot, so we just need to 
02088                                  * duplicate it and increase ref_count of target */
02089                                 if( target_id != id ) 
02090                                         target_slot = find_storage_slot( find_storage_block( storage, target_id ), target_id );
02091                                 else
02092                                         show_error( "reference refering to self id = %lX", id );
02093                         }else
02094                                 target_slot = slot ;    
02095                         
02096                         LOCAL_DEBUG_OUT( "target_slot = %p, slot = %p", target_slot, slot );
02097                         if( target_slot == NULL ) 
02098                                 return 0;
02099                         /* doing it here as store_data() may change slot pointers */
02100                         ++(target_slot->ref_count);                        
02101                         new_id = store_data( storage, (CARD8*)&target_id, sizeof(ASStorageID), ASStorage_Reference, 0);
02102                         LOCAL_DEBUG_OUT( "new_id = 0x%lX, target_id = %lX, target->ref_count = %d", new_id, target_id, target_slot->ref_count );
02103                 }
02104         }
02105         return new_id;
02106 }
02107 
02108 /*************************************************************************/
02109 /* test code */
02110 /*************************************************************************/
02111 #ifdef TEST_ASSTORAGE
02112 #include "afterimage.h"
02113 
02114 #define STORAGE_TEST_KINDS      7
02115 static int StorageTestKinds[STORAGE_TEST_KINDS][2] = 
02116 {
02117         {10, 10000 },
02118         {100, 5000 },
02119         {4096, 5000 },
02120         {128*1024, 128 },
02121         {256*1024, 32 },
02122         {512*1024, 16 },
02123         {1024*1024, 8 }
02124 };       
02125 
02126 CARD8 Buffer[1024*1024] ;
02127 /* #define STORAGE_TEST_COUNT  1 */
02128 #define STORAGE_TEST_COUNT  8+16+32+128+5000+5000+10000
02129 typedef struct ASStorageTest {
02130         int size ;
02131         CARD8 *data;
02132         Bool linked ;
02133         ASStorageID id ;
02134 }ASStorageTest;
02135  
02136 static ASStorageTest Tests[STORAGE_TEST_COUNT];
02137 
02138 static ASImageDecoder *imdec = NULL ;
02139 
02140 void
02141 make_storage_test_data( ASStorageTest *test, int min_size, int max_size, ASFlagType flags )
02142 {
02143         int size = random()%max_size ;
02144         int i ;
02145         static CARD32 rnd32_seed = 345824357;
02146         static int chan = 0 ;
02147         CARD32 *data ;
02148         CARD8 *test_data8 ;
02149         CARD32 *test_data32 ;
02150 
02151 #define MAX_MY_RND32            0x00ffffffff
02152 #ifdef WORD64
02153 #define MY_RND32() \
02154 (rnd32_seed = ((1664525L*rnd32_seed)&MAX_MY_RND32)+1013904223L)
02155 #else
02156 #define MY_RND32() \
02157 (rnd32_seed = (1664525L*rnd32_seed)+1013904223L)
02158 #endif
02159         
02160         if( size <= min_size )
02161                 size += min_size ;
02162         if( get_flags( flags, ASStorage_32Bit ) )       
02163                 size = ((size/4)+1)*4 ;
02164         test->size = size ;        
02165 #ifndef DEBUG_ALLOCS
02166         test->data = malloc(size);
02167 #else
02168         test->data = guarded_malloc(size);
02169 #endif
02170 
02171         test_data32     = (CARD32*)(test->data);
02172         test_data8      = test->data ;
02173 
02174         if( get_flags( flags, ASStorage_32Bit ) )
02175                 size = size / 4 ;
02176 
02177         test->linked = False ;
02178         
02179 
02180         if( imdec ) 
02181         {       
02182                 int k = 0;
02183                 if( chan == 0 ) 
02184                         imdec->decode_image_scanline( imdec );
02185                 data = imdec->buffer.channels[chan];
02186                 ++chan ; 
02187                 if( chan >= 3 ) 
02188                         chan = 0 ;
02189                 if( get_flags( flags, ASStorage_32Bit ) )
02190                 {       
02191                         if( get_flags( flags, ASStorage_8BitShift ) )
02192                         {
02193                                 for( i = 0 ; i < size ; ++i ) 
02194                                 {       
02195                                         test_data32[i] = ((CARD32)data[k])<<8 ;
02196                                         if( ++k >= imdec->im->width )           k = 0 ;
02197                                 }
02198                         }else    
02199                                 for( i = 0 ; i < size ; ++i ) 
02200                                 {       
02201                                         test_data32[i] = data[k] ;
02202                                         if( ++k >= imdec->im->width )           k = 0 ;
02203                                 }
02204                 }else
02205                         for( i = 0 ; i < size ; ++i ) 
02206                         {       
02207                                 test_data8[i] = data[k] ;
02208                                 if( ++k >= imdec->im->width )           k = 0 ;
02209                         }
02210                         
02211         }else
02212         {       
02213                 if( get_flags( flags, ASStorage_32Bit ) )
02214                 {       
02215                         if( get_flags( flags, ASStorage_8BitShift ) )
02216                         {
02217                                 for( i = 0 ; i < size ; ++i ) 
02218                                         test_data32[i] = (MY_RND32())&0x0000FF00 ;
02219                         }else    
02220                                 for( i = 0 ; i < size ; ++i ) 
02221                                         test_data32[i] = (MY_RND32())&0x000000FF ;
02222                 }else
02223                         for( i = 0 ; i < size ; ++i ) 
02224                                 test_data8[i] = MY_RND32() ;
02225         }
02226         test->id = 0 ;
02227 }
02228 
02229 int 
02230 test_data_integrity( CARD8 *a, CARD8* b, int size, ASFlagType flags ) 
02231 {
02232         register int i ;
02233         CARD32 *b32 = (CARD32*)b;
02234         CARD32 threshold32 = AS_STORAGE_DEFAULT_BMAP_THRESHOLD ;
02235         CARD32 threshold8 = AS_STORAGE_DEFAULT_BMAP_THRESHOLD ;
02236 
02237         if( get_flags( flags, ASStorage_32Bit ) )
02238         {       
02239                 size = size / 4 ;
02240                 if( get_flags( flags, ASStorage_8BitShift ) )
02241                         threshold32 = threshold32 << 8 ;                                
02242         }
02243 
02244         for( i = 0 ; i < size ; ++i ) 
02245         {
02246                 Bool fail = False ;
02247                 
02248                 if( get_flags( flags, ASStorage_Bitmap ) )
02249                 {       
02250                         if( get_flags( flags, ASStorage_32Bit ) )
02251                                 fail = ( (a[i] >  threshold8 && b32[i] <= threshold32 )||(a[i] <= threshold8 && b32[i] > threshold32));
02252                         else
02253                                 fail = ( (a[i] >  threshold8 && b[i] <= threshold8 )||(a[i] <= threshold8 && b[i] >  threshold8));
02254 
02255                 }else
02256                 {
02257                         if( get_flags( flags, ASStorage_32Bit ) )
02258                         {       
02259                                 if( get_flags( flags, ASStorage_8BitShift ) )
02260                                 {
02261                                         fail = ( (CARD8)(b32[i]>>8) != a[i] );
02262                                 }else
02263                                         fail = ( (CARD8)b32[i] != a[i] );
02264                         }else           
02265                                 fail = ( a[i] != b[i] );
02266                 }               
02267                 if( fail ) 
02268                 {
02269                         int k ;
02270                         if( get_flags( flags, ASStorage_32Bit ) )
02271                         {       
02272                                 fprintf( stderr, "\tBytes %d differ : a[%d] == 0x%2.2X, b32[%d] == 0x%8.8lX\na: ", i, i, a[i], i, b32[i] );
02273                                 for( k = 0 ; k < size ; ++k ) 
02274                                         fprintf( stderr, (k==i)?"##%8.8X## ":"%8.8X ", a[k] );
02275                                 fprintf( stderr, "\nb: " );
02276                                 for( k = 0 ; k < size ; ++k ) 
02277                                         fprintf( stderr, (k==i)?"##%8.8lX## ":"%8.8lX ", b32[k] );
02278                         
02279                         }else
02280                         {       
02281                                 fprintf( stderr, "\tBytes %d differ : a[%d] == 0x%2.2X, b[%d] == 0x%2.2X\na: ", i, i, a[i], i, b[i] );
02282                                 for( k = 0 ; k < size ; ++k ) 
02283                                         fprintf( stderr, (k==i)?"##%2.2X## ":"%2.2X ", a[k] );
02284                                 fprintf( stderr, "\nb: " );
02285                                 for( k = 0 ; k < size ; ++k ) 
02286                                         fprintf( stderr, (k==i)?"##%2.2X## ":"%2.2X ", b[k] );
02287                         }
02288 
02289                         fprintf( stderr, "\n" );
02290                         return 1;                       
02291                 }                          
02292         }
02293         return 0 ;
02294 }
02295           
02296 Bool 
02297 test_asstorage(Bool interactive, int all_test_count, ASFlagType test_flags )
02298 {
02299         ASStorage *storage ;
02300         ASStorageID id ;
02301         int i, kind, k;
02302         int min_size, max_size ;
02303         int test_count ;
02304         START_TIME(started);
02305 
02306         UsedMemory = 0 ;
02307         UncompressedSize = 0 ;
02308         CompressedSize = 0 ;
02309 
02310         fprintf( stderr, "\n%d :Testing flags 0x%lX @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n", __LINE__, test_flags );
02311         fprintf(stderr, "Testing storage creation ...");
02312         storage = create_asstorage();
02313 #define TEST_EVAL(val)   do{ \
02314                                                         if(!(val)){ fprintf(stderr, "failed\n"); return 1;} \
02315                                                         else fprintf(stderr, "success.\n");}while(0)
02316         TEST_EVAL( storage != NULL ); 
02317         
02318 #ifdef DO_CLOCKING      
02319         fprintf(stderr, "Testing speed for flags 0x%lX...", test_flags);
02320         {
02321 #define SPEED_SIZE 1024*1024*50         
02322                 CARD8 *speed_buffer ;
02323                 int i, id ;
02324                 static CARD32 rnd32_seed = 345824357;
02325 
02326                 speed_buffer = safemalloc( SPEED_SIZE );
02327 
02328                 for( i = 0 ; i < SPEED_SIZE ; ++i ) 
02329                         speed_buffer[i] = (MY_RND32())&0x00FF ;
02330                 
02331                 {
02332                         START_TIME(started2);
02333                         id = store_data( storage, &speed_buffer[0], SPEED_SIZE, test_flags, 0 );
02334                         SHOW_TIME("RLE compression speed ", started2);
02335                 }
02336                 {
02337                         START_TIME(started3);
02338                         fetch_data(storage, id, &speed_buffer[0], 0, SPEED_SIZE, 0, NULL);
02339                         SHOW_TIME("RLE de-compression speed ", started3);
02340                         forget_data(storage, id );
02341                 }
02342                 free( speed_buffer );
02343         }        
02344 
02345 #endif
02346         
02347         fprintf(stderr, "Testing store_data for data %p size = %d, and flags 0x%lX...", NULL, 0,
02348                         test_flags);
02349         id = store_data( storage, NULL, 0, test_flags, 0 );
02350         TEST_EVAL( id == 0 ); 
02351 
02352         kind = 0 ; 
02353         min_size = 1 ;
02354         max_size = StorageTestKinds[kind][0] ; 
02355         test_count = StorageTestKinds[kind][1] ;
02356         for( i = 0 ; i < all_test_count ; ++i ) 
02357         {
02358                 make_storage_test_data( &(Tests[i]), min_size, max_size, test_flags );
02359                 fprintf(stderr, "Testing store_data for data %p size = %d, and flags 0x%lX...", Tests[i].data, Tests[i].size,
02360                                 test_flags);
02361                 Tests[i].id = store_data( storage, Tests[i].data, Tests[i].size, test_flags, 0 );
02362                 TEST_EVAL( Tests[i].id != 0 ); 
02363                 fprintf(stderr, "\tstored with id = %lX...\n", Tests[i].id );
02364 
02365                 if( --test_count <= 0 )
02366                 {
02367                         if( ++kind >= all_test_count ) 
02368                                 break;
02369                         min_size = max_size ;
02370                         max_size = StorageTestKinds[kind][0] ; 
02371                         test_count = StorageTestKinds[kind][1] ;
02372                 }                  
02373         }        
02374 
02375         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02376         fprintf( stderr, "%d :compressed_size = %d, uncompressed_size = %d, ratio = %d %% ###########\n", __LINE__, CompressedSize, UncompressedSize, (UncompressedSize<100)?0:(CompressedSize/(UncompressedSize/100)) );
02377         SHOW_TIME("Pass 1", started);
02378 
02379         if( interactive )
02380            fgetc(stdin);
02381         for( i = 0 ; i < all_test_count ; ++i ) 
02382         {
02383                 int size ;
02384                 int res ;
02385                 fprintf(stderr, "Testing fetch_data for id %lX size = %d ...", Tests[i].id, Tests[i].size);
02386                 size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL);
02387                 TEST_EVAL( size == Tests[i].size ); 
02388                 
02389                 fprintf(stderr, "Testing fetched data integrity ...");
02390                 res = test_data_integrity( &(Buffer[0]), Tests[i].data, size, test_flags );
02391                 TEST_EVAL( res == 0 ); 
02392         }        
02393         if( !get_flags( test_flags, ASStorage_32Bit ) )
02394         {       
02395                 for( i = 0 ; i < all_test_count ; ++i ) 
02396                 {
02397                         int size ;
02398                         int res ;
02399                         fprintf(stderr, "Testing fetch_data32 for id %lX size = %d ...", Tests[i].id, Tests[i].size);
02400                         size = fetch_data32(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size/4, 0, NULL);
02401                         TEST_EVAL( size == Tests[i].size/4 ); 
02402                 
02403                         fprintf(stderr, "Testing fetched data integrity ...");
02404                         res = test_data_integrity( Tests[i].data, &(Buffer[0]), size, test_flags|ASStorage_32Bit );
02405                         TEST_EVAL( res == 0 ); 
02406                 }        
02407         }
02408 
02409         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02410         SHOW_TIME("Pass 2", started);
02411         if( interactive )
02412            fgetc(stdin);
02413         for( i = 0 ; i < all_test_count ; ++i ) 
02414         {
02415                 int size ;
02416                 int r = random();
02417                 if( (r&0x01) == 0 || Tests[i].id == 0 ) 
02418                         continue;
02419                 fprintf(stderr, "%d: Testing forget_data for id %lX size = %d ...\n", __LINE__, Tests[i].id, Tests[i].size);
02420                 forget_data(storage, Tests[i].id);
02421                 size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL );
02422                 TEST_EVAL( size != Tests[i].size ); 
02423                 Tests[i].id = 0;
02424 #ifndef DEBUG_ALLOCS
02425                 free( Tests[i].data );
02426 #else
02427                 guarded_free( Tests[i].data );
02428 #endif
02429                 Tests[i].data = NULL ; 
02430                 Tests[i].size = 0 ;
02431         }        
02432         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02433         SHOW_TIME("Pass 3", started);
02434         if( interactive )
02435            fgetc(stdin);
02436         kind = 0 ; 
02437         min_size = 1 ;
02438         max_size = StorageTestKinds[kind][0] ; 
02439         test_count = StorageTestKinds[kind][1] ;
02440         for( i = 0 ; i < all_test_count ; ++i ) 
02441         {
02442                 if( Tests[i].id == 0 ) 
02443                 {       
02444                         make_storage_test_data( &(Tests[i]), min_size, max_size, test_flags );
02445                         fprintf(stderr, "Testing store_data for data %p size = %d, and flags 0x%lX...\n", Tests[i].data, Tests[i].size,
02446                                         test_flags);
02447                         Tests[i].id = store_data( storage, Tests[i].data, Tests[i].size, test_flags, 0 );
02448                         TEST_EVAL( Tests[i].id != 0 ); 
02449                 }
02450                 if( --test_count <= 0 )
02451                 {
02452                         if( ++kind >= all_test_count ) 
02453                                 break;
02454                         min_size = max_size ;
02455                         max_size = StorageTestKinds[kind][0] ; 
02456                         test_count = StorageTestKinds[kind][1] ;
02457                 }                  
02458         }        
02459         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02460         SHOW_TIME("Pass 4", started);
02461         if( interactive )
02462            fgetc(stdin);
02463         for( i = 0 ; i < all_test_count ; ++i ) 
02464         {
02465                 int size ;
02466                 int res ;
02467                 fprintf(stderr, "Testing fetch_data for id %lX size = %d ...", Tests[i].id, Tests[i].size);
02468                 size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL);
02469                 TEST_EVAL( size == Tests[i].size ); 
02470                 
02471                 fprintf(stderr, "Testing fetched data integrity ...");
02472                 res = test_data_integrity( &(Buffer[0]), Tests[i].data, size, test_flags );
02473                 TEST_EVAL( res == 0 ); 
02474         }        
02475 
02476         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02477         SHOW_TIME("Pass 5", started);
02478         if( interactive )
02479            fgetc(stdin);
02480         for( i = 0 ; i < all_test_count ; ++i ) 
02481         {
02482                 int size ;
02483                 int r = random();
02484                 if( (r&0x01) == 0 || Tests[i].id == 0 ) 
02485                         continue;
02486                 fprintf(stderr, "%d: Testing forget_data for id %lX size = %d ...\n", __LINE__, Tests[i].id, Tests[i].size);
02487                 forget_data(storage, Tests[i].id);
02488                 size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL);
02489                 TEST_EVAL( size != Tests[i].size ); 
02490                 Tests[i].id = 0;
02491 #ifndef DEBUG_ALLOCS
02492                 free( Tests[i].data );
02493 #else
02494                 guarded_free( Tests[i].data );
02495 #endif
02496                 Tests[i].data = NULL ; 
02497                 Tests[i].size = 0 ;
02498         }        
02499 
02500         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02501         SHOW_TIME("Pass 6", started);
02502         if( interactive )
02503                 fgetc(stdin);
02504         for( k = 0 ; k < 50 ; ++k )
02505         {
02506                 fprintf( stderr, "%d :dup_data test iteration #%d !!!!!!!!!!!!!!!\n", __LINE__, k );
02507                 for( i = 0 ; i < all_test_count ; ++i ) 
02508                 {
02509                         int k, size, res ;
02510                 
02511                         if( Tests[i].id != 0 ) 
02512                                 continue;
02513                         
02514                         for( k = i+1 ; k < all_test_count ; ++k ) 
02515                                 if( Tests[k].id != 0 ) 
02516                                         break;
02517                         if( k >= all_test_count ) 
02518                                 for( k = i ; k >= 0 ; --k ) 
02519                                         if( Tests[k].id != 0 ) 
02520                                                 break;
02521 
02522                         if( Tests[k].id == 0 ) 
02523                                 continue;
02524         
02525                         fprintf(stderr, "Testing dup_data for id %lX size = %d ...\n", Tests[k].id, Tests[k].size);
02526                         Tests[i].id = dup_data(storage, Tests[k].id );
02527                         TEST_EVAL( Tests[i].id != 0 ); 
02528                         fprintf(stderr, "Dupped to id %lX - Testing dupped data fetching ...\n", Tests[i].id);
02529                         Tests[i].size = Tests[k].size ;
02530                         Tests[i].data = Tests[k].data ;
02531                         Tests[i].linked = True ;
02532                         size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL);
02533                         TEST_EVAL( size == Tests[i].size ); 
02534                 
02535                         fprintf(stderr, "Testing dupped data integrity ...\n");
02536                         res = test_data_integrity( &(Buffer[0]), Tests[i].data, size, test_flags );
02537                         TEST_EVAL( res == 0 ); 
02538         
02539                 }        
02540 
02541                 fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02542                 if( interactive )
02543                 fgetc(stdin);
02544                 for( i = 0 ; i < all_test_count ; ++i ) 
02545                 {
02546                         int size ;
02547                         int r = random();
02548                         if( (r&0x01) == 0 || Tests[i].id == 0 ) 
02549                                 continue;
02550                         fprintf(stderr, "%d: Testing forget_data for id %lX size = %d ...\n", __LINE__, Tests[i].id, Tests[i].size);
02551                         forget_data(storage, Tests[i].id);
02552                         size = fetch_data(storage, Tests[i].id, &(Buffer[0]), 0, Tests[i].size, 0, NULL);
02553                         TEST_EVAL( size != Tests[i].size ); 
02554                         Tests[i].id = 0;
02555                         if( !Tests[i].linked ) 
02556                         {       
02557                                 int z ;
02558                                 for( z = 0 ; z < all_test_count ; ++z ) 
02559                                 {
02560                                         if( Tests[z].linked ) 
02561                                                 if( Tests[z].data == Tests[i].data ) 
02562                                                 {
02563                                                         Tests[z].linked = False ;
02564                                                         Tests[i].data = NULL ; 
02565                                                         break;
02566                                                 }
02567                                 }        
02568                                 if( Tests[i].data )
02569                                 {       
02570         #ifndef DEBUG_ALLOCS
02571                                         free( Tests[i].data );
02572         #else
02573                                         guarded_free( Tests[i].data );
02574         #endif
02575                                 }
02576                         }else
02577                                 Tests[i].linked = False ;
02578                         Tests[i].data = NULL ; 
02579                         Tests[i].size = 0 ;
02580                 }        
02581         }       
02582         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02583         SHOW_TIME("Pass 7", started);
02584         if( interactive )
02585            fgetc(stdin);
02586         kind = 0 ; 
02587         min_size = 1 ;
02588         max_size = StorageTestKinds[kind][0] ; 
02589         test_count = StorageTestKinds[kind][1] ;
02590         for( i = 0 ; i < all_test_count ; ++i ) 
02591         {
02592                 if( Tests[i].id == 0 ) 
02593                 {       
02594                         make_storage_test_data( &(Tests[i]), min_size, max_size, test_flags );
02595                         fprintf(stderr, "Testing store_data for data %p size = %d, and flags 0x%lX...\n", Tests[i].data, Tests[i].size,
02596                                         test_flags);
02597                         Tests[i].id = store_data( storage, Tests[i].data, Tests[i].size, test_flags, 0 );
02598                         TEST_EVAL( Tests[i].id != 0 ); 
02599                 }
02600                 if( --test_count <= 0 )
02601                 {
02602                         if( ++kind >= all_test_count ) 
02603                                 break;
02604                         min_size = max_size ;
02605                         max_size = StorageTestKinds[kind][0] ; 
02606                         test_count = StorageTestKinds[kind][1] ;
02607                 }                  
02608         }        
02609         fprintf( stderr, "%d :memory used %d #####################################################\n", __LINE__, UsedMemory );
02610         fprintf( stderr, "%d :compressed_size = %d, uncompressed_size = %d, ratio = %d %% ###########\n", __LINE__, CompressedSize, UncompressedSize, (UncompressedSize<100)?0:(CompressedSize/(UncompressedSize/100)) );
02611         SHOW_TIME("", started);
02612         fprintf(stderr, "Testing storage destruction ...");
02613         destroy_asstorage(&storage);
02614         TEST_EVAL( storage == NULL ); 
02615 
02616         for( i = 0 ; i < all_test_count ; ++i ) 
02617                 if( Tests[i].data ) 
02618                 {
02619                         if( !Tests[i].linked ) 
02620                         {       
02621                                                                 int z ;
02622                                 for( z = 0 ; z < all_test_count ; ++z ) 
02623                                 {
02624                                         if( Tests[z].linked ) 
02625                                                 if( Tests[z].data == Tests[i].data ) 
02626                                                 {
02627                                                         Tests[z].linked = False ;
02628                                                         Tests[i].data = NULL ; 
02629                                                         break;
02630                                                 }
02631                                 }        
02632                                 if( Tests[i].data ) 
02633                                 {       
02634 #ifndef DEBUG_ALLOCS
02635                                         free( Tests[i].data );
02636 #else
02637                                         guarded_free( Tests[i].data );
02638 #endif
02639                                 }
02640                         }
02641                         Tests[i].data = NULL ;
02642                         Tests[i].size = 0 ;
02643                 }
02644 
02645         return 0 ;
02646 }
02647 
02648 int main(int argc, char **argv )
02649 {
02650         Bool interactive = False ; 
02651         ASImage *im = NULL ;
02652         int i ;
02653         int res = 0;
02654         int     test_count = STORAGE_TEST_COUNT ;
02655         
02656         set_output_threshold( 10 );
02657         
02658         for( i = 1 ; i < argc ; ++i ) 
02659         {       
02660                 fprintf( stderr, "i = %d argv = \"%s\"\n", i, argv[i] );
02661                 if( strcmp(argv[i], "-i") == 0 ) 
02662                         interactive = True ; 
02663                 else if( i+1 <= argc && strcmp(argv[i], "-s") == 0 ) 
02664                 {
02665                         fprintf( stderr, "Loading test source image \"%s\"\n", argv[i+1] );
02666                         im = file2ASImage( argv[i+1], 0xFFFFFFFF, SCREEN_GAMMA, 0, NULL );        
02667                         ++i ;
02668                 }else if( i+1 <= argc && strcmp(argv[i], "-c") == 0 ) 
02669                 {
02670                         test_count = atoi( argv[i+1] );
02671                         if( test_count > STORAGE_TEST_COUNT ) 
02672                                 test_count = STORAGE_TEST_COUNT ;
02673 
02674                         fprintf( stderr, "Test count = %d(\"%s\")\n", test_count, argv[i+1] );
02675                         ++i ;
02676                 }else if( i+1 <= argc && strcmp(argv[i], "-l") == 0 ) 
02677                 {
02678                         if( freopen( argv[i+1], "w", stderr ) == NULL )
02679                                 fprintf( stderr, "Failed to open log file \"%s\"\n", argv[i+1] );
02680                         ++i ;
02681                 }
02682 
02683         }
02684 
02685         if( im ) 
02686         {       
02687                 imdec = start_image_decoding(NULL, im, SCL_DO_ALL, 0, 0, im->width, im->height, NULL);
02688                 fprintf( stderr, "imdec = %p\n", imdec );
02689         }
02690         fprintf(stderr, "running tests ( res = %d ) ...\n", res );      
02691         if( res == 0 )
02692                 res = test_asstorage(interactive, test_count, 0);
02693 #if 1
02694         if( res == 0 )
02695                 res = test_asstorage(interactive, test_count, ASStorage_RLEDiffCompress);
02696         if( res == 0 )
02697                 res = test_asstorage(interactive, test_count, ASStorage_RLEDiffCompress|ASStorage_Bitmap);
02698         if( res == 0 )
02699                 res = test_asstorage(interactive, test_count, ASStorage_32Bit);
02700         if( res == 0 )
02701                 res = test_asstorage(interactive, test_count, ASStorage_32Bit|ASStorage_RLEDiffCompress);
02702         if( res == 0 )
02703                 res = test_asstorage(interactive, test_count, ASStorage_32Bit|ASStorage_RLEDiffCompress|ASStorage_Bitmap);
02704         
02705         if( res == 0 )
02706                 res = test_asstorage(interactive, test_count, ASStorage_32Bit|ASStorage_8BitShift);
02707         if( res == 0 )
02708                 res = test_asstorage(interactive, test_count, ASStorage_32Bit|ASStorage_8BitShift|ASStorage_RLEDiffCompress);
02709         if( res == 0 )
02710                 res = test_asstorage(interactive, test_count, ASStorage_32Bit|ASStorage_8BitShift|ASStorage_RLEDiffCompress|ASStorage_Bitmap);
02711 #endif  
02712         stop_image_decoding( &imdec );
02713         return res;
02714 }
02715 #endif
02716 

Generated on Tue Jul 5 14:13:26 2011 for ROOT_528-00b_version by  doxygen 1.5.1