00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #undef LOCAL_DEBUG
00023
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
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
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
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
00139 while( ++i < size )
00140 {
00141 diff[i] = (ASStorageDiff)data[i] - (ASStorageDiff)data[i-1] ;
00142
00143 }
00144
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
00154 while( ++i < size )
00155 {
00156 diff[i] = (ASStorageDiff)data32[i] - (ASStorageDiff)data32[i-1] ;
00157
00158 }
00159
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 ;
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 {
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 {
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 {
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 {
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;
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
00471
00472
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
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
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
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
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 ))
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
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 ;
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
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 )
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
01064
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 {
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
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
01248 }while( slot->flags == 0 );
01249 }
01250 }
01251 ++i ;
01252 }
01253 }
01254
01255
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
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;
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
01497
01498
01499
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 {
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
01532
01533 }else
01534 {
01535
01536 ref_index = StorageID2SlotIdx(id); ;
01537 ref_slot = block->slots[ref_index] ;
01538
01539 if( block->total_free > (int)ref_slot->size )
01540 {
01541
01542
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
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
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 ;
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
02088
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
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
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
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