home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 2 / DATAFILE_PDCD2.iso / utilities2 / desklib / Libraries / Mem / c / MidExtend < prev    next >
Encoding:
Text File  |  1993-05-13  |  5.3 KB  |  166 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Mem.MidExtend.c
  12.     Author:  Copyright © 1993 Jason Williams
  13.     Version: 1.00 (12 May 1993)
  14.     Purpose: Dynamic memory manager - reallocation
  15. */
  16.  
  17. #include "MemDefs.h"
  18.  
  19. #include <string.h> 
  20.  
  21.  
  22. extern BOOL Mem_MidExtend(mem_anchor *anchor, int at, int by)
  23. /*  Enlarges or reduces a Mem chunk by moving all data beyond 'at' by
  24.  *  'by' bytes up or down in memory. 'at' is an offset within the chunk.
  25.  *
  26.  *  Goes to rather a lot of effort to avoid moving the base address of
  27.  *  this chunk and others, but if mem_autocompact allows, it will compact
  28.  *  if it is absolutely necessary in order to manage the extension.
  29.  *
  30.  *  Returns TRUE if it succeeds
  31.  */
  32. {
  33.   mem_header *chunk, *next, *prev;
  34.   mem_anchor newchunk;
  35.   int         needed;
  36.   char *database;
  37.  
  38.   if (by == 0 || at < 0 || !Mem__FindChunk(anchor, &chunk))  return(FALSE);
  39.   if (at > chunk->datasize) return(FALSE);
  40.  
  41.   database = ((char *) chunk) + sizeof(mem_header);
  42.  
  43.  
  44.   /* ------ Reduce chunk ------ */
  45.   if (by < 0)                            /* Reducing the size of the chunk   */
  46.   {
  47.     if (-by > at) by = -at;              /* Can't delete past start of chunk */
  48.  
  49.     memmove(database + at + by, database + at, chunk->datasize - at);
  50.     chunk->datasize += by;               /* Shrink data area of this block   */
  51.  
  52.     Mem__SplitOffFreeChunk(chunk);      /* Return any free space for use    */
  53.     /* The anchor has not changed */
  54.     return(TRUE);
  55.   }
  56.  
  57.  
  58.   /* ------ Extend chunk ------ */
  59.   if ((int) chunk > (int) mem__heap) /* Step 1: merge with prevchunk if free */
  60.   {
  61.     prev = Mem__PrevChunk(chunk);
  62.     if (ISFREE(prev))
  63.     {
  64.       int newsize = prev->realsize + chunk->realsize;
  65.  
  66.       /*  Merge this chunk into the previous (free) chunk, shifting the data
  67.        *  down into it.
  68.        */
  69.       memmove((void *) prev, (void *) chunk, chunk->realsize);
  70.       prev->realsize = newsize;
  71.  
  72.       if (chunk == mem__lastchunk)
  73.         mem__lastchunk = prev;
  74.       else
  75.       {
  76.         next = Mem__NextChunk(prev);
  77.         next->prevrealsize = newsize;
  78.       }
  79.       chunk = prev;
  80.       *anchor = (mem_anchor) ((int)chunk + sizeof(mem_header));
  81.     }
  82.   }
  83.  
  84.  
  85.   if (chunk != mem__lastchunk)      /* Step 2: merge with next chunk if free */
  86.   {
  87.     next = Mem__NextChunk(chunk);
  88.     if (ISFREE(next))
  89.     {
  90.       /*  Next chunk is free, so we merge it onto the end of this one */
  91.  
  92.       chunk->realsize += next->realsize;
  93.       if (next == mem__lastchunk)
  94.         mem__lastchunk = chunk;
  95.       else
  96.       {
  97.         next = Mem__NextChunk(chunk);
  98.         next->prevrealsize = chunk->realsize;
  99.       }
  100.     }
  101.   }
  102.  
  103.  
  104.                    /* Step 3: Allocate more heap space if this is last chunk */
  105.   needed = chunk->datasize + by + sizeof(mem_header);
  106.   if (chunk == mem__lastchunk && chunk->realsize < needed)
  107.   {
  108.     /*  Still too small? This is the last chunk in the heap, so just
  109.      *  extend the heap to make enough room. Note that normally we won't
  110.      *  have data in the last chunk, but the previous 2 steps may have
  111.      *  merged another chunk into the last (free) chunk to try to get
  112.      *  enough memory.
  113.      */
  114.     mem__heapsize = Mem__HeapSize(mem__heapsize + 16 +
  115.                                   (needed - chunk->realsize));
  116.     mem__lastchunk->realsize = mem__heap + mem__heapsize - (int)mem__lastchunk;
  117.   }
  118.  
  119.  
  120.   /* Now, is the resulting chunk big enough to hold the extended data? */
  121.   if (chunk->realsize >= needed)
  122.   {
  123.     memmove(database + at + by, database + at, chunk->datasize - at);
  124.     chunk->datasize += by;               /* Expand data area of this block   */
  125.  
  126.     Mem__SplitOffFreeChunk(chunk);      /* Return any free space for use    */
  127.  
  128.     /* The anchor has not changed */
  129.     return(TRUE);
  130.   }
  131.  
  132.   Mem__SplitOffFreeChunk(chunk);        /* Return any free space for use    */
  133.  
  134.   /*  Still unable to extend the chunk.
  135.    *  Check if we can relocate this chunk into a larger one, compacting
  136.    *  if necessary (but only if we are allowed to by mem_autocompact)
  137.    */
  138.  
  139.   Mem_Alloc(&newchunk, chunk->datasize + by);
  140.   if (newchunk == NULL)
  141.   {
  142.     /*  **** Exercise for the reader
  143.      *  We can't just grab another chunk of large enough size.
  144.      *  At this point, we really should (if allowed) compact the
  145.      *  heap, extend the heap if necessary, then shift everything
  146.      *  above 'chunk' up enough to extend the chunk as needed.
  147.      *  However, this takes a bit of effort on my part, and also will
  148.      *  add a large bit of code to this function, so I have not yet
  149.      *  implemented it
  150.      */
  151.  
  152.      return(FALSE);
  153.   }
  154.  
  155.   memmove((char *) newchunk, database, at);         /* Copy 1st part of data */
  156.   memmove((char *) ((int) newchunk) + at + by,      /* Copy 2nd part of data */
  157.           database + at, chunk->datasize - at);
  158.  
  159.   Mem_Free(anchor);
  160.   *anchor = newchunk;
  161.   Mem__FindChunk(&newchunk, &chunk);
  162.   chunk->handle = anchor;
  163.  
  164.   return(TRUE);
  165. }
  166.