00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 #define JPEG_INTERNALS
00028 #define AM_MEMORY_MANAGER       
00029 #include "jinclude.h"
00030 #include "jpeglib.h"
00031 #include "jmemsys.h"            
00032 
00033 #ifndef NO_GETENV
00034 #ifndef HAVE_STDLIB_H           
00035 extern char * getenv JPP((const char * name));
00036 #endif
00037 #endif
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 #ifndef ALIGN_TYPE              
00073 #define ALIGN_TYPE  double
00074 #endif
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 typedef union small_pool_struct * small_pool_ptr;
00090 
00091 typedef union small_pool_struct {
00092   struct {
00093     small_pool_ptr next;        
00094     size_t bytes_used;          
00095     size_t bytes_left;          
00096   } hdr;
00097   ALIGN_TYPE dummy;             
00098 } small_pool_hdr;
00099 
00100 typedef union large_pool_struct FAR * large_pool_ptr;
00101 
00102 typedef union large_pool_struct {
00103   struct {
00104     large_pool_ptr next;        
00105     size_t bytes_used;          
00106     size_t bytes_left;          
00107   } hdr;
00108   ALIGN_TYPE dummy;             
00109 } large_pool_hdr;
00110 
00111 
00112 
00113 
00114 
00115 
00116 typedef struct {
00117   struct jpeg_memory_mgr pub;   
00118 
00119   
00120   small_pool_ptr small_list[JPOOL_NUMPOOLS];
00121   large_pool_ptr large_list[JPOOL_NUMPOOLS];
00122 
00123   
00124 
00125 
00126 
00127 
00128   jvirt_sarray_ptr virt_sarray_list;
00129   jvirt_barray_ptr virt_barray_list;
00130 
00131   
00132   long total_space_allocated;
00133 
00134   
00135 
00136 
00137   JDIMENSION last_rowsperchunk; 
00138 } my_memory_mgr;
00139 
00140 typedef my_memory_mgr * my_mem_ptr;
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 struct jvirt_sarray_control {
00151   JSAMPARRAY mem_buffer;        
00152   JDIMENSION rows_in_array;     
00153   JDIMENSION samplesperrow;     
00154   JDIMENSION maxaccess;         
00155   JDIMENSION rows_in_mem;       
00156   JDIMENSION rowsperchunk;      
00157   JDIMENSION cur_start_row;     
00158   JDIMENSION first_undef_row;   
00159   boolean pre_zero;             
00160   boolean dirty;                
00161   boolean b_s_open;             
00162   jvirt_sarray_ptr next;        
00163   backing_store_info b_s_info;  
00164 };
00165 
00166 struct jvirt_barray_control {
00167   JBLOCKARRAY mem_buffer;       
00168   JDIMENSION rows_in_array;     
00169   JDIMENSION blocksperrow;      
00170   JDIMENSION maxaccess;         
00171   JDIMENSION rows_in_mem;       
00172   JDIMENSION rowsperchunk;      
00173   JDIMENSION cur_start_row;     
00174   JDIMENSION first_undef_row;   
00175   boolean pre_zero;             
00176   boolean dirty;                
00177   boolean b_s_open;             
00178   jvirt_barray_ptr next;        
00179   backing_store_info b_s_info;  
00180 };
00181 
00182 
00183 #ifdef MEM_STATS                
00184 
00185 LOCAL(void)
00186 print_mem_stats (j_common_ptr cinfo, int pool_id)
00187 {
00188   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00189   small_pool_ptr shdr_ptr;
00190   large_pool_ptr lhdr_ptr;
00191 
00192   
00193 
00194 
00195 
00196   fprintf(stderr, "Freeing pool %d, total space = %ld\n",
00197           pool_id, mem->total_space_allocated);
00198 
00199   for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
00200        lhdr_ptr = lhdr_ptr->hdr.next) {
00201     fprintf(stderr, "  Large chunk used %ld\n",
00202             (long) lhdr_ptr->hdr.bytes_used);
00203   }
00204 
00205   for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
00206        shdr_ptr = shdr_ptr->hdr.next) {
00207     fprintf(stderr, "  Small chunk used %ld free %ld\n",
00208             (long) shdr_ptr->hdr.bytes_used,
00209             (long) shdr_ptr->hdr.bytes_left);
00210   }
00211 }
00212 
00213 #endif 
00214 
00215 
00216 LOCAL(void)
00217 out_of_memory (j_common_ptr cinfo, int which)
00218 
00219 
00220 {
00221 #ifdef MEM_STATS
00222   cinfo->err->trace_level = 2;  
00223 #endif
00224   ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
00225 }
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 static const size_t first_pool_slop[JPOOL_NUMPOOLS] = 
00242 {
00243         1600,                   
00244         16000                   
00245 };
00246 
00247 static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = 
00248 {
00249         0,                      
00250         5000                    
00251 };
00252 
00253 #define MIN_SLOP  50            
00254 
00255 
00256 METHODDEF(void *)
00257 alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00258 
00259 {
00260   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00261   small_pool_ptr hdr_ptr, prev_hdr_ptr;
00262   char * data_ptr;
00263   size_t odd_bytes, min_request, slop;
00264 
00265   
00266   if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
00267     out_of_memory(cinfo, 1);    
00268 
00269   
00270   odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00271   if (odd_bytes > 0)
00272     sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00273 
00274   
00275   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00276     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); 
00277   prev_hdr_ptr = NULL;
00278   hdr_ptr = mem->small_list[pool_id];
00279   while (hdr_ptr != NULL) {
00280     if (hdr_ptr->hdr.bytes_left >= sizeofobject)
00281       break;                    
00282     prev_hdr_ptr = hdr_ptr;
00283     hdr_ptr = hdr_ptr->hdr.next;
00284   }
00285 
00286   
00287   if (hdr_ptr == NULL) {
00288     
00289     min_request = sizeofobject + SIZEOF(small_pool_hdr);
00290     if (prev_hdr_ptr == NULL)   
00291       slop = first_pool_slop[pool_id];
00292     else
00293       slop = extra_pool_slop[pool_id];
00294     
00295     if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
00296       slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
00297     
00298     for (;;) {
00299       hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
00300       if (hdr_ptr != NULL)
00301         break;
00302       slop /= 2;
00303       if (slop < MIN_SLOP)      
00304         out_of_memory(cinfo, 2); 
00305     }
00306     mem->total_space_allocated += min_request + slop;
00307     
00308     hdr_ptr->hdr.next = NULL;
00309     hdr_ptr->hdr.bytes_used = 0;
00310     hdr_ptr->hdr.bytes_left = sizeofobject + slop;
00311     if (prev_hdr_ptr == NULL)   
00312       mem->small_list[pool_id] = hdr_ptr;
00313     else
00314       prev_hdr_ptr->hdr.next = hdr_ptr;
00315   }
00316 
00317   
00318   data_ptr = (char *) (hdr_ptr + 1); 
00319   data_ptr += hdr_ptr->hdr.bytes_used; 
00320   hdr_ptr->hdr.bytes_used += sizeofobject;
00321   hdr_ptr->hdr.bytes_left -= sizeofobject;
00322 
00323   return (void *) data_ptr;
00324 }
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 METHODDEF(void FAR *)
00342 alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00343 
00344 {
00345   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00346   large_pool_ptr hdr_ptr;
00347   size_t odd_bytes;
00348 
00349   
00350   if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
00351     out_of_memory(cinfo, 3);    
00352 
00353   
00354   odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00355   if (odd_bytes > 0)
00356     sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00357 
00358   
00359   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00360     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); 
00361 
00362   hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
00363                                             SIZEOF(large_pool_hdr));
00364   if (hdr_ptr == NULL)
00365     out_of_memory(cinfo, 4);    
00366   mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
00367 
00368   
00369   hdr_ptr->hdr.next = mem->large_list[pool_id];
00370   
00371 
00372 
00373   hdr_ptr->hdr.bytes_used = sizeofobject;
00374   hdr_ptr->hdr.bytes_left = 0;
00375   mem->large_list[pool_id] = hdr_ptr;
00376 
00377   return (void FAR *) (hdr_ptr + 1); 
00378 }
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 METHODDEF(JSAMPARRAY)
00395 alloc_sarray (j_common_ptr cinfo, int pool_id,
00396               JDIMENSION samplesperrow, JDIMENSION numrows)
00397 
00398 {
00399   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00400   JSAMPARRAY result;
00401   JSAMPROW workspace;
00402   JDIMENSION rowsperchunk, currow, i;
00403   long ltemp;
00404 
00405   
00406   ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00407           ((long) samplesperrow * SIZEOF(JSAMPLE));
00408   if (ltemp <= 0)
00409     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00410   if (ltemp < (long) numrows)
00411     rowsperchunk = (JDIMENSION) ltemp;
00412   else
00413     rowsperchunk = numrows;
00414   mem->last_rowsperchunk = rowsperchunk;
00415 
00416   
00417   result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
00418                                     (size_t) (numrows * SIZEOF(JSAMPROW)));
00419 
00420   
00421   currow = 0;
00422   while (currow < numrows) {
00423     rowsperchunk = MIN(rowsperchunk, numrows - currow);
00424     workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
00425         (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
00426                   * SIZEOF(JSAMPLE)));
00427     for (i = rowsperchunk; i > 0; i--) {
00428       result[currow++] = workspace;
00429       workspace += samplesperrow;
00430     }
00431   }
00432 
00433   return result;
00434 }
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 METHODDEF(JBLOCKARRAY)
00443 alloc_barray (j_common_ptr cinfo, int pool_id,
00444               JDIMENSION blocksperrow, JDIMENSION numrows)
00445 
00446 {
00447   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00448   JBLOCKARRAY result;
00449   JBLOCKROW workspace;
00450   JDIMENSION rowsperchunk, currow, i;
00451   long ltemp;
00452 
00453   
00454   ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00455           ((long) blocksperrow * SIZEOF(JBLOCK));
00456   if (ltemp <= 0)
00457     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00458   if (ltemp < (long) numrows)
00459     rowsperchunk = (JDIMENSION) ltemp;
00460   else
00461     rowsperchunk = numrows;
00462   mem->last_rowsperchunk = rowsperchunk;
00463 
00464   
00465   result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
00466                                      (size_t) (numrows * SIZEOF(JBLOCKROW)));
00467 
00468   
00469   currow = 0;
00470   while (currow < numrows) {
00471     rowsperchunk = MIN(rowsperchunk, numrows - currow);
00472     workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
00473         (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
00474                   * SIZEOF(JBLOCK)));
00475     for (i = rowsperchunk; i > 0; i--) {
00476       result[currow++] = workspace;
00477       workspace += blocksperrow;
00478     }
00479   }
00480 
00481   return result;
00482 }
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 METHODDEF(jvirt_sarray_ptr)
00523 request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00524                      JDIMENSION samplesperrow, JDIMENSION numrows,
00525                      JDIMENSION maxaccess)
00526 
00527 {
00528   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00529   jvirt_sarray_ptr result;
00530 
00531   
00532   if (pool_id != JPOOL_IMAGE)
00533     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); 
00534 
00535   
00536   result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
00537                                           SIZEOF(struct jvirt_sarray_control));
00538 
00539   result->mem_buffer = NULL;    
00540   result->rows_in_array = numrows;
00541   result->samplesperrow = samplesperrow;
00542   result->maxaccess = maxaccess;
00543   result->pre_zero = pre_zero;
00544   result->b_s_open = FALSE;     
00545   result->next = mem->virt_sarray_list; 
00546   mem->virt_sarray_list = result;
00547 
00548   return result;
00549 }
00550 
00551 
00552 METHODDEF(jvirt_barray_ptr)
00553 request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00554                      JDIMENSION blocksperrow, JDIMENSION numrows,
00555                      JDIMENSION maxaccess)
00556 
00557 {
00558   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00559   jvirt_barray_ptr result;
00560 
00561   
00562   if (pool_id != JPOOL_IMAGE)
00563     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); 
00564 
00565   
00566   result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
00567                                           SIZEOF(struct jvirt_barray_control));
00568 
00569   result->mem_buffer = NULL;    
00570   result->rows_in_array = numrows;
00571   result->blocksperrow = blocksperrow;
00572   result->maxaccess = maxaccess;
00573   result->pre_zero = pre_zero;
00574   result->b_s_open = FALSE;     
00575   result->next = mem->virt_barray_list; 
00576   mem->virt_barray_list = result;
00577 
00578   return result;
00579 }
00580 
00581 
00582 METHODDEF(void)
00583 realize_virt_arrays (j_common_ptr cinfo)
00584 
00585 {
00586   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00587   long space_per_minheight, maximum_space, avail_mem;
00588   long minheights, max_minheights;
00589   jvirt_sarray_ptr sptr;
00590   jvirt_barray_ptr bptr;
00591 
00592   
00593 
00594 
00595 
00596   space_per_minheight = 0;
00597   maximum_space = 0;
00598   for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00599     if (sptr->mem_buffer == NULL) { 
00600       space_per_minheight += (long) sptr->maxaccess *
00601                              (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00602       maximum_space += (long) sptr->rows_in_array *
00603                        (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00604     }
00605   }
00606   for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00607     if (bptr->mem_buffer == NULL) { 
00608       space_per_minheight += (long) bptr->maxaccess *
00609                              (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00610       maximum_space += (long) bptr->rows_in_array *
00611                        (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00612     }
00613   }
00614 
00615   if (space_per_minheight <= 0)
00616     return;                     
00617 
00618   
00619   avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
00620                                  mem->total_space_allocated);
00621 
00622   
00623 
00624 
00625 
00626   if (avail_mem >= maximum_space)
00627     max_minheights = 1000000000L;
00628   else {
00629     max_minheights = avail_mem / space_per_minheight;
00630     
00631 
00632 
00633     if (max_minheights <= 0)
00634       max_minheights = 1;
00635   }
00636 
00637   
00638 
00639   for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00640     if (sptr->mem_buffer == NULL) { 
00641       minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
00642       if (minheights <= max_minheights) {
00643         
00644         sptr->rows_in_mem = sptr->rows_in_array;
00645       } else {
00646         
00647         sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
00648         jpeg_open_backing_store(cinfo, & sptr->b_s_info,
00649                                 (long) sptr->rows_in_array *
00650                                 (long) sptr->samplesperrow *
00651                                 (long) SIZEOF(JSAMPLE));
00652         sptr->b_s_open = TRUE;
00653       }
00654       sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
00655                                       sptr->samplesperrow, sptr->rows_in_mem);
00656       sptr->rowsperchunk = mem->last_rowsperchunk;
00657       sptr->cur_start_row = 0;
00658       sptr->first_undef_row = 0;
00659       sptr->dirty = FALSE;
00660     }
00661   }
00662 
00663   for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00664     if (bptr->mem_buffer == NULL) { 
00665       minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
00666       if (minheights <= max_minheights) {
00667         
00668         bptr->rows_in_mem = bptr->rows_in_array;
00669       } else {
00670         
00671         bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
00672         jpeg_open_backing_store(cinfo, & bptr->b_s_info,
00673                                 (long) bptr->rows_in_array *
00674                                 (long) bptr->blocksperrow *
00675                                 (long) SIZEOF(JBLOCK));
00676         bptr->b_s_open = TRUE;
00677       }
00678       bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
00679                                       bptr->blocksperrow, bptr->rows_in_mem);
00680       bptr->rowsperchunk = mem->last_rowsperchunk;
00681       bptr->cur_start_row = 0;
00682       bptr->first_undef_row = 0;
00683       bptr->dirty = FALSE;
00684     }
00685   }
00686 }
00687 
00688 
00689 LOCAL(void)
00690 do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
00691 
00692 {
00693   long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00694 
00695   bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
00696   file_offset = ptr->cur_start_row * bytesperrow;
00697   
00698   for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00699     
00700     rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00701     
00702     thisrow = (long) ptr->cur_start_row + i;
00703     rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00704     
00705     rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00706     if (rows <= 0)              
00707       break;
00708     byte_count = rows * bytesperrow;
00709     if (writing)
00710       (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00711                                             (void FAR *) ptr->mem_buffer[i],
00712                                             file_offset, byte_count);
00713     else
00714       (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00715                                            (void FAR *) ptr->mem_buffer[i],
00716                                            file_offset, byte_count);
00717     file_offset += byte_count;
00718   }
00719 }
00720 
00721 
00722 LOCAL(void)
00723 do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
00724 
00725 {
00726   long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00727 
00728   bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
00729   file_offset = ptr->cur_start_row * bytesperrow;
00730   
00731   for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00732     
00733     rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00734     
00735     thisrow = (long) ptr->cur_start_row + i;
00736     rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00737     
00738     rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00739     if (rows <= 0)              
00740       break;
00741     byte_count = rows * bytesperrow;
00742     if (writing)
00743       (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00744                                             (void FAR *) ptr->mem_buffer[i],
00745                                             file_offset, byte_count);
00746     else
00747       (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00748                                            (void FAR *) ptr->mem_buffer[i],
00749                                            file_offset, byte_count);
00750     file_offset += byte_count;
00751   }
00752 }
00753 
00754 
00755 METHODDEF(JSAMPARRAY)
00756 access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
00757                     JDIMENSION start_row, JDIMENSION num_rows,
00758                     boolean writable)
00759 
00760 
00761 
00762 {
00763   JDIMENSION end_row = start_row + num_rows;
00764   JDIMENSION undef_row;
00765 
00766   
00767   if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00768       ptr->mem_buffer == NULL)
00769     ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00770 
00771   
00772   if (start_row < ptr->cur_start_row ||
00773       end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00774     if (! ptr->b_s_open)
00775       ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00776     
00777     if (ptr->dirty) {
00778       do_sarray_io(cinfo, ptr, TRUE);
00779       ptr->dirty = FALSE;
00780     }
00781     
00782 
00783 
00784 
00785 
00786 
00787 
00788     if (start_row > ptr->cur_start_row) {
00789       ptr->cur_start_row = start_row;
00790     } else {
00791       
00792       long ltemp;
00793 
00794       ltemp = (long) end_row - (long) ptr->rows_in_mem;
00795       if (ltemp < 0)
00796         ltemp = 0;              
00797       ptr->cur_start_row = (JDIMENSION) ltemp;
00798     }
00799     
00800 
00801 
00802 
00803     do_sarray_io(cinfo, ptr, FALSE);
00804   }
00805   
00806 
00807 
00808 
00809   if (ptr->first_undef_row < end_row) {
00810     if (ptr->first_undef_row < start_row) {
00811       if (writable)             
00812         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00813       undef_row = start_row;    
00814     } else {
00815       undef_row = ptr->first_undef_row;
00816     }
00817     if (writable)
00818       ptr->first_undef_row = end_row;
00819     if (ptr->pre_zero) {
00820       size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
00821       undef_row -= ptr->cur_start_row; 
00822       end_row -= ptr->cur_start_row;
00823       while (undef_row < end_row) {
00824         jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00825         undef_row++;
00826       }
00827     } else {
00828       if (! writable)           
00829         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00830     }
00831   }
00832   
00833   if (writable)
00834     ptr->dirty = TRUE;
00835   
00836   return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00837 }
00838 
00839 
00840 METHODDEF(JBLOCKARRAY)
00841 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
00842                     JDIMENSION start_row, JDIMENSION num_rows,
00843                     boolean writable)
00844 
00845 
00846 
00847 {
00848   JDIMENSION end_row = start_row + num_rows;
00849   JDIMENSION undef_row;
00850 
00851   
00852   if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00853       ptr->mem_buffer == NULL)
00854     ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00855 
00856   
00857   if (start_row < ptr->cur_start_row ||
00858       end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00859     if (! ptr->b_s_open)
00860       ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00861     
00862     if (ptr->dirty) {
00863       do_barray_io(cinfo, ptr, TRUE);
00864       ptr->dirty = FALSE;
00865     }
00866     
00867 
00868 
00869 
00870 
00871 
00872 
00873     if (start_row > ptr->cur_start_row) {
00874       ptr->cur_start_row = start_row;
00875     } else {
00876       
00877       long ltemp;
00878 
00879       ltemp = (long) end_row - (long) ptr->rows_in_mem;
00880       if (ltemp < 0)
00881         ltemp = 0;              
00882       ptr->cur_start_row = (JDIMENSION) ltemp;
00883     }
00884     
00885 
00886 
00887 
00888     do_barray_io(cinfo, ptr, FALSE);
00889   }
00890   
00891 
00892 
00893 
00894   if (ptr->first_undef_row < end_row) {
00895     if (ptr->first_undef_row < start_row) {
00896       if (writable)             
00897         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00898       undef_row = start_row;    
00899     } else {
00900       undef_row = ptr->first_undef_row;
00901     }
00902     if (writable)
00903       ptr->first_undef_row = end_row;
00904     if (ptr->pre_zero) {
00905       size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
00906       undef_row -= ptr->cur_start_row; 
00907       end_row -= ptr->cur_start_row;
00908       while (undef_row < end_row) {
00909         jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00910         undef_row++;
00911       }
00912     } else {
00913       if (! writable)           
00914         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00915     }
00916   }
00917   
00918   if (writable)
00919     ptr->dirty = TRUE;
00920   
00921   return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00922 }
00923 
00924 
00925 
00926 
00927 
00928 
00929 METHODDEF(void)
00930 free_pool (j_common_ptr cinfo, int pool_id)
00931 {
00932   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00933   small_pool_ptr shdr_ptr;
00934   large_pool_ptr lhdr_ptr;
00935   size_t space_freed;
00936 
00937   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00938     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); 
00939 
00940 #ifdef MEM_STATS
00941   if (cinfo->err->trace_level > 1)
00942     print_mem_stats(cinfo, pool_id); 
00943 #endif
00944 
00945   
00946   if (pool_id == JPOOL_IMAGE) {
00947     jvirt_sarray_ptr sptr;
00948     jvirt_barray_ptr bptr;
00949 
00950     for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00951       if (sptr->b_s_open) {     
00952         sptr->b_s_open = FALSE; 
00953         (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
00954       }
00955     }
00956     mem->virt_sarray_list = NULL;
00957     for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00958       if (bptr->b_s_open) {     
00959         bptr->b_s_open = FALSE; 
00960         (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
00961       }
00962     }
00963     mem->virt_barray_list = NULL;
00964   }
00965 
00966   
00967   lhdr_ptr = mem->large_list[pool_id];
00968   mem->large_list[pool_id] = NULL;
00969 
00970   while (lhdr_ptr != NULL) {
00971     large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
00972     space_freed = lhdr_ptr->hdr.bytes_used +
00973                   lhdr_ptr->hdr.bytes_left +
00974                   SIZEOF(large_pool_hdr);
00975     jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
00976     mem->total_space_allocated -= space_freed;
00977     lhdr_ptr = next_lhdr_ptr;
00978   }
00979 
00980   
00981   shdr_ptr = mem->small_list[pool_id];
00982   mem->small_list[pool_id] = NULL;
00983 
00984   while (shdr_ptr != NULL) {
00985     small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
00986     space_freed = shdr_ptr->hdr.bytes_used +
00987                   shdr_ptr->hdr.bytes_left +
00988                   SIZEOF(small_pool_hdr);
00989     jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
00990     mem->total_space_allocated -= space_freed;
00991     shdr_ptr = next_shdr_ptr;
00992   }
00993 }
00994 
00995 
00996 
00997 
00998 
00999 
01000 
01001 METHODDEF(void)
01002 self_destruct (j_common_ptr cinfo)
01003 {
01004   int pool;
01005 
01006   
01007 
01008 
01009 
01010   for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01011     free_pool(cinfo, pool);
01012   }
01013 
01014   
01015   jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
01016   cinfo->mem = NULL;            
01017 
01018   jpeg_mem_term(cinfo);         
01019 }
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 GLOBAL(void)
01028 jinit_memory_mgr (j_common_ptr cinfo)
01029 {
01030   my_mem_ptr mem;
01031   long max_to_use;
01032   int pool;
01033   size_t test_mac;
01034 
01035   cinfo->mem = NULL;            
01036 
01037   
01038 
01039 
01040 
01041 
01042 
01043 
01044   if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
01045     ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
01046   
01047 
01048 
01049 
01050 
01051   test_mac = (size_t) MAX_ALLOC_CHUNK;
01052   if ((long) test_mac != MAX_ALLOC_CHUNK ||
01053       (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
01054     ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
01055 
01056   max_to_use = jpeg_mem_init(cinfo); 
01057 
01058   
01059   mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
01060 
01061   if (mem == NULL) {
01062     jpeg_mem_term(cinfo);       
01063     ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
01064   }
01065 
01066   
01067   mem->pub.alloc_small = alloc_small;
01068   mem->pub.alloc_large = alloc_large;
01069   mem->pub.alloc_sarray = alloc_sarray;
01070   mem->pub.alloc_barray = alloc_barray;
01071   mem->pub.request_virt_sarray = request_virt_sarray;
01072   mem->pub.request_virt_barray = request_virt_barray;
01073   mem->pub.realize_virt_arrays = realize_virt_arrays;
01074   mem->pub.access_virt_sarray = access_virt_sarray;
01075   mem->pub.access_virt_barray = access_virt_barray;
01076   mem->pub.free_pool = free_pool;
01077   mem->pub.self_destruct = self_destruct;
01078 
01079   
01080   mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
01081 
01082   
01083   mem->pub.max_memory_to_use = max_to_use;
01084 
01085   for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01086     mem->small_list[pool] = NULL;
01087     mem->large_list[pool] = NULL;
01088   }
01089   mem->virt_sarray_list = NULL;
01090   mem->virt_barray_list = NULL;
01091 
01092   mem->total_space_allocated = SIZEOF(my_memory_mgr);
01093 
01094   
01095   cinfo->mem = & mem->pub;
01096 
01097   
01098 
01099 
01100 
01101 
01102 
01103 #ifndef NO_GETENV
01104   { char * memenv;
01105 
01106     if ((memenv = getenv("JPEGMEM")) != NULL) {
01107       char ch = 'x';
01108 
01109       if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
01110         if (ch == 'm' || ch == 'M')
01111           max_to_use *= 1000L;
01112         mem->pub.max_memory_to_use = max_to_use * 1000L;
01113       }
01114     }
01115   }
01116 #endif
01117 
01118 }